Compare commits
	
		
			714 Commits
		
	
	
		
			3.14.4
			...
			wip/garnac
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 9f35b5816a | ||
|   | 63c91f9d4f | ||
|   | aaa02440be | ||
|   | 9611661154 | ||
|   | a70a2c3744 | ||
|   | bc47b19c3f | ||
|   | bc1dd1cee4 | ||
|   | 495c89401a | ||
|   | e2efc85b08 | ||
|   | 020ae58fe4 | ||
|   | 525644059d | ||
|   | f0f638d2bd | ||
|   | bc8ec2d90d | ||
|   | 5b0eabec51 | ||
|   | 50099c4c10 | ||
|   | 55eef2deb3 | ||
|   | f9db65f47f | ||
|   | a809055470 | ||
|   | 247909e161 | ||
|   | e5ce6192f4 | ||
|   | 7adbb58736 | ||
|   | 0165cb6974 | ||
|   | 3cdcd3e9c1 | ||
|   | 6fc51e3723 | ||
|   | af45a50cb1 | ||
|   | 72d6efc0d5 | ||
|   | e0ffef06dd | ||
|   | d5b69bcd54 | ||
|   | ac8fe2d9b2 | ||
|   | e7a88dc6b2 | ||
|   | bcdda506e1 | ||
|   | 9b26694bbc | ||
|   | f053c09083 | ||
|   | ec9abaf1ef | ||
|   | 6b88420465 | ||
|   | fc0a834abb | ||
|   | e30010b9f0 | ||
|   | 935d76ba04 | ||
|   | cc013e1daa | ||
|   | a7a376ae1f | ||
|   | 5e57af6286 | ||
|   | 42b3a34f7b | ||
|   | 19d814c887 | ||
|   | 46eb682c83 | ||
|   | 3aea8d8ce6 | ||
|   | 40c3c69435 | ||
|   | 8071e5b149 | ||
|   | 8a481b3e10 | ||
|   | 50e3e3b929 | ||
|   | 2c7ef2269f | ||
|   | 8bded7d497 | ||
|   | 9ebe3419c3 | ||
|   | 9385c835b8 | ||
|   | efef0c993b | ||
|   | 3a2cd3389a | ||
|   | 88acfb8e60 | ||
|   | 8e22dce5d7 | ||
|   | e0906a77aa | ||
|   | 053f5088df | ||
|   | 75b992c7d0 | ||
|   | 213f0fa160 | ||
|   | 5054b2a99c | ||
|   | d455de32a0 | ||
|   | e7390cff83 | ||
|   | 49ea6486e2 | ||
|   | 996aeaef41 | ||
|   | a27b2597b9 | ||
|   | 0e8ca1a042 | ||
|   | f5f26c9cff | ||
|   | 91ac69382d | ||
|   | 8cc345fcf5 | ||
|   | 96b5042dda | ||
|   | 428c687b5a | ||
|   | 82bdd1e353 | ||
|   | 4bebc5e5fa | ||
|   | be5643cee7 | ||
|   | 2ee1c5fa61 | ||
|   | c625d2ee9d | ||
|   | 3078f70f90 | ||
|   | 7309b20c25 | ||
|   | c16a5ec1cf | ||
|   | f3e1964362 | ||
|   | 9b9083180f | ||
|   | 7606f79a1e | ||
|   | 99c0b82b15 | ||
|   | ca7c1d5e02 | ||
|   | 4a770907c1 | ||
|   | 049f1556dc | ||
|   | 7b20d151ed | ||
|   | 8ec0c99ff4 | ||
|   | cf3ee327a0 | ||
|   | 3ec3cc248d | ||
|   | 7fb3ecc12c | ||
|   | 4c9af7267d | ||
|   | db4355ba1e | ||
|   | 33150569cd | ||
|   | af2a13ded4 | ||
|   | 8b200de35a | ||
|   | 57ae203aab | ||
|   | bff75b64be | ||
|   | 8899b9da01 | ||
|   | 76e816a14f | ||
|   | 2750db2a89 | ||
|   | 86a913d37a | ||
|   | 2857fdbdb8 | ||
|   | 69a7d5ff02 | ||
|   | a4f763ac3b | ||
|   | f2afa7aa6c | ||
|   | a5d2555196 | ||
|   | dd5a4ecdf9 | ||
|   | 43a1d43f2b | ||
|   | d6d377a447 | ||
|   | ffd95c2ad5 | ||
|   | 72be89dfb9 | ||
|   | 2feeb57dee | ||
|   | 9c81b718f9 | ||
|   | 3a63d58d9e | ||
|   | a95ae4d178 | ||
|   | a692fd3808 | ||
|   | 377ecdb864 | ||
|   | d7f544f42e | ||
|   | 1ab8b854df | ||
|   | ae7aabd5de | ||
|   | b975676c5d | ||
|   | 86d8c3954f | ||
|   | 54557f062e | ||
|   | 130807a308 | ||
|   | e84f694668 | ||
|   | b18542f2b6 | ||
|   | da0aac665f | ||
|   | 8b0b0cf028 | ||
|   | 6f64d6b0aa | ||
|   | ebeca983c7 | ||
|   | cf88675807 | ||
|   | 405f1ce3d0 | ||
|   | 6190ae3873 | ||
|   | 69c267b142 | ||
|   | 9abc071283 | ||
|   | a9df4bb81a | ||
|   | bc9e63d3db | ||
|   | 5b5ceede2b | ||
|   | 4e63c95c02 | ||
|   | 67d3a7a2d7 | ||
|   | bc00f118f3 | ||
|   | 5801b5518f | ||
|   | 25a796afc6 | ||
|   | 27b37407d0 | ||
|   | e23e697043 | ||
|   | 35729e8659 | ||
|   | dc7e665de9 | ||
|   | 2e3bfd1a11 | ||
|   | b7aca07844 | ||
|   | dc780d2c44 | ||
|   | c49b284643 | ||
|   | 0373b854c1 | ||
|   | 5d837a5c85 | ||
|   | 79c86ae890 | ||
|   | 7c7cf91c32 | ||
|   | e407f5bbae | ||
|   | 8900bd2f5c | ||
|   | 83c17134f1 | ||
|   | 8e5fb03611 | ||
|   | dece49b53d | ||
|   | 443d579d40 | ||
|   | 5066eaf691 | ||
|   | 6ea7fa9973 | ||
|   | 79f755bf0f | ||
|   | 1845bfe1b6 | ||
|   | 8e22bf5bc9 | ||
|   | c13ddafdb8 | ||
|   | 94513726de | ||
|   | 0aa4c4d43e | ||
|   | e3db4ab16a | ||
|   | 614d6bd0f8 | ||
|   | 1d56d50fcd | ||
|   | 0ffd4254d9 | ||
|   | 36eee04a21 | ||
|   | d3fdaa3232 | ||
|   | 165050f8f9 | ||
|   | 68279e8a08 | ||
|   | cd1ce2cb0a | ||
|   | b01f95cfdd | ||
|   | 4b667d1e09 | ||
|   | fe8454d13f | ||
|   | 53a6d16891 | ||
|   | e76c3ecb00 | ||
|   | 637be80c86 | ||
|   | 975feb9202 | ||
|   | a5417ebee1 | ||
|   | b64b159109 | ||
|   | 804ab7894f | ||
|   | 299ed424d3 | ||
|   | 55692b4019 | ||
|   | 2fafa24305 | ||
|   | 51a2f28723 | ||
|   | e11feb229b | ||
|   | 1ee387bb31 | ||
|   | cba2ab445e | ||
|   | 038f828ab1 | ||
|   | 4dc5882777 | ||
|   | b0b08d5010 | ||
|   | 070cd27786 | ||
|   | 9df6cda3e3 | ||
|   | 39763d4add | ||
|   | 352cac3850 | ||
|   | 9c745105f8 | ||
|   | ab9dabe725 | ||
|   | 7ce06928e2 | ||
|   | ac79988939 | ||
|   | a43a2af18b | ||
|   | 07f533f617 | ||
|   | 10504b0fdc | ||
|   | a84f714808 | ||
|   | b41873dced | ||
|   | 0a9511b24b | ||
|   | 17438ced91 | ||
|   | 27c7512e4d | ||
|   | 124888764d | ||
|   | 7e1c6ff2a2 | ||
|   | 2fb8da0d5a | ||
|   | ad51c52b69 | ||
|   | 1b22da0039 | ||
|   | 8329e97502 | ||
|   | 74ca936a00 | ||
|   | 141760057b | ||
|   | e648f2c244 | ||
|   | f01247d815 | ||
|   | db6caa2c49 | ||
|   | fbd237bc66 | ||
|   | f6c9261bf6 | ||
|   | 14b0a83f64 | ||
|   | 441efd17ce | ||
|   | 208da2316d | ||
|   | 3b993131e8 | ||
|   | 117f57f74c | ||
|   | b97ebc4124 | ||
|   | 5d10196919 | ||
|   | f295349e26 | ||
|   | eb023ff2c9 | ||
|   | ba7c524a18 | ||
|   | dc99af40f3 | ||
|   | 1576b7d5a6 | ||
|   | 6ec7fa2cbd | ||
|   | bede9970de | ||
|   | 5f1bcc124f | ||
|   | 4d3419607a | ||
|   | 7dc0b0e602 | ||
|   | 1545d4e638 | ||
|   | a191554cf6 | ||
|   | b33a82eb7c | ||
|   | 2705c87f74 | ||
|   | 9fc1c919e8 | ||
|   | 9f04c58ffe | ||
|   | 7de1f3a7be | ||
|   | fd443ecf2a | ||
|   | 8979e52a6c | ||
|   | e8dd5601e7 | ||
|   | ccca810daf | ||
|   | 693456b644 | ||
|   | aacc3d5628 | ||
|   | 1ea8efdeda | ||
|   | a3fbbaabe8 | ||
|   | d5d95b2834 | ||
|   | 659b8ed471 | ||
|   | 94bce5a00f | ||
|   | 91b7dedf36 | ||
|   | aa1c819941 | ||
|   | be7e994abd | ||
|   | 6c05eb583e | ||
|   | 5547c98f97 | ||
|   | ea4979e182 | ||
|   | 8da5761ffc | ||
|   | aea71fbd01 | ||
|   | b55f792302 | ||
|   | dd060d78ce | ||
|   | 3fe281ada9 | ||
|   | f041b35b9b | ||
|   | afa58746ea | ||
|   | 6dbec6f81b | ||
|   | 2cbaa6660c | ||
|   | d74b0d5be8 | ||
|   | 6b82f61dba | ||
|   | 4c6866741d | ||
|   | 84baf4e181 | ||
|   | 3962f1d982 | ||
|   | 414be07a69 | ||
|   | 7f3ada7831 | ||
|   | 12771a555a | ||
|   | 92d6a69153 | ||
|   | 734402e14d | ||
|   | 5d360a9bce | ||
|   | f8cf5e373c | ||
|   | 8df3fa4e67 | ||
|   | bbf2b4e60e | ||
|   | bb4dcd62ec | ||
|   | 2345b9c6ad | ||
|   | af7cc87bfa | ||
|   | af3b599cbb | ||
|   | 0e73ceb4bd | ||
|   | 82a7060cdb | ||
|   | 09120132ef | ||
|   | cdac4d0e92 | ||
|   | 6aead0c67c | ||
|   | d593a61b39 | ||
|   | 9747277b7e | ||
|   | 989f9630a4 | ||
|   | daa15d94fd | ||
|   | 999b99a077 | ||
|   | fd0b366a96 | ||
|   | 320e2d452f | ||
|   | 4d5dd01b7d | ||
|   | 103c88bd72 | ||
|   | 64cf87cfe1 | ||
|   | 9f65edd4f5 | ||
|   | ea2496c80a | ||
|   | 0c30ceddbe | ||
|   | 5c9846c53a | ||
|   | 2a8563ab23 | ||
|   | 6a77d9722a | ||
|   | ef296031cb | ||
|   | e2d6028924 | ||
|   | 4d80a4cc31 | ||
|   | 4a968c3b4e | ||
|   | ccb7833e99 | ||
|   | b449ba942a | ||
|   | f53eea2c1c | ||
|   | b62db404ee | ||
|   | 90a28e7b1c | ||
|   | 8d51a9db5b | ||
|   | b39c00f344 | ||
|   | 83ce71c3bf | ||
|   | f9d869a3dd | ||
|   | 0b0ce4193f | ||
|   | 719d8bd0c7 | ||
|   | 4fc1811c15 | ||
|   | 4b5f5abb4f | ||
|   | 95ad52ba58 | ||
|   | dac30a222e | ||
|   | 7d1b593fbd | ||
|   | d6a7559750 | ||
|   | cff5ef0ec2 | ||
|   | d478d8f143 | ||
|   | 7eca43cec9 | ||
|   | 9060190555 | ||
|   | 0de3869656 | ||
|   | 9f13033f15 | ||
|   | 48bf807430 | ||
|   | c68e43a97f | ||
|   | cc53d48fa8 | ||
|   | ca6e799b97 | ||
|   | 0f8e387dc0 | ||
|   | d62c595e51 | ||
|   | dd3cf94744 | ||
|   | eb56e0a3d7 | ||
|   | 8937c32cd5 | ||
|   | a8a5da768a | ||
|   | 33bfcf56ce | ||
|   | 40cccb58a5 | ||
|   | eb6c70137b | ||
|   | df3b412a25 | ||
|   | cfba0a5dfc | ||
|   | 3561b46fc6 | ||
|   | 8dfb88b669 | ||
|   | 2e3086e2aa | ||
|   | f424056fea | ||
|   | cfb7297cf1 | ||
|   | 8769b3d554 | ||
|   | f8b82c376c | ||
|   | 868e1427a8 | ||
|   | 4aa74af694 | ||
|   | f3fecd478d | ||
|   | a5d1f67c34 | ||
|   | 102fa0e373 | ||
|   | dbca3337b2 | ||
|   | 939f7ce781 | ||
|   | c6e6ed87c5 | ||
|   | 8188cddcf7 | ||
|   | 9f17c05a15 | ||
|   | c3455b01af | ||
|   | d4e8d97e58 | ||
|   | a86368dcb1 | ||
|   | a13f906ed1 | ||
|   | f9e91bf007 | ||
|   | 7c5fe42835 | ||
|   | e76decbcf2 | ||
|   | aac5a5dcaf | ||
|   | 9b3186f8a5 | ||
|   | 4917e367d5 | ||
|   | 955c3c7c71 | ||
|   | 8821162aef | ||
|   | 0356f7afb3 | ||
|   | ba6fa54fdd | ||
|   | b2d4ecab30 | ||
|   | 882a222d5c | ||
|   | 7b79c44608 | ||
|   | 580483d516 | ||
|   | 57c1078ee7 | ||
|   | 3a2920d4bc | ||
|   | ad13fa3bb3 | ||
|   | 9b50119d31 | ||
|   | 3ff6316562 | ||
|   | 43058a3698 | ||
|   | 8c16ac47c1 | ||
|   | 6880cae3fb | ||
|   | 4fc684b2ed | ||
|   | d63b9a1797 | ||
|   | 72bd934604 | ||
|   | ed70e99b7b | ||
|   | 6d72b7c017 | ||
|   | 656fe49dbe | ||
|   | 3471ef3441 | ||
|   | af9d8f1931 | ||
|   | a30ca3e62f | ||
|   | 9e3bac0237 | ||
|   | 67a30b7a89 | ||
|   | 68ba45bcb2 | ||
|   | 6bacbac656 | ||
|   | 87e52b18c2 | ||
|   | 637cc9269d | ||
|   | fcdd1944a4 | ||
|   | 5636784604 | ||
|   | 9a3b178da1 | ||
|   | a1488005b6 | ||
|   | cca68b31b1 | ||
|   | 85452aff4f | ||
|   | d9d83abae2 | ||
|   | 0bc6cb2aeb | ||
|   | d628cce058 | ||
|   | b646e25fee | ||
|   | 94c3c8f412 | ||
|   | d3988c04d6 | ||
|   | dd0cb55997 | ||
|   | aef27647a0 | ||
|   | 18f958d06d | ||
|   | 3efbb96119 | ||
|   | e5d97666af | ||
|   | 83d7e932d6 | ||
|   | f858f66fe0 | ||
|   | fffb863f37 | ||
|   | adf7c0e730 | ||
|   | bbcee174ce | ||
|   | 9c6e6ea381 | ||
|   | db9645fcb3 | ||
|   | 6af48d75a4 | ||
|   | 6234f7d1db | ||
|   | 301a65e05a | ||
|   | 376d4911b6 | ||
|   | 0559d2c19f | ||
|   | 54e482bc7b | ||
|   | 37c3b79551 | ||
|   | 78d8525699 | ||
|   | 23c00688b4 | ||
|   | 438410c22c | ||
|   | 59f348eb11 | ||
|   | cbad65f657 | ||
|   | 1e8e107dd9 | ||
|   | 8631bf2bbb | ||
|   | b9b41c20a6 | ||
|   | 2d3deccd8e | ||
|   | 68289a5d61 | ||
|   | adccbc9b7b | ||
|   | 94b111cf6c | ||
|   | 7303955618 | ||
|   | 5e8bb9cc9d | ||
|   | accfdf7936 | ||
|   | c215247a6c | ||
|   | 96b202c80d | ||
|   | 0ac2f61a2c | ||
|   | 2aa6dcd9d8 | ||
|   | 469b85eb7c | ||
|   | 673ddfde04 | ||
|   | 56ca7eeb65 | ||
|   | b414955230 | ||
|   | af9072e725 | ||
|   | 9b903e93e3 | ||
|   | 7966f00a18 | ||
|   | 9a99a80710 | ||
|   | be77874ec9 | ||
|   | 768286bffb | ||
|   | f5c65d9ea1 | ||
|   | f328890ed1 | ||
|   | 945bf626c6 | ||
|   | f6869bbbc2 | ||
|   | eafe11a7cf | ||
|   | daba1b511b | ||
|   | 87a13d2c00 | ||
|   | 11a9b4baa0 | ||
|   | de71fd0941 | ||
|   | 87c973c260 | ||
|   | 644ab0e270 | ||
|   | 3142220443 | ||
|   | 1f0ed5483a | ||
|   | 72f5a36522 | ||
|   | 7f19db1f7b | ||
|   | 3f2d658f20 | ||
|   | 05353c1f7e | ||
|   | 4d23e7c202 | ||
|   | ad90b7dd2f | ||
|   | 3356a43c04 | ||
|   | 3a5a647d49 | ||
|   | a2ff8f4e1e | ||
|   | e294f6df8c | ||
|   | 422ddeddb9 | ||
|   | 8ef48a99ae | ||
|   | 9d7af8a5fc | ||
|   | 764c3dd137 | ||
|   | 7e7c8ecbd4 | ||
|   | d561b3b18f | ||
|   | ce14bde08d | ||
|   | b91461ee39 | ||
|   | 22c13b3144 | ||
|   | 0bfebc3cae | ||
|   | db384a656c | ||
|   | 1dea1813b1 | ||
|   | 71c4138933 | ||
|   | 9d73b4efbb | ||
|   | 049f67df0a | ||
|   | 2d878d3f55 | ||
|   | 3c06f2dc90 | ||
|   | 460e1fd7ca | ||
|   | f083935c6e | ||
|   | 5c66bee84b | ||
|   | ef32bbdc99 | ||
|   | 5f91a62f6f | ||
|   | 152b2dab59 | ||
|   | 625d3de2ee | ||
|   | f71315eb1e | ||
|   | 0484ef142d | ||
|   | 6609d9c6a4 | ||
|   | 73c4342580 | ||
|   | 0d5c24f13d | ||
|   | b6d070b06f | ||
|   | 87eb5f8632 | ||
|   | 5c60ea6635 | ||
|   | 9abcf424b8 | ||
|   | cc7af83f8a | ||
|   | ae91a174e9 | ||
|   | 9c73e21113 | ||
|   | a1d8110221 | ||
|   | 9d6357f05a | ||
|   | 1fc58faff9 | ||
|   | fea7ac84ee | ||
|   | 20bee6f48e | ||
|   | fb5c0c3352 | ||
|   | 5bc2bcd109 | ||
|   | d12390002a | ||
|   | 13acf9e35d | ||
|   | 3beb187cac | ||
|   | a3b8dcbd04 | ||
|   | 3ff8b0051d | ||
|   | a8bf7934fb | ||
|   | 7159845c6e | ||
|   | 7bccd4f22f | ||
|   | e4e00b383e | ||
|   | 36454542ae | ||
|   | 34ba868b4c | ||
|   | 274ea76eea | ||
|   | a180e8b87e | ||
|   | 26c8086190 | ||
|   | 34fbca0181 | ||
|   | 4496fb4447 | ||
|   | 7e66d2a484 | ||
|   | 12135afa5e | ||
|   | cac660a5bc | ||
|   | dcce4e64bc | ||
|   | 4d3511649b | ||
|   | d4ea2bbd9c | ||
|   | f303ec2eaa | ||
|   | 2ca4ed6b04 | ||
|   | a5ad89dd65 | ||
|   | 4a4d724e59 | ||
|   | 8fdbae192a | ||
|   | 2413e672c8 | ||
|   | c8432cc430 | ||
|   | 015864da09 | ||
|   | 669c9da2a4 | ||
|   | 4d1d8e831e | ||
|   | 9e199e6350 | ||
|   | 4673d8f245 | ||
|   | 90111c03a1 | ||
|   | 23681800d9 | ||
|   | b47afe89d3 | ||
|   | af7f51b992 | ||
|   | f3d30d897f | ||
|   | dcc4ce4ff4 | ||
|   | b9fb4a5887 | ||
|   | d9985cd9bc | ||
|   | 6e3f7b7ddc | ||
|   | 2dd1f37820 | ||
|   | 57af975154 | ||
|   | c5940580ed | ||
|   | 8296d4cdce | ||
|   | bf9a00d5c9 | ||
|   | c1db9d9181 | ||
|   | 9d2cd8ff87 | ||
|   | d514e8ab41 | ||
|   | 44a60eb7e9 | ||
|   | 6b92b45021 | ||
|   | ee461b5495 | ||
|   | 46f3eb0b71 | ||
|   | ef32899b4d | ||
|   | 5e9db422c9 | ||
|   | 662dd6a289 | ||
|   | d5e6177900 | ||
|   | 34ac80348c | ||
|   | 8a7a01b0cf | ||
|   | 2cabc067d1 | ||
|   | 26c4c21e13 | ||
|   | 6eda784cf0 | ||
|   | fb1459062f | ||
|   | bc9547f29e | ||
|   | 89a371ec98 | ||
|   | 2db71e73b4 | ||
|   | 472f2a4b8e | ||
|   | db04ac9eb7 | ||
|   | 75105e254f | ||
|   | 901a05ad80 | ||
|   | ab6c4c82f6 | ||
|   | cacb32482c | ||
|   | 4450b5bb14 | ||
|   | 34421e90c3 | ||
|   | 93b7137c62 | ||
|   | 5ad15bb5e5 | ||
|   | cd4206764e | ||
|   | b10a017446 | ||
|   | d393cba39e | ||
|   | 578f593d56 | ||
|   | 55df99447a | ||
|   | d45080d32e | ||
|   | fa97364fa8 | ||
|   | 41303101e5 | ||
|   | 68542ae1ef | ||
|   | 0c730d8feb | ||
|   | aeef98fd19 | ||
|   | 69079b3b48 | ||
|   | ad7292faef | ||
|   | 2f7843b295 | ||
|   | b24cd5ae08 | ||
|   | c782078e00 | ||
|   | 5a86286aba | ||
|   | b1ac83d3b6 | ||
|   | e73f5cc8ab | ||
|   | 593b417e5e | ||
|   | 5e84c8f20b | ||
|   | 9745f9f8ce | ||
|   | 99f7be33ad | ||
|   | 6492845f27 | ||
|   | fd1243d881 | ||
|   | 00535b34b6 | ||
|   | a2b2a7a26f | ||
|   | 9fdf487da1 | ||
|   | c5033616e9 | ||
|   | a0e038f34b | ||
|   | 71dab32769 | ||
|   | c408cf7aac | ||
|   | e96eb0e82e | ||
|   | 0015963457 | ||
|   | b832bc7424 | ||
|   | 89b14babb9 | ||
|   | 7ecde19aee | ||
|   | d7854794cf | ||
|   | f6f5f624d4 | ||
|   | 7012c82fc7 | ||
|   | a0d2d207e7 | ||
|   | 6e25c37da1 | ||
|   | 061f434201 | ||
|   | 638087fe78 | ||
|   | 286a6ada5a | ||
|   | cb66ab5a87 | ||
|   | e72c6916aa | ||
|   | 8b98cb818c | ||
|   | f8a4d450a5 | ||
|   | 681cf95236 | ||
|   | 90d6734f8c | ||
|   | 213cd8a334 | ||
|   | 3b1271d9be | ||
|   | 13b6bd20ca | ||
|   | 63e31af476 | ||
|   | 718a89eb2f | ||
|   | a43ca7b5b1 | ||
|   | af00ca534a | ||
|   | 4b2b431700 | ||
|   | 2c1a6b6a12 | ||
|   | b3544f8ec1 | ||
|   | df384965c3 | ||
|   | 700d367937 | ||
|   | 7c5989c978 | ||
|   | 8819d9ce66 | ||
|   | b63413e5b0 | ||
|   | cd1e1d4bf1 | ||
|   | 9710c013c5 | ||
|   | 05f8d79323 | ||
|   | f2546dfeea | ||
|   | 47e339b46e | ||
|   | 016b8f5b4a | ||
|   | b3821c4f90 | ||
|   | 29e5c6c363 | ||
|   | e1704acda4 | ||
|   | 60cbb41f42 | ||
|   | d88c8d9ced | ||
|   | 60ab11ecbf | ||
|   | 34516aeab6 | ||
|   | a37f632b1b | ||
|   | 8a6542c242 | ||
|   | 7e12000d97 | ||
|   | 23f086da8a | ||
|   | 4c2c1c4dd2 | ||
|   | 545f298921 | ||
|   | 64295e8cd7 | ||
|   | 722d4c6c17 | ||
|   | cc8462969d | ||
|   | 989bb6ebb1 | ||
|   | 1dbda68839 | ||
|   | a460f88b31 | 
							
								
								
									
										18
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										18
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -57,19 +57,21 @@ testgradient | ||||
| m4/* | ||||
| INSTALL | ||||
| mkinstalldirs | ||||
| src/mutter-enum-types.[ch] | ||||
| src/stamp-mutter-enum-types.h | ||||
| src/mutter-marshal.[ch] | ||||
| src/stamp-mutter-marshal.h | ||||
| meta-enum-types.[ch] | ||||
| src/stamp-meta-enum-types.h | ||||
| src/meta-dbus-display-config.[ch] | ||||
| src/meta-dbus-idle-monitor.[ch] | ||||
| src/meta-dbus-login1.[ch] | ||||
| src/gtk-shell-protocol.c | ||||
| src/gtk-shell-server-protocol.h | ||||
| src/xdg-shell-protocol.c | ||||
| src/xdg-shell-server-protocol.h | ||||
| src/xserver-protocol.c | ||||
| src/xserver-server-protocol.h | ||||
| src/xdg-shell-unstable-v*-protocol.c | ||||
| src/xdg-shell-unstable-v*-server-protocol.h | ||||
| src/pointer-gestures-unstable-v*-protocol.c | ||||
| src/pointer-gestures-unstable-v*-server-protocol.h | ||||
| src/relative-pointer-unstable-v*-protocol.c | ||||
| src/relative-pointer-unstable-v*-server-protocol.h | ||||
| src/pointer-constraints-unstable-v*-protocol.c | ||||
| src/pointer-constraints-unstable-v*-server-protocol.h | ||||
| src/meta/meta-version.h | ||||
| doc/reference/*.args | ||||
| doc/reference/*.bak | ||||
|   | ||||
| @@ -9,5 +9,3 @@ DISTCLEANFILES = \ | ||||
| 	intltool-update \ | ||||
| 	po/stamp-it \ | ||||
| 	po/.intltool-merge-cache | ||||
|  | ||||
| DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc | ||||
|   | ||||
							
								
								
									
										333
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										333
									
								
								NEWS
									
									
									
									
									
								
							| @@ -1,44 +1,321 @@ | ||||
| 3.14.4 | ||||
| 3.19.4 | ||||
| ====== | ||||
| * Fix flash on unredirection [Chris; #743858] | ||||
| * Fix incompatibility with GLES2 GLSL [Alban; #745442] | ||||
| * Add function to refresh all background instances [Rui; #739178] | ||||
| * Fix geometry of shaded windows [Florian; #746145] | ||||
| * Misc. bug fixes [Florian, Rui; #698995, #743217, #743254] | ||||
| * Fix updating stacking order when setting transient_for [Jonas; #755606] | ||||
| * Support screen rotation when supported by the driver [Carlos; #745079] | ||||
| * Protect against broken WM_CLASS property implementations [Sebastian; #759658] | ||||
| * Handle wl_pointer v5 events on wayland [Carlos; #760637] | ||||
| * Implement DND actions on wayland [Carlos; #760805] | ||||
| * Misc. bug fixes [Jonas, Rui, Ray, Marek; #754711, #756789, #759297, #758613, | ||||
|   #760330, #760476, #759222, #760670] | ||||
|  | ||||
| Contributors: | ||||
|   Alban Browaeys, Rui Matos, Florian Müllner, Chris Wilson | ||||
|   Jonas Ådahl, Marek Chalupa, Carlos Garnacho, Sebastian Keller, Rui Matos, | ||||
|   Florian Müllner, Jasper St. Pierre, Ray Strode | ||||
|  | ||||
| Translations: | ||||
|   Matej Urbančič [sl], Muhammet Kara [tr], Samir Ribic [bs] | ||||
|   Aurimas Černius [lt] | ||||
|  | ||||
| 3.14.3 | ||||
| 3.19.3 | ||||
| ====== | ||||
| * Correct refresh rate units on KMS/Wayland [Daniel; #758653] | ||||
| * Fix crash when initial cursor position is not on a monitor [Marek; #756698] | ||||
| * Fix crash when more CRTs are enabled than outputs connected [Rui; #751638] | ||||
| * Fix touch pointer emulation on wayland [Carlos; #756754] | ||||
| * Allow minimizing windows that don't advertise supporting it [Jasper; #758186] | ||||
| * Force 2-finger scroll by default if available [Bastien; #759304] | ||||
| * Fix crash during XWayland initialization [Marek; #751845] | ||||
| * Ensure to send a ConfigureNotify to just mapped windows [Rui; #759492] | ||||
| * Misc. bug fixes and cleanups [Carlos, Jonas, Lionel; #758239, #758633, | ||||
|   #755503, #759374] | ||||
|  | ||||
| Contributors: | ||||
|   Jonas Ådahl, Marek Chalupa, Carlos Garnacho, Lionel Landwerlin, Rui Matos, | ||||
|   Bastien Nocera, Daniel Stone, Jasper St. Pierre | ||||
|  | ||||
| 3.19.2 | ||||
| ====== | ||||
| * Fix crash on monitor unplug [Rui; #756796] | ||||
| * Exit cleanly on initialization errors [Owen; #757311] | ||||
| * Allow to determine backend setting from session type [Ray; #741666] | ||||
| * Fix DRM device detection for non-PCI devices [Alban; #754911] | ||||
| * Don't force placement of windows without buffer on wayland [Marek; #751887] | ||||
| * Fix initialization of bypass compositor hint [Rui; #758544] | ||||
|  | ||||
| Contributors: | ||||
|   Alban Browaeys, Marek Chalupa, Rui Matos, Florian Müllner, Ray Strode, | ||||
|   Owen W. Taylor | ||||
|  | ||||
| 3.19.1 | ||||
| ====== | ||||
| * wayland: Allow to trigger popups through keyboard/touch [Carlos; #756296] | ||||
| * Fix modifiers-only input source switching on Ubuntu [Alberts; #756543] | ||||
| * Misc. bug fixes [Jonas, Rui, Giovanni, Florian; #756675, #756660, #746420, | ||||
|   #756548, #756796, #757101, #757148] | ||||
|  | ||||
| Contributors: | ||||
|   Jonas Ådahl, Giovanni Campagna, Carlos Garnacho, Rui Matos, | ||||
|   Alberts Muktupāvels, Florian Müllner | ||||
|  | ||||
| Translations: | ||||
|   Daniel Șerbănescu [ro] | ||||
|  | ||||
| 3.18.1 | ||||
| ====== | ||||
| * Misc. crash fixes [Jonas, Rui, Carlos, Owen, Florian; #755096, #754979, | ||||
|   #755490, #754357, #745785, #756642] | ||||
| * Improve HiDPI support on wayland [Jonas; #755097] | ||||
| * Fix doubly-scaled cursor on XWayland HiDPI [Jonas; #755099] | ||||
| * Stop hiding titlebar buttons in dialogs [Florian; #641630] | ||||
| * Add support for fullscreen/unfullscreen animations [Cosimo; #707248] | ||||
| * Misc. bug fixes [Rui, Colin, Florian; #743339, #752047, #756074, #756649] | ||||
|  | ||||
| Contributors: | ||||
|   Jonas Ådahl, Cosimo Cecchi, Carlos Garnacho, Rui Matos, Florian Müllner, | ||||
|   Jasper St. Pierre, Colin Walters, Owen W. Taylor | ||||
|  | ||||
| 3.18.0 | ||||
| ====== | ||||
| * Misc. fixes [Florian, Jonas; #753434] | ||||
|  | ||||
| Contributors: | ||||
|   Jonas Ådahl, Florian Müllner | ||||
|  | ||||
| Translations: | ||||
|   Rūdolfs Mazurs [lv] | ||||
|  | ||||
| 3.17.92 | ||||
| ======= | ||||
| * Don't omit the background color for backgrounds that don't fill the screen | ||||
|   [Ray; #754476] | ||||
| * Fix up key state on FocusIn when running nested [Owen; #753948] | ||||
| * Find the right DRM device instead of hardcoding card0 [Marek; #753434] | ||||
| * Scale cursor on HiDPI screens [Jonas; #744932] | ||||
| * Misc. fixes and cleanups [Lan, Jonas, Javier, Olivier; #754545, #754215, | ||||
|   #754621, #754715] | ||||
|  | ||||
| Contributors: | ||||
|   Jonas Ådahl, Marek Chalupa, Olivier Fourdan, Javier Jardón, Ting-Wei Lan, | ||||
|   Ray Strode, Owen W. Taylor | ||||
|  | ||||
| 3.17.91 | ||||
| ======= | ||||
| * Send error on pointer-gesture protocol version mismatch [Jonas; #753855] | ||||
| * Misc. cleanups [Jonas; #744932] | ||||
|  | ||||
| Contributors: | ||||
|   Jonas Ådahl | ||||
|  | ||||
| Translations: | ||||
|   Chao-Hsiung Liao [zh_TW], Piotr Drąg [pl] | ||||
|  | ||||
| 3.17.90 | ||||
| ======= | ||||
| * Fix glitch with some fullscreen apps [Rui; #753020] | ||||
| * Fix screen update issue with NVidia driver [Aaron, Rui; #728464] | ||||
| * Only call frame callbacks for surfaces that get drawn [Adel; #739163] | ||||
| * Misc. bug fixes and cleanups [Jonas, Rui, Ting-Wei; #753222, #752753, #753237, | ||||
|   #753380, #744104, #744932] | ||||
|  | ||||
| Contributors: | ||||
|   Jonas Ådahl, Adel Gadllah, Carlos Garnacho, Ting-Wei Lan, Rui Matos, | ||||
|   Florian Müllner, Aaron Plattner, Jasper St. Pierre | ||||
|  | ||||
| Translations: | ||||
|   Akom Chotiphantawanon [th] | ||||
|  | ||||
| 3.17.4 | ||||
| ====== | ||||
| * nested: Allow basic configuration of dummy outputs [Jonas; #747089] | ||||
| * Send wl_surface.enter and wl_surface.leave on output changes [Jonas; #744453] | ||||
| * Improve HiDPI handling on wayland [Jonas; #745655, #744934] | ||||
| * Implement compositor-side animated cursors [Carlos; #752342] | ||||
| * Misc. bug fixes [Peter, Marek, Carlos, Matthias, Rui; #750816, #751884, | ||||
|   #752248, #752551, #752552, #752673, #752674] | ||||
|  | ||||
| Contributors: | ||||
|   Jonas Ådahl, Marek Chalupa, Matthias Clasen, Carlos Garnacho, Peter Hutterer, | ||||
|   Rui Matos, Florian Müllner, Jasper St. Pierre | ||||
|  | ||||
| 3.17.3 | ||||
| ====== | ||||
| * Add X11/wayland clipboard interaction [Carlos; #738312] | ||||
| * Support VM monitor layout hints on wayland [Thomas; #750363] | ||||
| * Misc. bug fixes [Rui, Jonas, Olivier, Carlos, Ting-Wei, Peter, Florian; | ||||
|   #749994, #750256, #749716, #748705, #750552, #751036, #750007, #751136, | ||||
|   #750552, #751471, #751715, #750680] | ||||
|  | ||||
| Contributors: | ||||
|   Jonas Ådahl, Dave Airlie, Cosimo Cecchi, Olivier Fourdan, Carlos Garnacho, | ||||
|   Thomas Hellstrom, Peter Hutterer, Ting-Wei Lan, Jasper Lievisse Adriaanse, | ||||
|   Rui Matos, Florian Müllner, Jasper St. Pierre | ||||
|  | ||||
| Translations: | ||||
|   Marek Černocký [cs], Christian Kirbach [de], Pedro Albuquerque [pt] | ||||
|  | ||||
| 3.17.2 | ||||
| ====== | ||||
| * Honor default value for click method setting [Rui; #746290] | ||||
| * Add X11/wayland clipboard interoperation [Carlos; #738312] | ||||
| * Misc. bug fixes [Rui; #749076, #749711] | ||||
|  | ||||
| Contributors: | ||||
|   Carlos Garnacho, Rui Matos, Jasper St. Pierre | ||||
|  | ||||
| 3.17.1 | ||||
| ====== | ||||
| * Add public method to get neighboring monitor [Florian; #633994] | ||||
| * Apply the right settings to the right input devices [Carlos; #747886] | ||||
| * Fix scroll button setting [Ondrej; #747967] | ||||
| * Add support for modal hint on wayland [Jonas; #745720] | ||||
| * Don't reset idle time for non-hardware events [Rui; #748541] | ||||
| * Misc. bug fixes [Ray, Rui; #748380, #748478] | ||||
|  | ||||
| Contributors: | ||||
|   Jonas Ådahl, Carlos Garnacho, Ondrej Holy, Rui Matos, Florian Müllner, | ||||
|   Jasper St. Pierre, Ray Strode, Tomeu Vizoso | ||||
|  | ||||
| 3.16.1 | ||||
| ====== | ||||
| * Add function to refresh all background instances [Rui; #739178] | ||||
| * Fix swapped scroll methods on wayland [Ondrej; #746870] | ||||
| * Manually activate stage to fix accessibility on wayland [Ray, Rui; #746670] | ||||
| * Center pointer on primary monitor on startup [Carlos; #746896] | ||||
| * wayland: Reword synchronized state application semantics [Jonas; #743617] | ||||
| * Ensure input settings are applied on startup [Rui; #747434] | ||||
| * Misc. bug fixes [Jonas, Giovanni, Calvin, Ray, Rui; #744932, #746509, #746692, | ||||
|   #746510, #746545, #747263] | ||||
|  | ||||
| Contributors: | ||||
|   Jonas Ådahl, Giovanni Campagna, Carlos Garnacho, Ondrej Holy, Rui Matos, | ||||
|   Jasper St. Pierre, Ray Strode, Calvin Walton | ||||
|  | ||||
| Translations: | ||||
|   Khaled Hosny [ar], Marek Černocký [cs] | ||||
|  | ||||
| 3.16.0 | ||||
| ====== | ||||
| * wayland: Don't skip notifying about initial maximized state [Jonas; #745303] | ||||
|  | ||||
| Contributors: | ||||
|   Jonas Ådahl | ||||
|  | ||||
| Translations: | ||||
|   Kjartan Maraas [nb], Jiri Grönroos [fi], Andika Triwidada [id], | ||||
|   Inaki Larranaga Murgoitio [eu], Ask H. Larsen [da], Muhammet Kara [tr] | ||||
|  | ||||
| 3.15.92 | ||||
| ======= | ||||
| * Ensure pointer visibility on monitor changes [Rui, Marek; #745121, #745752] | ||||
| * Fix geometry of shaded windows [Florian; #746145] | ||||
| * Take over cursor visibility handling from gsd [Carlos; #712775] | ||||
| * Fix touch interaction on window decorations [Carlos; #745335] | ||||
| * Add options for libinput_config_click_method [Carlos; #746290] | ||||
| * Scale window decorations on HiDPI displays [Florian; #744354] | ||||
| * Misc. bug fixes [Carlos, Ray, Rui; #745163, #746295, #746098, #745734] | ||||
|  | ||||
| Contributors: | ||||
|   Marek Chalupa, Carlos Garnacho, Rui Matos, Florian Müllner, | ||||
|   Jasper St. Pierre, Ray Strode | ||||
|  | ||||
| Translations: | ||||
|   Piotr Drąg [pl], Milo Casagrande [it], Changwoo Ryu [ko], | ||||
|   Daniel Korostil [uk], Baurzhan Muftakhidinov [kk], Trần Ngọc Quân [vi], | ||||
|   Alexander Shopov [bg], Jordi Mas [ca], Samir Ribic [bs], A S Alam [pa], | ||||
|   Matej Urbančič [sl] | ||||
|  | ||||
| 3.15.91 | ||||
| ======= | ||||
| * wayland: Fix nested compositor mode [Jonas; #745401] | ||||
| * wayland: Fix pointer constraining [Marek; #727337] | ||||
| * wayland: Fix input region on HiDPI [Jonas; #744933] | ||||
| * Allow themes to style buttons differently based on function [Horst; #745108] | ||||
| * Misc. bug fixes and cleanups [Ray, Rui, Alban; #745141, #745118, #745476, | ||||
|   #745442] | ||||
|  | ||||
| Contributors: | ||||
|   Jonas Ådahl, Alban Browaeys, Marek Chalupa, Horst, Rui Matos, | ||||
|   Jasper St. Pierre, Ray Strode | ||||
|  | ||||
| Translations: | ||||
|   Chao-Hsiung Liao [zh_TW], Efstathios Iosifidis [el], Dušan Kazik [sk], | ||||
|   Balázs Úr [hu], Daniel Mustieles [es], Claude Paroz [fr], Stas Solovey [ru], | ||||
|   Yosef Or Boczko [he], Rafael Ferreira [pt_BR], Aurimas Černius [lt], | ||||
|   Fran Dieguez [gl], Anders Jonsson [sv], Мирослав Николић [sr, sr@latin] | ||||
|  | ||||
| 3.15.90 | ||||
| ======= | ||||
| * Initialize MetaOutput even when we can't get the EDID [Rui; #743412] | ||||
| * Expose MetaMonitorManager to introspection [Rui; #743745] | ||||
| * Fix flash on unredirection [Chris; #743858] | ||||
| * Update xdg-shell implementation to v5 [Jonas; #744452] | ||||
| * Do not try to use seat devices that aren't (yet) present [Ray; #744640] | ||||
| * Add keybindings for switching to VT8-VT12 [Ray; #744800] | ||||
| * Misc bug fixes [Jonas, Cosimo; #743678, #744500] | ||||
|  | ||||
| Contributors: | ||||
|   Jonas Ådahl, Cosimo Cecchi, Carlos Garnacho, Rui Matos, Jasper St. Pierre, | ||||
|   Ray Strode, Chris Wilson | ||||
|  | ||||
| Translations: | ||||
|   Yosef Or Boczko [he], Yuri Myasoedov [ru], Kristjan SCHMIDT [eo], | ||||
|   Matej Urbančič [sl], Dušan Kazik [sk] | ||||
|  | ||||
| 3.15.4 | ||||
| ====== | ||||
| * Use GTK+ theme for window decorations instead of metacity [Florian; #741917] | ||||
| * Export the same EDID information on X11 and wayland [Carlos; #742882] | ||||
| * Apply input device configuration on wayland [Carlos; #739397] | ||||
| * Implement pointer barriers on wayland [Jonas; #706655] | ||||
| * Misc. bug fixes (Ting-Wei, Rui, Ikey, Florian, Marek, Jonas; #741829, | ||||
|   #738630, #737463, #698995, #727893, #742825, #742824, #742841, #743173, | ||||
|   #743189, #743217, #743254] | ||||
|  | ||||
| Contributors: | ||||
|   Jonas Ådahl, Giovanni Campagna, Marek Chalupa, Ikey Doherty, Adel Gadllah, | ||||
|   Carlos Garnacho, Ting-Wei Lan, Rui Matos, Florian Müllner, Jasper St. Pierre, | ||||
|   Rico Tzschichholz | ||||
|  | ||||
| Translations: | ||||
|   Matej Urbančič [sl], Balázs Úr [hu], Marek Černocký [cs], | ||||
|   Inaki Larranaga Murgoitio [eu], Rafael Ferreira [pt_BR], | ||||
|   Daniel Mustieles [es], Fran Dieguez [gl] | ||||
|  | ||||
| 3.15.3 | ||||
| ====== | ||||
| * Fix crash when trying to unredirect a destroyed window [Florian; #740133] | ||||
| * Fix "flicker" during startup transition [Ray; #740377] | ||||
| * Don't leave left-over frames queued [Owen; #738686] | ||||
| * Set CRTC configuration even if it might be redundant [Rui; #740838] | ||||
|  | ||||
| Contributors: | ||||
|   Rui Matos, Florian Müllner, Jasper St. Pierre, Ray Strode, Owen W. Taylor | ||||
|  | ||||
| 3.14.2 | ||||
| ====== | ||||
| * Prevent crash applying monitor config for a closed lid [Rui; #739450] | ||||
| * Misc. fixes [Rui, Jonathon, Jasper; #738630] | ||||
|  | ||||
| Contributors: | ||||
|   Jonathon Jongsma, Rui Matos, Jasper St. Pierre | ||||
|  | ||||
| 3.14.1.5 | ||||
| ======== | ||||
| * Fix wayland hiDPI regressions [Adel; #739161] | ||||
|  | ||||
| Contributors: | ||||
|   Adel Gadllah, Florian Müllner, Jasper St. Pierre | ||||
|   Rui Matos, Jasper St. Pierre, Rico Tzschichholz, Owen W. Taylor | ||||
|  | ||||
| Translations: | ||||
|   Dušan Kazik [sk] | ||||
|   Trần Ngọc Quân [vi], Muhammet Kara [tr] | ||||
|  | ||||
| 3.15.2 | ||||
| ====== | ||||
| * Don't enable hiDPI on monitors with broken EDID [Bastien; #734839] | ||||
| * Prevent crash applying monitor config for a closed lid [Rui; #739450] | ||||
| * Fix "flicker" during startup transition [Ray; #740377] | ||||
| * Misc. bug fixes [Lan, Florian, Carlos; #731521, #740133, #738890] | ||||
|  | ||||
| Contributors: | ||||
|   Emmanuele Bassi, Carlos Garnacho, Jonathon Jongsma, Ting-Wei Lan, Rui Matos, | ||||
|   Florian Müllner, Bastien Nocera, Jasper St. Pierre, Ray Strode | ||||
|  | ||||
| Translations: | ||||
|   Kjartan Maraas [nb] | ||||
|  | ||||
| 3.15.1 | ||||
| ====== | ||||
| * Use GResources for theme loading [Cosimo; #736936] | ||||
| * Fix headerbar drag getting stuck on xwayland [Carlos; #738411] | ||||
| * Fix wayland hiDPI regressions [Adel; #739161] | ||||
| * Misc bug fixes and cleanups [Jasper, Rui, Carlos; #662962, #738630, #738888, | ||||
|   #738890] | ||||
|  | ||||
| Contributors: | ||||
|   Cosimo Cecchi, Adel Gadllah, Carlos Garnacho, Rui Matos, Florian Müllner, | ||||
|   Jasper St. Pierre | ||||
|  | ||||
| 3.14.1 | ||||
| ====== | ||||
|   | ||||
| @@ -4,7 +4,6 @@ | ||||
| srcdir=`dirname $0` | ||||
| test -z "$srcdir" && srcdir=. | ||||
|  | ||||
| PKG_NAME="mutter" | ||||
| REQUIRED_AUTOMAKE_VERSION=1.11 | ||||
|  | ||||
| (test -f $srcdir/configure.ac \ | ||||
| @@ -19,4 +18,4 @@ which gnome-autogen.sh || { | ||||
|     echo "your distribution's package manager)." | ||||
|     exit 1 | ||||
| } | ||||
| USE_GNOME2_MACROS=1 USE_COMMON_DOC_BUILD=yes . gnome-autogen.sh | ||||
| . gnome-autogen.sh | ||||
|   | ||||
							
								
								
									
										83
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										83
									
								
								configure.ac
									
									
									
									
									
								
							| @@ -1,7 +1,7 @@ | ||||
| AC_PREREQ(2.62) | ||||
|  | ||||
| m4_define([mutter_major_version], [3]) | ||||
| m4_define([mutter_minor_version], [14]) | ||||
| m4_define([mutter_minor_version], [19]) | ||||
| m4_define([mutter_micro_version], [4]) | ||||
|  | ||||
| m4_define([mutter_version], | ||||
| @@ -46,37 +46,25 @@ IT_PROG_INTLTOOL([0.41]) | ||||
| AC_PROG_CC | ||||
| AC_PROG_CC_C_O | ||||
| AC_PROG_INSTALL | ||||
| AC_PROG_SED | ||||
| AC_HEADER_STDC | ||||
| PKG_PROG_PKG_CONFIG([0.21]) | ||||
|  | ||||
| # Sets GLIB_GENMARSHAL and GLIB_MKENUMS | ||||
| AM_PATH_GLIB_2_0() | ||||
|  | ||||
| #### Integer sizes | ||||
|  | ||||
| AC_CHECK_SIZEOF(char) | ||||
| AC_CHECK_SIZEOF(short) | ||||
| AC_CHECK_SIZEOF(long) | ||||
| AC_CHECK_SIZEOF(int) | ||||
| AC_CHECK_SIZEOF(void *) | ||||
| AC_CHECK_SIZEOF(long long) | ||||
| AC_CHECK_SIZEOF(__int64) | ||||
|  | ||||
| ## byte order | ||||
| AC_C_BIGENDIAN | ||||
|  | ||||
| CANBERRA_GTK=libcanberra-gtk3 | ||||
| CANBERRA_GTK_VERSION=0.26 | ||||
|  | ||||
| CLUTTER_PACKAGE=clutter-1.0 | ||||
|  | ||||
| MUTTER_PC_MODULES=" | ||||
|    gtk+-3.0 >= 3.9.11 | ||||
|    gtk+-3.0 >= 3.19.8 | ||||
|    gio-unix-2.0 >= 2.35.1 | ||||
|    pango >= 1.2.0 | ||||
|    cairo >= 1.10.0 | ||||
|    gsettings-desktop-schemas >= 3.7.3 | ||||
|    $CLUTTER_PACKAGE >= 1.19.5 | ||||
|    gsettings-desktop-schemas >= 3.19.3 | ||||
|    $CLUTTER_PACKAGE >= 1.25.1 | ||||
|    cogl-1.0 >= 1.17.1 | ||||
|    upower-glib >= 0.99.0 | ||||
|    gnome-desktop-3.0 | ||||
| @@ -90,6 +78,7 @@ MUTTER_PC_MODULES=" | ||||
|    xkeyboard-config | ||||
|    xkbcommon >= 0.4.3 | ||||
|    xkbcommon-x11 | ||||
|    xrender | ||||
|    x11-xcb | ||||
|    xcb-randr | ||||
| " | ||||
| @@ -200,22 +189,43 @@ AC_SUBST(XWAYLAND_PATH) | ||||
|  | ||||
| PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES) | ||||
|  | ||||
| PKG_CHECK_MODULES(MUTTER_NATIVE_BACKEND, [clutter-egl-1.0 libdrm libsystemd libinput gbm >= 10.3], [have_native_backend=yes], [have_native_backend=no]) | ||||
| if test $have_native_backend = yes; then | ||||
|    AC_DEFINE([HAVE_NATIVE_BACKEND],[1],[Define if you want to enable the native (KMS) backend based on systemd]) | ||||
| fi | ||||
| AM_CONDITIONAL([HAVE_NATIVE_BACKEND],[test $have_native_backend = yes]) | ||||
| MUTTER_NATIVE_BACKEND_MODULES="clutter-egl-1.0 libdrm libsystemd libinput gudev-1.0 gbm >= 10.3" | ||||
|  | ||||
| PKG_CHECK_MODULES(MUTTER_WAYLAND, [clutter-wayland-1.0 clutter-wayland-compositor-1.0 wayland-server >= 1.5.90], [have_wayland=yes], [have_wayland=no]) | ||||
| if test $have_wayland = yes; then | ||||
|    AC_PATH_PROG([WAYLAND_SCANNER],[wayland-scanner],[no]) | ||||
|    AS_IF([test $WAYLAND_SCANNER = "no"], | ||||
|      AC_MSG_ERROR([Could not find wayland-scanner in your PATH, required for parsing wayland extension protocols])) | ||||
|    AC_SUBST([WAYLAND_SCANNER]) | ||||
| AC_ARG_ENABLE(native-backend, | ||||
|   AS_HELP_STRING([--disable-native-backend], [disable mutter native (KMS) backend]),, | ||||
|   enable_native_backend=auto | ||||
| ) | ||||
| AS_IF([test "$enable_native_backend" = "yes"], [have_native_backend=yes], | ||||
|       [test "$enable_native_backend" = "auto"], PKG_CHECK_EXISTS([$MUTTER_NATIVE_BACKEND_MODULES], [have_native_backend=yes])) | ||||
|  | ||||
|    AC_DEFINE([HAVE_WAYLAND],[1],[Define if you want to enable Wayland support]) | ||||
| fi | ||||
| AM_CONDITIONAL([HAVE_WAYLAND],[test $have_wayland = yes]) | ||||
| AS_IF([test "$have_native_backend" = "yes"], [ | ||||
|   PKG_CHECK_MODULES([MUTTER_NATIVE_BACKEND], [$MUTTER_NATIVE_BACKEND_MODULES]) | ||||
|   AC_DEFINE([HAVE_NATIVE_BACKEND],[1], [Define if you want to enable the native (KMS) backend based on systemd]) | ||||
| ]) | ||||
| AM_CONDITIONAL([HAVE_NATIVE_BACKEND],[test "$have_native_backend" = "yes"]) | ||||
|  | ||||
| MUTTER_WAYLAND_MODULES="clutter-wayland-1.0 clutter-wayland-compositor-1.0 wayland-server >= 1.6.90" | ||||
|  | ||||
| AC_ARG_ENABLE(wayland, | ||||
|   AS_HELP_STRING([--disable-wayland], [disable mutter on wayland support]),, | ||||
|   enable_wayland=auto | ||||
| ) | ||||
| AS_IF([test "$enable_wayland" = "yes"], [have_wayland=yes], | ||||
|       [test "$enable_wayland" = "auto"], PKG_CHECK_EXISTS([$MUTTER_WAYLAND_MODULES], [have_wayland=yes])) | ||||
|  | ||||
| AS_IF([test "$have_wayland" = "yes"], [ | ||||
|   PKG_CHECK_MODULES([MUTTER_WAYLAND], [$MUTTER_WAYLAND_MODULES]) | ||||
|   AC_PATH_PROG([WAYLAND_SCANNER],[wayland-scanner],[no]) | ||||
|   AS_IF([test $WAYLAND_SCANNER = "no"], | ||||
|     [AC_MSG_ERROR([Could not find wayland-scanner in your PATH, required for parsing wayland extension protocols])]) | ||||
|   AC_SUBST([WAYLAND_SCANNER]) | ||||
|   AC_DEFINE([HAVE_WAYLAND],[1],[Define if you want to enable Wayland support]) | ||||
|  | ||||
|   PKG_CHECK_MODULES(WAYLAND_PROTOCOLS, [wayland-protocols >= 1.1], | ||||
| 		    [ac_wayland_protocols_pkgdatadir=`$PKG_CONFIG --variable=pkgdatadir wayland-protocols`]) | ||||
|   AC_SUBST(WAYLAND_PROTOCOLS_DATADIR, $ac_wayland_protocols_pkgdatadir) | ||||
| ]) | ||||
| AM_CONDITIONAL([HAVE_WAYLAND],[test "$have_wayland" = "yes"]) | ||||
|  | ||||
| PKG_CHECK_EXISTS([xi >= 1.6.99.1], | ||||
|                  AC_DEFINE([HAVE_XI23],[1],[Define if you have support for XInput 2.3 or greater])) | ||||
| @@ -266,6 +276,8 @@ AC_CHECK_LIB(Xrandr, XRRUpdateConfiguration, | ||||
|  | ||||
| if test "x$found_randr" = "xyes"; then | ||||
|    AC_DEFINE(HAVE_RANDR, , [Have the Xrandr extension library]) | ||||
|    PKG_CHECK_EXISTS([xrandr >= 1.5.0], | ||||
|                  AC_DEFINE([HAVE_XRANDR15],[1],[Define if you have support for XRandR 1.5 or greater])) | ||||
| fi | ||||
|  | ||||
| MUTTER_LIBS="$MUTTER_LIBS $RANDR_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm" | ||||
| @@ -312,7 +324,10 @@ if test "x$enable_debug" = "xyes"; then | ||||
| 	CFLAGS="$CFLAGS -g -O" | ||||
| fi | ||||
|  | ||||
| GTK_DOC_CHECK([1.15], [--flavour no-tmpl]) | ||||
| AC_CHECK_DECL([GL_EXT_x11_sync_object], | ||||
|               [], | ||||
|               [AC_MSG_ERROR([GL_EXT_x11_sync_object definition not found, please update your GL headers])], | ||||
|               [#include <GL/glx.h>]) | ||||
|  | ||||
| #### Warnings (last since -Werror can disturb other tests) | ||||
|  | ||||
| @@ -385,8 +400,6 @@ Makefile | ||||
| data/Makefile | ||||
| doc/Makefile | ||||
| doc/man/Makefile | ||||
| doc/reference/Makefile | ||||
| doc/reference/meta-docs.sgml | ||||
| src/Makefile | ||||
| src/libmutter.pc | ||||
| src/compositor/plugins/Makefile | ||||
| @@ -416,6 +429,8 @@ mutter-$VERSION | ||||
| 	libcanberra:              ${have_libcanberra} | ||||
| 	Introspection:            ${found_introspection} | ||||
| 	Session management:       ${found_sm} | ||||
| 	Wayland:                  ${have_wayland} | ||||
| 	Native (KMS) backend:     ${have_native_backend} | ||||
| " | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| desktopfiles_in_files = \ | ||||
| 	mutter.desktop.in \ | ||||
| 	mutter-wayland.desktop.in | ||||
| 	mutter.desktop.in | ||||
| desktopfilesdir = $(datadir)/applications | ||||
| desktopfiles_DATA = $(desktopfiles_in_files:.desktop.in=.desktop) | ||||
|  | ||||
|   | ||||
| @@ -1,17 +0,0 @@ | ||||
| [Desktop Entry] | ||||
| Type=Application | ||||
| _Name=Mutter (wayland compositor) | ||||
| Exec=mutter --wayland --display-server | ||||
| NoDisplay=true | ||||
| # name of loadable control center module | ||||
| X-GNOME-WMSettingsModule=metacity | ||||
| # name we put on the WM spec check window | ||||
| X-GNOME-WMName=Mutter | ||||
| # back compat only  | ||||
| X-GnomeWMSettingsLibrary=metacity | ||||
| X-GNOME-Bugzilla-Bugzilla=GNOME | ||||
| X-GNOME-Bugzilla-Product=mutter | ||||
| X-GNOME-Bugzilla-Component=general | ||||
| X-GNOME-Autostart-Phase=WindowManager | ||||
| X-GNOME-Provides=windowmanager | ||||
| X-GNOME-Autostart-Notify=true | ||||
| @@ -29,5 +29,25 @@ | ||||
|       <default><![CDATA[['<Primary><Alt>F7']]]></default> | ||||
|       <_summary>Switch to VT 7</_summary> | ||||
|     </key> | ||||
|     <key name="switch-to-session-8" type="as"> | ||||
|       <default><![CDATA[['<Primary><Alt>F8']]]></default> | ||||
|       <_summary>Switch to VT 8</_summary> | ||||
|     </key> | ||||
|     <key name="switch-to-session-9" type="as"> | ||||
|       <default><![CDATA[['<Primary><Alt>F9']]]></default> | ||||
|       <_summary>Switch to VT 9</_summary> | ||||
|     </key> | ||||
|     <key name="switch-to-session-10" type="as"> | ||||
|       <default><![CDATA[['<Primary><Alt>F10']]]></default> | ||||
|       <_summary>Switch to VT 10</_summary> | ||||
|     </key> | ||||
|     <key name="switch-to-session-11" type="as"> | ||||
|       <default><![CDATA[['<Primary><Alt>F11']]]></default> | ||||
|       <_summary>Switch to VT 11</_summary> | ||||
|     </key> | ||||
|     <key name="switch-to-session-12" type="as"> | ||||
|       <default><![CDATA[['<Primary><Alt>F12']]]></default> | ||||
|       <_summary>Switch to VT 12</_summary> | ||||
|     </key> | ||||
|   </schema> | ||||
| </schemalist> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| SUBDIRS = man reference | ||||
| SUBDIRS = man | ||||
|  | ||||
| EXTRA_DIST=theme-format.txt dialogs.txt code-overview.txt \ | ||||
| EXTRA_DIST = dialogs.txt code-overview.txt \ | ||||
| 	how-to-get-focus-right.txt rationales.txt | ||||
|   | ||||
| @@ -1,171 +0,0 @@ | ||||
| ## Process this file with automake to produce Makefile.in | ||||
|  | ||||
| # We require automake 1.6 at least. | ||||
| AUTOMAKE_OPTIONS = 1.6 | ||||
|  | ||||
| # This is a blank Makefile.am for using gtk-doc. | ||||
| # Copy this to your project's API docs directory and modify the variables to | ||||
| # suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples | ||||
| # of using the various options. | ||||
|  | ||||
| # The name of the module, e.g. 'glib'. | ||||
| DOC_MODULE=meta | ||||
|  | ||||
| # Uncomment for versioned docs and specify the version of the module, e.g. '2'. | ||||
| #DOC_MODULE_VERSION=2 | ||||
|  | ||||
|  | ||||
| # The top-level SGML file. You can change this if you want to. | ||||
| DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml | ||||
|  | ||||
| # Directories containing the source code, relative to $(srcdir). | ||||
| # gtk-doc will search all .c and .h files beneath these paths | ||||
| # for inline comments documenting functions and macros. | ||||
| # e.g. DOC_SOURCE_DIR=../../../gtk ../../../gdk | ||||
| DOC_SOURCE_DIR=../../src/ | ||||
|  | ||||
| # Extra options to pass to gtkdoc-scangobj. Not normally needed. | ||||
| SCANGOBJ_OPTIONS= | ||||
|  | ||||
| # Extra options to supply to gtkdoc-scan. | ||||
| # e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" | ||||
| SCAN_OPTIONS=--rebuild-types | ||||
|  | ||||
| # Extra options to supply to gtkdoc-mkdb. | ||||
| # e.g. MKDB_OPTIONS=--xml-mode --output-format=xml | ||||
| MKDB_OPTIONS=--xml-mode --output-format=xml | ||||
|  | ||||
| # Extra options to supply to gtkdoc-mktmpl | ||||
| # e.g. MKTMPL_OPTIONS=--only-section-tmpl | ||||
| MKTMPL_OPTIONS= | ||||
|  | ||||
| # Extra options to supply to gtkdoc-mkhtml | ||||
| MKHTML_OPTIONS= | ||||
|  | ||||
| # Extra options to supply to gtkdoc-fixref. Not normally needed. | ||||
| # e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html | ||||
| FIXXREF_OPTIONS= | ||||
|  | ||||
| # Used for dependencies. The docs will be rebuilt if any of these change. | ||||
| # e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h | ||||
| # e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c | ||||
| HFILE_GLOB=$(top_srcdir)/src/*/*.h | ||||
| CFILE_GLOB=$(top_srcdir)/src/*/*.c | ||||
|  | ||||
| # Extra header to include when scanning, which are not under DOC_SOURCE_DIR | ||||
| # e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h | ||||
| EXTRA_HFILES= | ||||
|  | ||||
| # Header files or dirs to ignore when scanning. Use base file/dir names | ||||
| # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code | ||||
| IGNORE_HFILES= \ | ||||
| 	async-getprop.h \ | ||||
| 	atoms.h \ | ||||
| 	bell.h \ | ||||
| 	boxes-private.h \ | ||||
| 	clutter-utils.h \ | ||||
| 	cogl-utils.h \ | ||||
| 	compositor-private.h \ | ||||
| 	constraints.h \ | ||||
| 	core.h \ | ||||
| 	display-private.h \ | ||||
| 	draw-workspace.h \ | ||||
| 	edge-resistance.h \ | ||||
| 	eventqueue.h \ | ||||
| 	frame.h \ | ||||
| 	frames.h \ | ||||
| 	group-private.h \ | ||||
| 	group-props.h \ | ||||
| 	iconcache.h \ | ||||
| 	inlinepixbufs.h \ | ||||
| 	keybindings-private.h \ | ||||
| 	meta-background-actor-private.h \ | ||||
| 	meta-background-group-private.h \ | ||||
| 	meta-module.h \ | ||||
| 	meta-plugin-manager.h \ | ||||
| 	meta-shadow-factory-private.h \ | ||||
| 	meta-texture-rectangle.h \ | ||||
| 	meta-texture-tower.h \ | ||||
| 	meta-window-actor-private.h \ | ||||
| 	meta-window-group.h \ | ||||
| 	meta-window-shape.h \ | ||||
| 	mutter-enum-types.h \ | ||||
| 	mutter-Xatomtype.h \ | ||||
| 	place.h \ | ||||
| 	preview-widget.h \ | ||||
| 	region-utils.h \ | ||||
| 	resizepopup.h \ | ||||
| 	screen-private.h \ | ||||
| 	session.h \ | ||||
| 	stack.h \ | ||||
| 	stack-tracker.h \ | ||||
| 	stamp-mutter-enum-types.h \ | ||||
| 	tabpopup.h \ | ||||
| 	theme.h \ | ||||
| 	theme-private.h \ | ||||
| 	tile-preview.h \ | ||||
| 	ui.h \ | ||||
| 	window-private.h \ | ||||
| 	window-props.h \ | ||||
| 	workspace-private.h \ | ||||
| 	xprops.h \ | ||||
| 	$(NULL) | ||||
|  | ||||
| if !HAVE_WAYLAND | ||||
| IGNORE_HFILES += \ | ||||
| 	meta-surface-actor-wayland.h	\ | ||||
| 	wayland				\ | ||||
| 	$(NULL) | ||||
| endif | ||||
|  | ||||
| MKDB_OPTIONS+=--ignore-files="$(IGNORE_HFILES)" | ||||
|  | ||||
| # Images to copy into HTML directory. | ||||
| # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png | ||||
| HTML_IMAGES= | ||||
|  | ||||
| # Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). | ||||
| # e.g. content_files=running.sgml building.sgml changes-2.0.sgml | ||||
| content_files= \ | ||||
| 	mutter-overview.xml \ | ||||
| 	running-mutter.xml \ | ||||
| 	$(NULL) | ||||
|  | ||||
| # SGML files where gtk-doc abbrevations (#GtkWidget) are expanded | ||||
| # These files must be listed here *and* in content_files | ||||
| # e.g. expand_content_files=running.sgml | ||||
| expand_content_files= \ | ||||
| 	mutter-overview.xml \ | ||||
| 	running-mutter.xml \ | ||||
| 	$(NULL) | ||||
|  | ||||
| # CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. | ||||
| # Only needed if you are using gtkdoc-scangobj to dynamically query widget | ||||
| # signals and properties. | ||||
| # e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) | ||||
| # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) | ||||
| GTKDOC_CFLAGS=$(MUTTER_CFLAGS) | ||||
| GTKDOC_LIBS=$(MUTTER_LIBS) $(top_builddir)/src/libmutter.la | ||||
|  | ||||
| # This includes the standard gtk-doc make rules, copied by gtkdocize. | ||||
| include $(top_srcdir)/gtk-doc.make | ||||
|  | ||||
| # Other files to distribute | ||||
| # e.g. EXTRA_DIST += version.xml.in | ||||
| EXTRA_DIST += | ||||
|  | ||||
| # Files not to distribute | ||||
| # for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types | ||||
| # for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt | ||||
| DISTCLEANFILES = $(DOC_MODULES).types | ||||
|  | ||||
| # Comment this out if you want 'make check' to test you doc status | ||||
| # and run some sanity checks | ||||
| if ENABLE_GTK_DOC | ||||
| TESTS_ENVIRONMENT = cd $(srcdir) && \ | ||||
|   DOC_MODULE=$(DOC_MODULE) DOC_MAIN_SGML_FILE=$(DOC_MAIN_SGML_FILE) \ | ||||
|   SRCDIR=$(abs_srcdir) BUILDDIR=$(abs_builddir) | ||||
| #TESTS = $(GTKDOC_CHECK) | ||||
| endif | ||||
|  | ||||
| -include $(top_srcdir)/git.mk | ||||
| @@ -1,59 +0,0 @@ | ||||
| <?xml version="1.0"?> | ||||
| <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" | ||||
|                "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" | ||||
| [ | ||||
|   <!ENTITY % local.common.attrib "xmlns:xi  CDATA  #FIXED 'http://www.w3.org/2003/XInclude'"> | ||||
|   <!ENTITY version "@VERSION@"> | ||||
| ]> | ||||
| <book id="index"> | ||||
|   <bookinfo> | ||||
|     <title>Mutter Reference Manual</title> | ||||
|     <releaseinfo> | ||||
|       This document is for Mutter &version;. | ||||
|       The latest version of this documentation can be found on-line at | ||||
|       <ulink role="online-location" url="http://developer.gnome.org/meta/">http://developer.gnome.org/meta/</ulink>. | ||||
|     </releaseinfo> | ||||
|   </bookinfo> | ||||
|  | ||||
|   <xi:include href="xml/mutter-overview.xml"/> | ||||
|   <xi:include href="xml/running-mutter.xml"/> | ||||
|  | ||||
|   <part id="core-reference"> | ||||
|     <title>Mutter Core Reference</title> | ||||
|     <xi:include href="xml/main.xml"/> | ||||
|     <xi:include href="xml/common.xml"/> | ||||
|     <xi:include href="xml/gradient.xml"/> | ||||
|     <xi:include href="xml/prefs.xml"/> | ||||
|     <xi:include href="xml/util.xml"/> | ||||
|     <xi:include href="xml/errors.xml"/> | ||||
|     <xi:include href="xml/meta-plugin.xml"/> | ||||
|     <xi:include href="xml/barrier.xml"/> | ||||
|     <xi:include href="xml/boxes.xml"/> | ||||
|     <xi:include href="xml/compositor.xml"/> | ||||
|     <xi:include href="xml/display.xml"/> | ||||
|     <xi:include href="xml/group.xml"/> | ||||
|     <xi:include href="xml/keybindings.xml"/> | ||||
|     <xi:include href="xml/meta-background-actor.xml"/> | ||||
|     <xi:include href="xml/meta-shadow-factory.xml"/> | ||||
|     <xi:include href="xml/meta-shaped-texture.xml"/> | ||||
|     <xi:include href="xml/meta-window-actor.xml"/> | ||||
|     <xi:include href="xml/screen.xml"/> | ||||
|     <xi:include href="xml/window.xml"/> | ||||
|     <xi:include href="xml/workspace.xml"/> | ||||
|   </part> | ||||
|  | ||||
|   <chapter id="object-tree"> | ||||
|     <title>Object Hierarchy</title> | ||||
|      <xi:include href="xml/tree_index.sgml"/> | ||||
|   </chapter> | ||||
|   <index id="api-index-full"> | ||||
|     <title>API Index</title> | ||||
|     <xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include> | ||||
|   </index> | ||||
|   <index id="deprecated-api-index" role="deprecated"> | ||||
|     <title>Index of deprecated API</title> | ||||
|     <xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include> | ||||
|   </index> | ||||
|  | ||||
|   <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include> | ||||
| </book> | ||||
| @@ -1,684 +0,0 @@ | ||||
| <SECTION> | ||||
| <FILE>barrier</FILE> | ||||
| <TITLE>MetaBarrier</TITLE> | ||||
| MetaBarrier | ||||
| MetaBarrierClass | ||||
| meta_barrier_is_active | ||||
| meta_barrier_destroy | ||||
| meta_barrier_release | ||||
| MetaBarrierDirection | ||||
| MetaBarrierEvent | ||||
| <SUBSECTION Standard> | ||||
| META_BARRIER | ||||
| META_BARRIER_CLASS | ||||
| META_BARRIER_GET_CLASS | ||||
| META_IS_BARRIER | ||||
| META_IS_BARRIER_CLASS | ||||
| META_TYPE_BARRIER | ||||
| META_TYPE_BARRIER_EVENT | ||||
| MetaBarrierPrivate | ||||
| meta_barrier_event_get_type | ||||
| meta_barrier_get_type | ||||
| </SECTION> | ||||
|  | ||||
| <SECTION> | ||||
| <FILE>boxes</FILE> | ||||
| MetaRectangle | ||||
| MetaStrut | ||||
| MetaEdgeType | ||||
| MetaEdge | ||||
| meta_rectangle_copy | ||||
| meta_rectangle_free | ||||
| meta_rect | ||||
| meta_rectangle_area | ||||
| meta_rectangle_intersect | ||||
| meta_rectangle_equal | ||||
| meta_rectangle_union | ||||
| meta_rectangle_overlap | ||||
| meta_rectangle_vert_overlap | ||||
| meta_rectangle_horiz_overlap | ||||
| meta_rectangle_could_fit_rect | ||||
| meta_rectangle_contains_rect | ||||
| <SUBSECTION Standard> | ||||
| META_TYPE_RECTANGLE | ||||
| meta_rectangle_get_type | ||||
| </SECTION> | ||||
|  | ||||
| <SECTION> | ||||
| <FILE>common</FILE> | ||||
| META_VIRTUAL_CORE_POINTER_ID | ||||
| META_VIRTUAL_CORE_KEYBOARD_ID | ||||
| MetaFrameFlags | ||||
| MetaMenuOp | ||||
| MetaWindowMenuFunc | ||||
| MetaGrabOp | ||||
| MetaCursor | ||||
| MetaFrameType | ||||
| MetaVirtualModifier | ||||
| MetaDirection | ||||
| MetaMotionDirection | ||||
| MetaSide | ||||
| MetaButtonFunction | ||||
| MAX_BUTTONS_PER_CORNER | ||||
| MetaButtonLayout | ||||
| MetaFrameBorders | ||||
| meta_frame_borders_clear | ||||
| META_ICON_WIDTH | ||||
| META_ICON_HEIGHT | ||||
| META_MINI_ICON_WIDTH | ||||
| META_MINI_ICON_HEIGHT | ||||
| META_DEFAULT_ICON_NAME | ||||
| META_PRIORITY_RESIZE | ||||
| META_PRIORITY_BEFORE_REDRAW | ||||
| META_PRIORITY_REDRAW | ||||
| META_PRIORITY_PREFS_NOTIFY | ||||
| POINT_IN_RECT | ||||
| MetaStackLayer | ||||
| MetaWindowMenu | ||||
| MetaResizePopup | ||||
| </SECTION> | ||||
|  | ||||
| <SECTION> | ||||
| <FILE>compositor</FILE> | ||||
| MetaCompEffect | ||||
| MetaCompositor | ||||
| meta_compositor_new | ||||
| meta_compositor_destroy | ||||
| meta_compositor_manage_screen | ||||
| meta_compositor_unmanage_screen | ||||
| meta_compositor_window_shape_changed | ||||
| meta_compositor_process_event | ||||
| meta_compositor_filter_keybinding | ||||
| meta_compositor_add_window | ||||
| meta_compositor_remove_window | ||||
| meta_compositor_show_window | ||||
| meta_compositor_hide_window | ||||
| meta_compositor_switch_workspace | ||||
| meta_compositor_maximize_window | ||||
| meta_compositor_unmaximize_window | ||||
| meta_compositor_sync_window_geometry | ||||
| meta_compositor_set_updates_frozen | ||||
| meta_compositor_queue_frame_drawn | ||||
| meta_compositor_sync_stack | ||||
| meta_compositor_sync_screen_size | ||||
| meta_compositor_flash_screen | ||||
| meta_get_stage_for_screen | ||||
| meta_get_overlay_group_for_screen | ||||
| meta_get_overlay_window | ||||
| meta_get_window_actors | ||||
| meta_get_window_group_for_screen | ||||
| meta_get_top_window_group_for_screen | ||||
| meta_disable_unredirect_for_screen | ||||
| meta_enable_unredirect_for_screen | ||||
| meta_set_stage_input_region | ||||
| meta_empty_stage_input_region | ||||
| </SECTION> | ||||
|  | ||||
| <SECTION> | ||||
| <FILE>display</FILE> | ||||
| MetaTabList | ||||
| MetaTabShowType | ||||
| meta_XFree | ||||
| meta_display_get_compositor_version | ||||
| meta_display_get_xinput_opcode | ||||
| meta_display_supports_extended_barriers | ||||
| meta_display_get_xdisplay | ||||
| meta_display_get_compositor | ||||
| meta_display_get_screens | ||||
| meta_display_has_shape | ||||
| meta_display_screen_for_root | ||||
| meta_display_get_focus_window | ||||
| meta_display_xwindow_is_a_no_focus_window | ||||
| meta_display_get_damage_event_base | ||||
| meta_display_get_shape_event_base | ||||
| meta_display_xserver_time_is_before | ||||
| meta_display_get_last_user_time | ||||
| meta_display_get_current_time | ||||
| meta_display_get_current_time_roundtrip | ||||
| meta_display_get_ignored_modifier_mask | ||||
| meta_display_get_tab_list | ||||
| meta_display_get_tab_next | ||||
| meta_display_get_tab_current | ||||
| meta_display_begin_grab_op | ||||
| meta_display_end_grab_op | ||||
| meta_display_get_grab_op | ||||
| meta_display_add_keybinding | ||||
| meta_display_remove_keybinding | ||||
| meta_display_get_keybinding_action | ||||
| meta_display_set_input_focus_window | ||||
| meta_display_focus_the_no_focus_window | ||||
| meta_display_sort_windows_by_stacking | ||||
| meta_display_get_leader_window | ||||
| meta_display_add_ignored_crossing_serial | ||||
| meta_display_unmanage_screen | ||||
| meta_display_clear_mouse_mode | ||||
| MetaDisplay | ||||
| MetaDisplayClass | ||||
| <SUBSECTION Standard> | ||||
| META_DISPLAY | ||||
| META_DISPLAY_CLASS | ||||
| META_DISPLAY_GET_CLASS | ||||
| META_IS_DISPLAY | ||||
| META_IS_DISPLAY_CLASS | ||||
| META_TYPE_DISPLAY | ||||
| meta_display_get_type | ||||
| </SECTION> | ||||
|  | ||||
| <SECTION> | ||||
| <FILE>errors</FILE> | ||||
| meta_error_trap_push | ||||
| meta_error_trap_pop | ||||
| meta_error_trap_push_with_return | ||||
| meta_error_trap_pop_with_return | ||||
| </SECTION> | ||||
|  | ||||
| <SECTION> | ||||
| <FILE>gradient</FILE> | ||||
| MetaGradientType | ||||
| meta_gradient_create_simple | ||||
| meta_gradient_create_multi | ||||
| meta_gradient_create_interwoven | ||||
| meta_gradient_add_alpha | ||||
| </SECTION> | ||||
|  | ||||
| <SECTION> | ||||
| <FILE>group</FILE> | ||||
| MetaGroup | ||||
| meta_window_get_group | ||||
| meta_window_compute_group | ||||
| meta_window_shutdown_group | ||||
| meta_window_group_leader_changed | ||||
| meta_display_lookup_group | ||||
| meta_group_list_windows | ||||
| meta_group_update_layers | ||||
| meta_group_get_startup_id | ||||
| meta_group_get_size | ||||
| meta_group_property_notify | ||||
| </SECTION> | ||||
|  | ||||
| <SECTION> | ||||
| <FILE>keybindings</FILE> | ||||
| MetaKeyBinding | ||||
| META_TYPE_KEY_BINDING | ||||
| meta_key_binding_get_name | ||||
| meta_key_binding_get_modifiers | ||||
| meta_key_binding_get_mask | ||||
| meta_key_binding_is_builtin | ||||
| meta_keybindings_set_custom_handler | ||||
| meta_screen_ungrab_all_keys | ||||
| meta_screen_grab_all_keys | ||||
| </SECTION> | ||||
|  | ||||
| <SECTION> | ||||
| <FILE>main</FILE> | ||||
| meta_get_option_context | ||||
| meta_init | ||||
| meta_run | ||||
| meta_get_replace_current_wm | ||||
| meta_set_wm_name | ||||
| meta_set_gnome_wm_keybindings | ||||
| MetaExitCode | ||||
| meta_exit | ||||
| meta_quit | ||||
| </SECTION> | ||||
|  | ||||
| <SECTION> | ||||
| <FILE>meta-background</FILE> | ||||
| <TITLE>MetaBackground</TITLE> | ||||
| MetaBackgroundEffects | ||||
| MetaBackground | ||||
| MetaBackgroundClass | ||||
| meta_background_new | ||||
| meta_background_copy | ||||
| meta_background_load_gradient | ||||
| meta_background_load_color | ||||
| meta_background_load_still_frame | ||||
| meta_background_load_file_async | ||||
| meta_background_load_file_finish | ||||
| meta_background_get_filename | ||||
| meta_background_get_style | ||||
| meta_background_get_shading | ||||
| meta_background_get_color | ||||
| meta_background_get_second_color | ||||
| <SUBSECTION Standard> | ||||
| META_BACKGROUND | ||||
| META_BACKGROUND_CLASS | ||||
| META_BACKGROUND_GET_CLASS | ||||
| META_IS_BACKGROUND | ||||
| META_IS_BACKGROUND_CLASS | ||||
| META_TYPE_BACKGROUND | ||||
| MetaBackgroundPrivate | ||||
| meta_background_get_type | ||||
| </SECTION> | ||||
|  | ||||
| <SECTION> | ||||
| <FILE>meta-background-actor</FILE> | ||||
| <TITLE>MetaBackgroundActor</TITLE> | ||||
| MetaBackgroundActor | ||||
| MetaBackgroundActorClass | ||||
| meta_background_actor_new_for_screen | ||||
| MetaSnippetHook | ||||
| meta_background_actor_add_glsl_snippet | ||||
| meta_background_actor_set_uniform_float | ||||
| <SUBSECTION Standard> | ||||
| META_BACKGROUND_ACTOR | ||||
| META_BACKGROUND_ACTOR_CLASS | ||||
| META_BACKGROUND_ACTOR_GET_CLASS | ||||
| META_IS_BACKGROUND_ACTOR | ||||
| META_IS_BACKGROUND_ACTOR_CLASS | ||||
| META_TYPE_BACKGROUND_ACTOR | ||||
| MetaBackgroundActorPrivate | ||||
| meta_background_actor_get_type | ||||
| </SECTION> | ||||
|  | ||||
| <SECTION> | ||||
| <FILE>meta-background-group</FILE> | ||||
| <TITLE>MetaBackgroundGroup</TITLE> | ||||
| MetaBackgroundGroupClass | ||||
| meta_background_group_new | ||||
| <SUBSECTION Standard> | ||||
| META_BACKGROUND_GROUP | ||||
| META_BACKGROUND_GROUP_CLASS | ||||
| META_BACKGROUND_GROUP_GET_CLASS | ||||
| META_IS_BACKGROUND_GROUP | ||||
| META_IS_BACKGROUND_GROUP_CLASS | ||||
| META_TYPE_BACKGROUND_GROUP | ||||
| MetaBackgroundGroupPrivate | ||||
| meta_background_group_get_type | ||||
| </SECTION> | ||||
|  | ||||
| <SECTION> | ||||
| <FILE>meta-plugin</FILE> | ||||
| <TITLE>MetaPlugin</TITLE> | ||||
| MetaPlugin | ||||
| MetaPluginClass | ||||
| MetaPluginInfo | ||||
| meta_plugin_running | ||||
| meta_plugin_debug_mode | ||||
| meta_plugin_get_info | ||||
| MetaPluginVersion | ||||
| META_PLUGIN_DECLARE | ||||
| meta_plugin_switch_workspace_completed | ||||
| meta_plugin_minimize_completed | ||||
| meta_plugin_unminimize_completed | ||||
| meta_plugin_maximize_completed | ||||
| meta_plugin_unmaximize_completed | ||||
| meta_plugin_map_completed | ||||
| meta_plugin_destroy_completed | ||||
| MetaModalOptions | ||||
| meta_plugin_begin_modal | ||||
| meta_plugin_end_modal | ||||
| meta_plugin_get_screen | ||||
| meta_plugin_manager_set_plugin_type | ||||
| <SUBSECTION Standard> | ||||
| META_IS_PLUGIN | ||||
| META_IS_PLUGIN_CLASS | ||||
| META_PLUGIN | ||||
| META_PLUGIN_CLASS | ||||
| META_PLUGIN_GET_CLASS | ||||
| META_TYPE_PLUGIN | ||||
| MetaPluginPrivate | ||||
| meta_plugin_get_type | ||||
| </SECTION> | ||||
|  | ||||
| <SECTION> | ||||
| <FILE>meta-shadow-factory</FILE> | ||||
| MetaShadowParams | ||||
| meta_shadow_factory_get_default | ||||
| meta_shadow_factory_set_params | ||||
| meta_shadow_factory_get_params | ||||
| MetaShadowFactory | ||||
| MetaShadowFactoryClass | ||||
| <SUBSECTION Standard> | ||||
| META_IS_SHADOW_FACTORY | ||||
| META_IS_SHADOW_FACTORY_CLASS | ||||
| META_SHADOW_FACTORY | ||||
| META_SHADOW_FACTORY_CLASS | ||||
| META_SHADOW_FACTORY_GET_CLASS | ||||
| META_TYPE_SHADOW_FACTORY | ||||
| meta_shadow_factory_get_type | ||||
| </SECTION> | ||||
|  | ||||
| <SECTION> | ||||
| <FILE>meta-shaped-texture</FILE> | ||||
| <TITLE>MetaShapedTexture</TITLE> | ||||
| MetaShapedTexture | ||||
| MetaShapedTextureClass | ||||
| meta_shaped_texture_new | ||||
| meta_shaped_texture_set_create_mipmaps | ||||
| meta_shaped_texture_update_area | ||||
| meta_shaped_texture_set_pixmap | ||||
| meta_shaped_texture_get_texture | ||||
| meta_shaped_texture_set_mask_texture | ||||
| meta_shaped_texture_set_clip_region | ||||
| meta_shaped_texture_get_image | ||||
| <SUBSECTION Standard> | ||||
| META_IS_SHAPED_TEXTURE | ||||
| META_IS_SHAPED_TEXTURE_CLASS | ||||
| META_SHAPED_TEXTURE | ||||
| META_SHAPED_TEXTURE_CLASS | ||||
| META_SHAPED_TEXTURE_GET_CLASS | ||||
| META_TYPE_SHAPED_TEXTURE | ||||
| MetaShapedTexturePrivate | ||||
| meta_shaped_texture_get_type | ||||
| </SECTION> | ||||
|  | ||||
| <SECTION> | ||||
| <FILE>meta-window-actor</FILE> | ||||
| <TITLE>MetaWindowActor</TITLE> | ||||
| MetaWindowActor | ||||
| MetaWindowActorClass | ||||
| meta_window_actor_get_x_window | ||||
| meta_window_actor_get_workspace | ||||
| meta_window_actor_get_meta_window | ||||
| meta_window_actor_get_texture | ||||
| meta_window_actor_is_override_redirect | ||||
| meta_window_actor_get_description | ||||
| meta_window_actor_showing_on_its_workspace | ||||
| meta_window_actor_is_destroyed | ||||
| <SUBSECTION Standard> | ||||
| META_IS_WINDOW_ACTOR | ||||
| META_IS_WINDOW_ACTOR_CLASS | ||||
| META_TYPE_WINDOW_ACTOR | ||||
| META_WINDOW_ACTOR | ||||
| META_WINDOW_ACTOR_CLASS | ||||
| META_WINDOW_ACTOR_GET_CLASS | ||||
| MetaWindowActorPrivate | ||||
| meta_window_actor_get_type | ||||
| </SECTION> | ||||
|  | ||||
| <SECTION> | ||||
| <FILE>meta-cullable</FILE> | ||||
| <TITLE>MetaCullable</TITLE> | ||||
| MetaCullable | ||||
| MetaCullableInterface | ||||
| meta_cullable_cull_out | ||||
| meta_cullable_reset_culling | ||||
| meta_cullable_cull_out_children | ||||
| meta_cullable_reset_culling_children | ||||
| <SUBSECTION Standard> | ||||
| META_TYPE_CULLABLE | ||||
| META_CULLABLE | ||||
| META_IS_CULLABLE | ||||
| META_CULLABLE_GET_IFACE | ||||
| meta_cullable_get_type | ||||
| </SECTION> | ||||
|  | ||||
| <SECTION> | ||||
| <FILE>prefs</FILE> | ||||
| MetaPreference | ||||
| MetaPrefsChangedFunc | ||||
| meta_prefs_add_listener | ||||
| meta_prefs_remove_listener | ||||
| meta_prefs_init | ||||
| meta_prefs_override_preference_schema | ||||
| meta_preference_to_string | ||||
| meta_prefs_get_mouse_button_mods | ||||
| meta_prefs_get_mouse_button_resize | ||||
| meta_prefs_get_mouse_button_menu | ||||
| meta_prefs_get_focus_mode | ||||
| meta_prefs_get_focus_new_windows | ||||
| meta_prefs_get_attach_modal_dialogs | ||||
| meta_prefs_get_raise_on_click | ||||
| meta_prefs_get_theme | ||||
| meta_prefs_get_titlebar_font | ||||
| meta_prefs_get_num_workspaces | ||||
| meta_prefs_get_dynamic_workspaces | ||||
| meta_prefs_get_disable_workarounds | ||||
| meta_prefs_get_auto_raise | ||||
| meta_prefs_get_auto_raise_delay | ||||
| meta_prefs_get_focus_change_on_pointer_rest | ||||
| meta_prefs_get_gnome_accessibility | ||||
| meta_prefs_get_gnome_animations | ||||
| meta_prefs_get_edge_tiling | ||||
| meta_prefs_get_auto_maximize | ||||
| meta_prefs_get_button_layout | ||||
| meta_prefs_get_action_double_click_titlebar | ||||
| meta_prefs_get_action_middle_click_titlebar | ||||
| meta_prefs_get_action_right_click_titlebar | ||||
| meta_prefs_set_num_workspaces | ||||
| meta_prefs_get_workspace_name | ||||
| meta_prefs_change_workspace_name | ||||
| meta_prefs_get_cursor_theme | ||||
| meta_prefs_get_cursor_size | ||||
| meta_prefs_get_compositing_manager | ||||
| meta_prefs_get_force_fullscreen | ||||
| meta_prefs_set_force_fullscreen | ||||
| meta_prefs_get_workspaces_only_on_primary | ||||
| meta_prefs_get_no_tab_popup | ||||
| meta_prefs_set_no_tab_popup | ||||
| meta_prefs_get_draggable_border_width | ||||
| meta_prefs_get_ignore_request_hide_titlebar | ||||
| meta_prefs_set_ignore_request_hide_titlebar | ||||
| MetaKeyBindingAction | ||||
| MetaKeyBindingFlags | ||||
| MetaKeyCombo | ||||
| MetaKeyHandlerFunc | ||||
| meta_prefs_get_keybindings | ||||
| meta_prefs_get_keybinding_action | ||||
| meta_prefs_get_window_binding | ||||
| meta_prefs_get_overlay_binding | ||||
| meta_prefs_get_visual_bell | ||||
| meta_prefs_bell_is_audible | ||||
| meta_prefs_get_visual_bell_type | ||||
| MetaKeyHandler | ||||
| <SUBSECTION Standard> | ||||
| meta_key_binding_get_type | ||||
| </SECTION> | ||||
|  | ||||
| <SECTION> | ||||
| <FILE>screen</FILE> | ||||
| MetaScreen | ||||
| MetaScreenClass | ||||
| meta_screen_get_screen_number | ||||
| meta_screen_get_display | ||||
| meta_screen_get_xroot | ||||
| meta_screen_get_size | ||||
| meta_screen_get_compositor_data | ||||
| meta_screen_set_compositor_data | ||||
| meta_screen_for_x_screen | ||||
| meta_screen_set_cm_selection | ||||
| meta_screen_unset_cm_selection | ||||
| meta_screen_get_startup_sequences | ||||
| meta_screen_get_workspaces | ||||
| meta_screen_get_n_workspaces | ||||
| meta_screen_get_workspace_by_index | ||||
| meta_screen_remove_workspace | ||||
| meta_screen_append_new_workspace | ||||
| meta_screen_get_active_workspace_index | ||||
| meta_screen_get_active_workspace | ||||
| meta_screen_get_n_monitors | ||||
| meta_screen_get_primary_monitor | ||||
| meta_screen_get_current_monitor | ||||
| meta_screen_get_monitor_geometry | ||||
| meta_screen_get_monitor_index_for_rect | ||||
| meta_screen_focus_default_window | ||||
| MetaScreenCorner | ||||
| meta_screen_override_workspace_layout | ||||
| <SUBSECTION Standard> | ||||
| META_IS_SCREEN | ||||
| META_IS_SCREEN_CLASS | ||||
| META_SCREEN | ||||
| META_SCREEN_CLASS | ||||
| META_SCREEN_GET_CLASS | ||||
| META_TYPE_SCREEN | ||||
| meta_screen_get_type | ||||
| </SECTION> | ||||
|  | ||||
| <SECTION> | ||||
| <FILE>util</FILE> | ||||
| meta_is_verbose | ||||
| meta_set_verbose | ||||
| meta_is_debugging | ||||
| meta_set_debugging | ||||
| meta_is_syncing | ||||
| meta_set_syncing | ||||
| meta_set_replace_current_wm | ||||
| meta_debug_spew_real | ||||
| meta_verbose_real | ||||
| meta_bug | ||||
| meta_warning | ||||
| meta_fatal | ||||
| MetaDebugTopic | ||||
| meta_topic_real | ||||
| meta_add_verbose_topic | ||||
| meta_remove_verbose_topic | ||||
| meta_push_no_msg_prefix | ||||
| meta_pop_no_msg_prefix | ||||
| meta_unsigned_long_equal | ||||
| meta_unsigned_long_hash | ||||
| meta_frame_type_to_string | ||||
| meta_gravity_to_string | ||||
| _ | ||||
| N_ | ||||
| meta_g_utf8_strndup | ||||
| meta_free_gslist_and_elements | ||||
| meta_show_dialog | ||||
| meta_debug_spew | ||||
| meta_verbose | ||||
| meta_topic | ||||
| MetaLaterType | ||||
| meta_later_add | ||||
| meta_later_remove | ||||
| </SECTION> | ||||
|  | ||||
| <SECTION> | ||||
| <FILE>window</FILE> | ||||
| MetaWindow | ||||
| MetaWindowClass | ||||
| MetaWindowType | ||||
| MetaMaximizeFlags | ||||
| meta_window_get_frame | ||||
| meta_window_has_focus | ||||
| meta_window_appears_focused | ||||
| meta_window_is_shaded | ||||
| meta_window_is_monitor_sized | ||||
| meta_window_is_override_redirect | ||||
| meta_window_is_skip_taskbar | ||||
| meta_window_get_rect | ||||
| meta_window_get_buffer_rect | ||||
| meta_window_get_frame_rect | ||||
| meta_window_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 | ||||
| meta_window_get_window_type | ||||
| meta_window_get_window_type_atom | ||||
| meta_window_get_workspace | ||||
| meta_window_get_monitor | ||||
| meta_window_is_on_all_workspaces | ||||
| meta_window_located_on_workspace | ||||
| meta_window_is_hidden | ||||
| meta_window_activate | ||||
| meta_window_activate_with_workspace | ||||
| meta_window_get_description | ||||
| meta_window_get_wm_class | ||||
| meta_window_get_wm_class_instance | ||||
| meta_window_showing_on_its_workspace | ||||
| meta_window_get_gtk_application_id | ||||
| meta_window_get_gtk_unique_bus_name | ||||
| meta_window_get_gtk_application_object_path | ||||
| meta_window_get_gtk_window_object_path | ||||
| meta_window_get_gtk_app_menu_object_path | ||||
| meta_window_get_gtk_menubar_object_path | ||||
| meta_window_move | ||||
| meta_window_move_frame | ||||
| meta_window_move_resize_frame | ||||
| meta_window_move_to_monitor | ||||
| meta_window_resize | ||||
| meta_window_set_demands_attention | ||||
| meta_window_unset_demands_attention | ||||
| meta_window_get_startup_id | ||||
| meta_window_change_workspace_by_index | ||||
| meta_window_change_workspace | ||||
| meta_window_get_compositor_private | ||||
| meta_window_set_compositor_private | ||||
| meta_window_configure_notify | ||||
| meta_window_get_role | ||||
| meta_window_get_layer | ||||
| meta_window_find_root_ancestor | ||||
| meta_window_is_ancestor_of_transient | ||||
| MetaWindowForeachFunc | ||||
| meta_window_foreach_transient | ||||
| meta_window_foreach_ancestor | ||||
| meta_window_get_maximized | ||||
| meta_window_is_fullscreen | ||||
| meta_window_is_on_primary_monitor | ||||
| meta_window_requested_bypass_compositor | ||||
| meta_window_requested_dont_bypass_compositor | ||||
| meta_window_is_mapped | ||||
| meta_window_toplevel_is_mapped | ||||
| meta_window_get_icon_geometry | ||||
| meta_window_set_icon_geometry | ||||
| meta_window_maximize | ||||
| meta_window_unmaximize | ||||
| meta_window_minimize | ||||
| meta_window_unminimize | ||||
| meta_window_raise | ||||
| meta_window_lower | ||||
| meta_window_get_title | ||||
| meta_window_get_transient_for | ||||
| meta_window_get_transient_for_as_xid | ||||
| meta_window_delete | ||||
| meta_window_get_stable_sequence | ||||
| meta_window_get_user_time | ||||
| meta_window_get_pid | ||||
| meta_window_get_client_machine | ||||
| meta_window_is_remote | ||||
| meta_window_is_modal | ||||
| meta_window_is_attached_dialog | ||||
| meta_window_get_mutter_hints | ||||
| meta_window_get_frame_type | ||||
| meta_window_get_frame_bounds | ||||
| meta_window_get_tile_match | ||||
| meta_window_make_fullscreen | ||||
| meta_window_unmake_fullscreen | ||||
| meta_window_make_above | ||||
| meta_window_unmake_above | ||||
| meta_window_shade | ||||
| meta_window_unshade | ||||
| meta_window_stick | ||||
| meta_window_unstick | ||||
| meta_window_kill | ||||
| meta_window_focus | ||||
| meta_window_check_alive | ||||
| meta_window_get_work_area_current_monitor | ||||
| meta_window_get_work_area_for_monitor | ||||
| meta_window_get_work_area_all_monitors | ||||
| meta_window_begin_grab_op | ||||
| <SUBSECTION Standard> | ||||
| META_IS_WINDOW | ||||
| META_IS_WINDOW_CLASS | ||||
| META_TYPE_WINDOW | ||||
| META_WINDOW | ||||
| META_WINDOW_CLASS | ||||
| META_WINDOW_GET_CLASS | ||||
| meta_window_get_type | ||||
| </SECTION> | ||||
|  | ||||
| <SECTION> | ||||
| <FILE>workspace</FILE> | ||||
| MetaWorkspace | ||||
| MetaWorkspaceClass | ||||
| meta_workspace_index | ||||
| meta_workspace_get_screen | ||||
| meta_workspace_list_windows | ||||
| meta_workspace_get_work_area_for_monitor | ||||
| meta_workspace_get_work_area_all_monitors | ||||
| meta_workspace_activate | ||||
| meta_workspace_activate_with_focus | ||||
| meta_workspace_update_window_hints | ||||
| meta_workspace_set_builtin_struts | ||||
| meta_workspace_get_neighbor | ||||
| <SUBSECTION Standard> | ||||
| META_IS_WORKSPACE | ||||
| META_IS_WORKSPACE_CLASS | ||||
| META_TYPE_WORKSPACE | ||||
| META_WORKSPACE | ||||
| META_WORKSPACE_CLASS | ||||
| META_WORKSPACE_GET_CLASS | ||||
| meta_workspace_get_type | ||||
| </SECTION> | ||||
|  | ||||
| @@ -1,15 +0,0 @@ | ||||
| <part id="mutter-overview"> | ||||
|  | ||||
|   <title>Overview</title> | ||||
|  | ||||
|   <partintro> | ||||
|  | ||||
|     <para>Mutter is a GObject-based library for creating compositing window managers.</para> | ||||
|  | ||||
|     <para>Compositors that wish to use Mutter must implement a subclass of #MetaPlugin and register it with meta_plugin_manager_set_plugin_type() before calling meta_init() but after g_type_init().</para> | ||||
|  | ||||
|     <para>#MetaPlugin provides virtual functions that allow to override default behavior in the window management code, such as the effect to perform when a window is created or when switching workspaces.</para> | ||||
|  | ||||
|   </partintro> | ||||
|  | ||||
| </part> | ||||
| @@ -1,100 +0,0 @@ | ||||
| <part id="running-mutter"> | ||||
|  | ||||
|   <title>Running Mutter</title> | ||||
|  | ||||
|   <partintro> | ||||
|  | ||||
|     <section id="environment-variables"> | ||||
|       <title>Environment Variables</title> | ||||
|  | ||||
|       <para> | ||||
|         Mutter automatically checks environment variables during | ||||
|         its initialization. These environment variables are meant | ||||
|         as debug tools or overrides for default behaviours: | ||||
|       </para> | ||||
|  | ||||
|       <variablelist> | ||||
|         <varlistentry> | ||||
|           <term>MUTTER_VERBOSE</term> | ||||
|           <listitem> | ||||
|             <para>Enable verbose mode, in which more information is printed to the console. Mutter needs to be built with the --enable-verbose-mode option (enabled by default). For more fine-grained control of the output, see meta_add_verbose_topic().</para> | ||||
|           </listitem> | ||||
|         </varlistentry> | ||||
|         <varlistentry> | ||||
|           <term>MUTTER_DEBUG</term> | ||||
|           <listitem> | ||||
|             <para>Traps and prints X errors to the console.</para> | ||||
|           </listitem> | ||||
|         </varlistentry> | ||||
|         <varlistentry> | ||||
|           <term>MUTTER_G_FATAL_WARNINGS</term> | ||||
|           <listitem> | ||||
|             <para>Causes any logging from the domains Mutter, Gtk, Gdk, Pango or GLib to terminate the process (only when using the log functions in GLib).</para> | ||||
|           </listitem> | ||||
|         </varlistentry> | ||||
|         <varlistentry> | ||||
|           <term>MUTTER_USE_LOGFILE</term> | ||||
|           <listitem> | ||||
|             <para>Log all messages to a temporary file.</para> | ||||
|           </listitem> | ||||
|         </varlistentry> | ||||
|         <varlistentry> | ||||
|           <term>MUTTER_DEBUG_XINERAMA</term> | ||||
|           <listitem> | ||||
|             <para>Log extra information about support of the XINERAMA extension.</para> | ||||
|           </listitem> | ||||
|         </varlistentry> | ||||
|         <varlistentry> | ||||
|           <term>MUTTER_DEBUG_SM</term> | ||||
|           <listitem> | ||||
|             <para>Log extra information about session management.</para> | ||||
|           </listitem> | ||||
|         </varlistentry> | ||||
|         <varlistentry> | ||||
|           <term>MUTTER_DEBUG_BUTTON_GRABS</term> | ||||
|           <listitem> | ||||
|             <para>Log extra information about button grabs.</para> | ||||
|           </listitem> | ||||
|         </varlistentry> | ||||
|         <varlistentry> | ||||
|           <term>MUTTER_SYNC</term> | ||||
|           <listitem> | ||||
|             <para>Call XSync after each X call.</para> | ||||
|           </listitem> | ||||
|         </varlistentry> | ||||
|         <varlistentry> | ||||
|           <term>MUTTER_DISPLAY</term> | ||||
|           <listitem> | ||||
|             <para>Name of the X11 display to use.</para> | ||||
|           </listitem> | ||||
|         </varlistentry> | ||||
|         <varlistentry> | ||||
|           <term>META_DISABLE_MIPMAPS</term> | ||||
|           <listitem> | ||||
|             <para>Disable use of mipmaps for the textures that back window pixmaps.</para> | ||||
|           </listitem> | ||||
|         </varlistentry> | ||||
|         <varlistentry> | ||||
|           <term>MUTTER_USE_STATIC_GRAVITY</term> | ||||
|           <listitem> | ||||
|             <para>Enable support for clients with static bit-gravity.</para> | ||||
|           </listitem> | ||||
|         </varlistentry> | ||||
|         <varlistentry> | ||||
|           <term>MUTTER_WM_CLASS_FILTER</term> | ||||
|           <listitem> | ||||
|             <para>Comma-separated list of WM_CLASS names to which to restrict Mutter to.</para> | ||||
|           </listitem> | ||||
|         </varlistentry> | ||||
|         <varlistentry> | ||||
|           <term>MUTTER_DISABLE_FALLBACK_COLOR</term> | ||||
|           <listitem> | ||||
|             <para>Disable fallback for themed colors, for easier detection of typographical errors.</para> | ||||
|           </listitem> | ||||
|         </varlistentry> | ||||
|       </variablelist> | ||||
|  | ||||
|     </section> | ||||
|  | ||||
|   </partintro> | ||||
| </part> | ||||
| @@ -1,396 +0,0 @@ | ||||
| Themes are in a simple XML-subset format. There are multiple versions | ||||
| of the theme format, and a given theme can support more than one format. | ||||
|  | ||||
| Version 1:     THEMEDIR/metacity-1/metacity-theme-1.xml | ||||
|   (original metacity format) | ||||
| Version 2:     THEMEDIR/metacity-1/metacity-theme-2.xml | ||||
| Version 3:     THEMEDIR/metacity-1/metacity-theme-3.xml | ||||
|  | ||||
| The subdirectory name is "metacity-1" in all versions. | ||||
|  | ||||
| As you might expect, older versions of metacity will not understand | ||||
| newer theme formats. However, newer versions will use old themes. | ||||
| Metacity will always use the newest theme format it understands that | ||||
| the X server supports. Some format versions are only supported if you | ||||
| have the right X server features. | ||||
|  | ||||
| Each format *requires* the corresponding filename. If you put version | ||||
| 2 format features in the metacity-1/metacity-theme-1.xml file, then | ||||
| metacity will get angry. | ||||
|  | ||||
| This document has separate sections for each format version. You may | ||||
| want to read the document in reverse order, since the base features | ||||
| are discussed under version 1. | ||||
|  | ||||
| New Features in Theme Format Version 3.4 | ||||
| ======================================== | ||||
|  | ||||
| An additional color type is added to pick up custom colors defined | ||||
| in the GTK+ theme's CSS: | ||||
|  | ||||
|   gtk:custom(name,fallback) | ||||
|  | ||||
| where <name> refers to a custom color defined with @define-color in | ||||
| the GTK+ theme, and <fallback> provides an alternative color definition | ||||
| in case the color referenced by <name> is not found. | ||||
|  | ||||
| New Features in Theme Format Version 3.3 | ||||
| ======================================== | ||||
|  | ||||
| Add two additional button background functions - left_single_background and | ||||
| right_single_background - for button groups with just a single button. | ||||
|  | ||||
| There are now additional frame states to style left/right tiled windows | ||||
| differently ("tiled_left", "tiled_right", "tiled_left_and_shaded", | ||||
| "tiled_right_and_shaded"). | ||||
|  | ||||
| New Features in Theme Format Version 3.2 | ||||
| ======================================== | ||||
|  | ||||
| A new window type 'attached' is added for modal dialogs which are | ||||
| attached to their parent window. (When the attach_modal_dialogs preference | ||||
| is turned on.) If no style is defined for the 'attached' window type, | ||||
| the 'border' window type will be used instead. | ||||
|  | ||||
| New Features in Theme Format Version 3.1 | ||||
| ======================================== | ||||
|  | ||||
| Additional predefined variables are added for positioning expressions: | ||||
|  | ||||
|  frame_x_center: the X center of the entire frame, with respect to the | ||||
|      piece currently being drawn. | ||||
|  frame_y_center: the Y center of the entire frame, with respect to the | ||||
|      piece currently being drawn. | ||||
|  | ||||
| The <title/> element now supports an "ellipsize_width" attribute. When | ||||
| specified, this gives a width at which to ellipsize the title. If not | ||||
| specified, the title will simply be clipped to the title area. | ||||
|  | ||||
| New Features in Theme Format Version 3 | ||||
| ====================================== | ||||
|  | ||||
| Format version 3 has exactly one new feature; any element in the file | ||||
| can now have a version attribute: | ||||
|  | ||||
|   version="[<|<=|=>|>] MAJOR.MINOR" | ||||
|  | ||||
| (< and > should be to be entity escaped as < and >). If this | ||||
| version check is not met, then the element and its children will be | ||||
| ignored. This allows having alternate sections of the theme file for | ||||
| older and newer version of the Metacity theme format. | ||||
|  | ||||
| When placed on the toplevel <metacity_theme> element, an unsatisfied | ||||
| version check will not just cause the contents of the file to be | ||||
| ignored, it will also cause the lookup of a theme file to proceed on | ||||
| and look for an older format 2 or format 1 file. This allows making a | ||||
| metacity-theme-3.xml file that is only used the format version 3.2 or | ||||
| newer is supported, and using metacity-theme-1.xml for older window | ||||
| managers. | ||||
|  | ||||
| New Features in Theme Format Version 2 | ||||
| ====================================== | ||||
|  | ||||
| The optional attributes rounded_top_left, rounded_top_right, | ||||
| rounded_bottom_left and rounded_bottom_right on <frame_geometry> | ||||
| should now be the radius of the corner in pixels. You may still use | ||||
| the values "false" for 0 and "true" for 5, which means v1 values will | ||||
| still work just fine. | ||||
|  | ||||
| <frame_geometry> has a new optional attribute, hide_buttons. If this | ||||
| is true, no buttons will be displayed on the titlebar. | ||||
|  | ||||
| Anywhere you can use a positive integer, you can use an integer constant. | ||||
|  | ||||
| As well as constant integers and reals, you may define constant colours, | ||||
| thus: | ||||
|   <constant name="RevoltingPink" value="#FF00FF"/> | ||||
|   <constant name="Background" value="gtk:bg[NORMAL]"/> | ||||
|  | ||||
| <frame_style> has two new optional attributes, background and alpha. | ||||
| If you specify alpha, you must specify background. background is a | ||||
| colour used for the background of the frame. alpha is the transparency | ||||
| as a real between 0.0 and 1.0. If the current X server does not support | ||||
| alpha channels, the value is ignored. | ||||
|  | ||||
| The filename attribute of <image> may begin with "theme:". If so, the | ||||
| rest of the string is the name of a theme icon. The 64x64 version of the | ||||
| icon is used, except for fallback mini_icons, which use the 16x16 version. | ||||
| This does not affect ordinary resizing. For example: | ||||
|   <button function="close" state="normal"> | ||||
|     <draw_ops> | ||||
|       <include name="active_button"/> | ||||
|       <image filename="theme:gnome-logout" x="2" y="2" | ||||
|           width="width-4" height="height-4"/> | ||||
|       <!-- Note: not "theme:gnome-logout.png" or similar. --> | ||||
|     </draw_ops> | ||||
|   </button> | ||||
|  | ||||
| <menu_icon>s are parsed but ignored. | ||||
|  | ||||
| Fallback icons can be specified using <fallback>. There are two | ||||
| optional arguments, icon and mini_icon. The values of these arguments | ||||
| are identical to that of the filename attribute of <image>. Fallback | ||||
| icons are used when a window does not supply its own icon. If a fallback | ||||
| icon is not specified with <fallback>, Metacity will use a built-in | ||||
| icon, as in metacity-theme-1. | ||||
|  | ||||
| The <arc> element, as well as the original start_angle and end_angle | ||||
| attributes, may be given from and to attributes. The values of these | ||||
| attributes are given in degrees clockwise, with 0 being straight up. | ||||
| For example: | ||||
|   <arc from="0.0" to="90.0" filled="true" color="#FF00FF" | ||||
|       x="0" y="5" width="15" height="15"/> | ||||
|  | ||||
| <frame state="shaded"> may now take an optional resize attribute, with | ||||
| the same interpretation as the resize attribute on <frame state="normal">. | ||||
| If this attribute is omitted for state="shaded", it defaults to "both". | ||||
| (If it is omitted for state="normal", it remains an error.) | ||||
|  | ||||
| In addition to the four <button> functions which are required in | ||||
| metacity-theme-1, there are six new functions in metacity-theme-2: | ||||
| shade, unshade, above, unabove, stick and unstick. | ||||
|        | ||||
| Overview of Theme Format Version 1 | ||||
| ================================== | ||||
|  | ||||
| <?xml version="1.0"?> | ||||
| <metacity_theme> | ||||
| <!-- Only one info section is allowed --> | ||||
| <info> | ||||
|   <name>Foo</name> | ||||
|   <author>Foo P. Bar</author> | ||||
|   <copyright>whoever, 2002</copyright> | ||||
|   <date>Jan 31 2005</date> | ||||
|   <description>A sentence about the theme.</description> | ||||
| </info> | ||||
|  | ||||
| <!-- define a frame geometry to be referenced later --> | ||||
| <!-- frame_geometry has an optional has_title attribute which  | ||||
|      determines whether the title text height is included in the  | ||||
|      height calculation. if not specified, defaults to true. | ||||
|      It also has an optional text_size="medium" attribute | ||||
|      (same sizes as with Pango markup, xx-small thru medium thru | ||||
|      xx-large)  | ||||
|  | ||||
|      Finally it has optional args rounded_top_left=true,  | ||||
|      rounded_top_right=true, rounded_bottom_left=true, | ||||
|      rounded_bottom_right=true. | ||||
|  | ||||
|      --> | ||||
| <frame_geometry name="normal" has_title="true" title_scale="medium"> | ||||
|   <distance name="left_width" value="6"/> | ||||
|   <distance name="right_width" value="6"/> | ||||
|   <distance name="bottom_height" value="7"/> | ||||
|   <distance name="left_titlebar_edge" value="6"/> | ||||
|   <distance name="right_titlebar_edge" value="6"/> | ||||
|   <distance name="button_width" value="17"/> | ||||
|   <distance name="button_height" value="17"/> | ||||
|   <!-- alternative to button_width button_height distances --> | ||||
|   <aspect_ratio name="button" value="1.0"/> | ||||
|   <distance name="title_vertical_pad" value="4"/> | ||||
|   <border name="title_border" left="3" right="12" top="4" bottom="3"/> | ||||
|   <border name="button_border" left="0" right="0" top="1" bottom="1"/> | ||||
| </frame_geometry> | ||||
|  | ||||
| <!-- inheritance is allowed; simply overwrites values from parent --> | ||||
| <frame_geometry name="borderless" parent="normal"> | ||||
|   <distance name="left_width" value="0"/> | ||||
|   <distance name="right_width" value="0"/> | ||||
|   <distance name="bottom_height" value="0"/> | ||||
|   <distance name="left_titlebar_edge" value="0"/> | ||||
|   <distance name="right_titlebar_edge" value="0"/> | ||||
| </frame_geometry> | ||||
|  | ||||
| <!-- define a constant to use in positions/sizes of draw operations; | ||||
|      constant names must start with a capital letter. | ||||
|   --> | ||||
| <constant name="LineOffset" value="3"/> | ||||
|  | ||||
| <!-- define drawing operations to be referenced later;  | ||||
|      these draw-op lists can also be placed inline.  | ||||
|  | ||||
|      Positions/lengths are given as expressions. | ||||
|      Operators are: +,-,*,/,%,`max`,`min` | ||||
|      All operators are infix including `max` and `min`,  | ||||
|       i.e. "2 `max` 5" | ||||
|       | ||||
|      Some variables are predefined, and constants can also  | ||||
|      be used. Variables are: | ||||
|  | ||||
|        width - width of target area | ||||
|        height - height of target area | ||||
|        object_width - natural width of object being drawn | ||||
|        object_height - natural height of object being drawn | ||||
|        left_width - distance from left of frame to client window | ||||
|        right_width - distance from right of frame to client window | ||||
|        top_height - distance from top of frame to client window | ||||
|        bottom_height - distance from bottom of frame to client window | ||||
|        mini_icon_width - width of mini icon for window | ||||
|        mini_icon_height - height of mini icon | ||||
|        icon_width - width of large icon | ||||
|        icon_height - height of large icon | ||||
|        title_width - width of title text | ||||
|        title_height - height of title text | ||||
|  | ||||
|     All these are always defined, except object_width/object_height  | ||||
|     which only exists for <image> right now. | ||||
|  | ||||
|   --> | ||||
|  | ||||
| <draw_ops name="demo_all_ops"> | ||||
|   <line color="#00FF00" x1="LineOffset" y1="0" x2="0" y2="height"/> | ||||
|   <line color="gtk:fg[NORMAL]"  | ||||
|         x1="width - 1" y1="0" x2="width - 1" y2="height"  | ||||
|         width="3" dash_on_length="2" dash_off_length="3"/> | ||||
|   <rectangle color="blend/gtk:fg[NORMAL]/gtk:bg[NORMAL]/0.7" | ||||
|              x="0" y="0" width="width - 1" height="height - 1" filled="true"/> | ||||
|   <arc color="dark gray" x="0" y="0" width="width - 1" height="height - 1"  | ||||
|        filled="false" start_angle="30" extent_angle="180"/> | ||||
|   <tint color="orange" alpha="0.5" x="0" y="0" width="width" height="height"/> | ||||
|  <!-- may be vertical, horizontal, diagonal --> | ||||
|   <gradient type="diagonal"  | ||||
|             x="10" y="30" width="width / 3" height="height / 4"> | ||||
|     <!-- any number of colors allowed here. A color can be  | ||||
|          a color name like "blue" (look at gcolorsel), a hex color | ||||
|          as in HTML (#FFBB99), or a color from the gtk theme  | ||||
|          given as "gtk:base[NORMAL]", "gtk:fg[ACTIVE]", etc. | ||||
|        --> | ||||
|     <color value="gtk:fg[SELECTED]"/> | ||||
|     <!-- color obtained by a 0.5 alpha composite of the second color onto the first --> | ||||
|     <color value="blend/gtk:bg[SELECTED]/gtk:fg[SELECTED]/0.5"/> | ||||
|   </gradient> | ||||
|   <!-- image has an optional colorize="#color" attribute to give the | ||||
|        image a certain color --> | ||||
|   <image filename="foo.png" alpha="0.7" | ||||
|          x="10" y="30" width="width / 3" height="height / 4"/> | ||||
|   <gtk_arrow state="normal" shadow="in" arrow="up" | ||||
|              filled="true" | ||||
|              x="2" y="2" width="width - 4" height="height - 4"/> | ||||
|   <gtk_box state="normal" shadow="out" | ||||
|            x="2" y="2" width="width - 4" height="height - 4"/> | ||||
|   <gtk_vline state="normal" x="2" y1="0" y2="height"/> | ||||
|   <!-- window's icon --> | ||||
|   <icon alpha="0.7" | ||||
|         x="10" y="30" width="width / 3" height="height / 4"/> | ||||
|   <!-- window's title --> | ||||
|   <title color="gtk:text[NORMAL]" x="20" y="30"/> | ||||
|   <!-- include another draw ops list; has optional x/y/width/height attrs --> | ||||
|   <include name="some_other_draw_ops"/> | ||||
|   <!-- tile another draw ops list; has optional | ||||
|        x/y/width/height/tile_xoffset/tile_yoffset --> | ||||
|   <tile name="some_other_draw_ops" tile_width="10" tile_height="10"/> | ||||
| </draw_ops> | ||||
|  | ||||
| <frame_style name="normal" geometry="normal"> | ||||
|   <!-- How to draw each piece of the frame. | ||||
|        For each piece, a draw_ops can be given inline or referenced  | ||||
|        by name. If a piece is omitted, then nothing will be drawn  | ||||
|        for that piece. | ||||
|  | ||||
|        For each piece, the "width" and "height" variables in  | ||||
|        coordinate expressions refers to the dimensions of the piece,  | ||||
|        the origin is at the top left of the piece. | ||||
|    | ||||
|        So <rectangle x="0" y="0" width="width-1" height="height-1"/> | ||||
|        will outline a piece. | ||||
|     --> | ||||
|  | ||||
|   <piece position="entire_background" draw_ops="demo_all_ops"/> | ||||
|   <piece position="left_titlebar_edge"> | ||||
|     <draw_ops> | ||||
|       <line color="#00FF00" x1="0" y1="0" x2="0" y2="height"/> | ||||
|     </draw_ops> | ||||
|   </piece> | ||||
|  | ||||
|   <!-- The complete list of frame pieces: | ||||
|  | ||||
|        entire_background: whole frame | ||||
|        titlebar: entire area above the app's window  | ||||
|        titlebar_middle: area of titlebar_background not considered | ||||
|                         part of an edge | ||||
|        left_titlebar_edge: left side of titlebar background | ||||
|        right_titlebar_edge: right side of titlebar background | ||||
|        top_titlebar_edge: top side of titlebar background | ||||
|        bottom_titlebar_edge: bottom side of titlebar background  | ||||
|        title: the title area (doesn't include buttons) | ||||
|        left_edge: left edge of the frame | ||||
|        right_edge: right edge of the frame | ||||
|        bottom_edge: bottom edge of the frame | ||||
|        overlay: same area as entire_background, but drawn after  | ||||
|                 drawing all sub-pieces instead of before | ||||
|  | ||||
|    --> | ||||
|  | ||||
|   <!-- For buttons, drawing methods have to be provided for  | ||||
|        each of three states:  | ||||
|           normal, pressed, prelight | ||||
|        and the button function or position must be provided: | ||||
|           close, maximize, minimize, menu,  | ||||
|           left_left_background, left_middle_background, | ||||
|           left_right_background, right_left_background,  | ||||
|           right_middle_background, right_right_background | ||||
|        So a working theme needs 3*4 = 12 button declarations | ||||
|        and a theme may have up to 3*10 = 30 button declarations | ||||
|        in order to handle button-rearrangement preferences. | ||||
|   | ||||
|        (The name "function" for the attribute is from before the  | ||||
|         background values existed.) | ||||
|     --> | ||||
|  | ||||
|   <button function="close" state="normal" draw_ops="previously_named"/> | ||||
|   <button function="menu" state="normal"> | ||||
|     <draw_ops> | ||||
|       <icon alpha="0.7" | ||||
|             x="0" y="0" width="object_width" height="object_height"/> | ||||
|     </draw_ops> | ||||
|   </button> | ||||
|  | ||||
| </frame_style> | ||||
|  | ||||
| <!-- styles can inherit from each other with the parent="" attribute.  | ||||
|      In a subclass anything can be re-specified to override  | ||||
|      the parent style. --> | ||||
| <frame_style name="focused" parent="normal"> | ||||
|   <piece position="title"> | ||||
|     <draw_ops> | ||||
|       <rectangle color="gtk:bg[SELECTED]" | ||||
|                  x="0" y="0" width="width-1" height="height-1"/> | ||||
|       <title color="gtk:fg[SELECTED]" x="(width - title_width) / 2" | ||||
|                                       y="(height - title_height) / 2"/> | ||||
|     </draw_ops> | ||||
|   </piece> | ||||
| </frame_style> | ||||
|  | ||||
| <!-- Maps styles to states of frame.  | ||||
|  | ||||
|      Focus: yes (focused), no (not focused) | ||||
|      Window states: normal, maximized, shaded, maximized_and_shaded | ||||
|      Window resizability: none, vertical, horizontal, both | ||||
|  | ||||
|      Everything unspecified just does the same as | ||||
|      unfocused/normal/both. | ||||
|  | ||||
|      only state="normal" needs a resize="" attribute. | ||||
|  --> | ||||
| <frame_style_set name="normal"> | ||||
| <frame focus="yes" state="normal" resize="both" style="focused"/> | ||||
| <frame focus="no" state="normal" resize="both" style="normal"/> | ||||
| </frame_style_set> | ||||
|  | ||||
| <!-- Each window type needs a style set  | ||||
|      Types: normal, dialog, modal_dialog, menu, utility, border | ||||
|   --> | ||||
| <window type="normal" style_set="normal"/> | ||||
|  | ||||
|  | ||||
| <!-- For menu icons, drawing methods are needed for the same  | ||||
|      four types as the buttons, and GTK states | ||||
|      (insensitive,prelight,normal,etc.) | ||||
|   --> | ||||
|  | ||||
| <menu_icon function="close" state="normal" draw_ops="previously_named"/> | ||||
|  | ||||
|  | ||||
| </metacity_theme> | ||||
|  | ||||
|  | ||||
| @@ -22,9 +22,7 @@ src/core/screen.c | ||||
| src/core/util.c | ||||
| src/core/window.c | ||||
| src/ui/frames.c | ||||
| src/ui/resizepopup.c | ||||
| src/ui/theme.c | ||||
| src/ui/theme-parser.c | ||||
| src/x11/session.c | ||||
| src/x11/window-props.c | ||||
| src/x11/xprops.c | ||||
|   | ||||
| @@ -1 +1,2 @@ | ||||
| data/mutter-wayland.desktop.in | ||||
| # List of source files that should NOT be translated. | ||||
| # Please keep this file sorted alphabetically. | ||||
|   | ||||
							
								
								
									
										766
									
								
								po/bg.po
									
									
									
									
									
								
							
							
						
						
									
										766
									
								
								po/bg.po
									
									
									
									
									
								
							| @@ -1,9 +1,9 @@ | ||||
| # Bulgarian translation of mutter po-file. | ||||
| # Copyright (C) 2002, 2004, 2006, 2007, 2008 Free Software Foundation, Inc. | ||||
| # Copyright (C) 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. | ||||
| # Copyright (C) 2014 Free Software Foundation, Inc. | ||||
| # Copyright (C) 2014, 2015 Free Software Foundation, Inc. | ||||
| # Alexander Shopov <ash@kambanaria.org>, 2002, 2006, 2007, 2009, 2010. | ||||
| # Alexander Shopov <ash@kambanaria.org>, 2011, 2012, 2013, 2014. | ||||
| # Alexander Shopov <ash@kambanaria.org>, 2011, 2012, 2013, 2014, 2015. | ||||
| # Vladimir Petkov <kaladan@gmail.com>, 2004.  | ||||
| # Rostislav Raykov <zbrox@i-space.org>, 2004. | ||||
| # Yavor Doganov <yavor@gnu.org>, 2008. | ||||
| @@ -12,8 +12,8 @@ msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: mutter master\n" | ||||
| "Report-Msgid-Bugs-To: \n" | ||||
| "POT-Creation-Date: 2014-09-25 06:27+0300\n" | ||||
| "PO-Revision-Date: 2014-09-25 06:27+0300\n" | ||||
| "POT-Creation-Date: 2015-03-10 09:51+0200\n" | ||||
| "PO-Revision-Date: 2015-03-10 09:51+0200\n" | ||||
| "Last-Translator: Alexander Shopov <ash@kambanaria.org>\n" | ||||
| "Language-Team: Bulgarian <dict@fsa-bg.org>\n" | ||||
| "Language: bg\n" | ||||
| @@ -437,29 +437,49 @@ msgstr "Превключване към виртуална графична ко | ||||
| msgid "Switch to VT 7" | ||||
| msgstr "Превключване към виртуална графична конзола 7" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:412 | ||||
| #: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:8 | ||||
| msgid "Switch to VT 8" | ||||
| msgstr "Превключване към виртуална графична конзола 8" | ||||
|  | ||||
| #: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:9 | ||||
| msgid "Switch to VT 9" | ||||
| msgstr "Превключване към виртуална графична конзола 9" | ||||
|  | ||||
| #: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:10 | ||||
| msgid "Switch to VT 10" | ||||
| msgstr "Превключване към виртуална графична конзола 10" | ||||
|  | ||||
| #: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:11 | ||||
| msgid "Switch to VT 11" | ||||
| msgstr "Превключване към виртуална графична конзола 11" | ||||
|  | ||||
| #: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:12 | ||||
| msgid "Switch to VT 12" | ||||
| msgstr "Превключване към виртуална графична конзола 12" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:364 | ||||
| msgid "Built-in display" | ||||
| msgstr "Вграден екран" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:437 | ||||
| #: ../src/backends/meta-monitor-manager.c:391 | ||||
| msgid "Unknown" | ||||
| msgstr "Непознат" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:439 | ||||
| #: ../src/backends/meta-monitor-manager.c:393 | ||||
| msgid "Unknown Display" | ||||
| msgstr "Непознат екран" | ||||
|  | ||||
| #. TRANSLATORS: this is a monitor vendor name, followed by a | ||||
| #. * size in inches, like 'Dell 15"' | ||||
| #. | ||||
| #: ../src/backends/meta-monitor-manager.c:447 | ||||
| #: ../src/backends/meta-monitor-manager.c:401 | ||||
| #, c-format | ||||
| msgid "%s %s" | ||||
| msgstr "%s %s" | ||||
|  | ||||
| #. This probably means that a non-WM compositor like xcompmgr is running; | ||||
| #. * we have no way to get it to exit | ||||
| #: ../src/compositor/compositor.c:443 | ||||
| #: ../src/compositor/compositor.c:456 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Another compositing manager is already running on screen %i on display \"%s" | ||||
| @@ -495,7 +515,7 @@ msgstr "Из_чакване" | ||||
| msgid "_Force Quit" | ||||
| msgstr "_Принудително спиране" | ||||
|  | ||||
| #: ../src/core/display.c:547 | ||||
| #: ../src/core/display.c:562 | ||||
| #, c-format | ||||
| msgid "Failed to open X Window System display '%s'\n" | ||||
| msgstr "Неуспешно отваряне на дисплея на X Window „%s“\n" | ||||
| @@ -534,19 +554,6 @@ msgstr "Wayland да е мениджър за наслагване" | ||||
| msgid "Run as a full display server, rather than nested" | ||||
| msgstr "Изпълнение като самостоятелен, а не вграден сървър за изобразяване" | ||||
|  | ||||
| #: ../src/core/main.c:451 | ||||
| #, c-format | ||||
| msgid "Failed to scan themes directory: %s\n" | ||||
| msgstr "Неуспешно сканиране на папката с темите: %s\n" | ||||
|  | ||||
| #: ../src/core/main.c:467 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Could not find a theme! Be sure %s exists and contains the usual themes.\n" | ||||
| msgstr "" | ||||
| "Не е открита тема! Проверете дали папката „%s“ съществува и съдържа " | ||||
| "обичайните теми.\n" | ||||
|  | ||||
| #: ../src/core/mutter.c:39 | ||||
| #, c-format | ||||
| msgid "" | ||||
| @@ -571,718 +578,29 @@ msgstr "Отпечатване на версията на програмата" | ||||
| msgid "Mutter plugin to use" | ||||
| msgstr "Приставка, която да се ползва" | ||||
|  | ||||
| #: ../src/core/prefs.c:2065 | ||||
| #: ../src/core/prefs.c:2004 | ||||
| #, c-format | ||||
| msgid "Workspace %d" | ||||
| msgstr "Работен плот %d" | ||||
|  | ||||
| #: ../src/core/screen.c:543 | ||||
| #: ../src/core/screen.c:525 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Display \"%s\" already has a window manager; try using the --replace option " | ||||
| "to replace the current window manager." | ||||
| msgstr "" | ||||
| "Вече има мениджър на прозорци на дисплей „%s“. Пробвайте да го замените с " | ||||
| "опцията „--replace“." | ||||
|  | ||||
| #: ../src/core/screen.c:607 | ||||
| #, c-format | ||||
| msgid "Screen %d on display '%s' is invalid\n" | ||||
| msgstr "Екранът %d на дисплей „%s“ е невалиден\n" | ||||
|  | ||||
| #: ../src/core/screen.c:559 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Screen %d on display \"%s\" already has a window manager; try using the --" | ||||
| "replace option to replace the current window manager.\n" | ||||
| msgstr "" | ||||
| "Екранът %d на дисплей „%s“ вече има мениджър на прозорци; пробвайте да го " | ||||
| "замените с опцията --replace.\n" | ||||
|  | ||||
| #: ../src/core/screen.c:652 | ||||
| #, c-format | ||||
| msgid "Screen %d on display \"%s\" already has a window manager\n" | ||||
| msgstr "Екран %d на дисплей „%s“ вече има мениджър за прозорци\n" | ||||
|  | ||||
| #: ../src/core/util.c:118 | ||||
| msgid "Mutter was compiled without support for verbose mode\n" | ||||
| msgstr "Mutter е компилиран без поддръжка на подробен режим\n" | ||||
|  | ||||
| #. Translators: This represents the size of a window.  The first number is | ||||
| #. * the width of the window and the second is the height. | ||||
| #. | ||||
| #: ../src/ui/resizepopup.c:134 | ||||
| #, c-format | ||||
| msgid "%d x %d" | ||||
| msgstr "%d×%d" | ||||
|  | ||||
| #: ../src/ui/theme.c:233 | ||||
| msgid "top" | ||||
| msgstr "горния" | ||||
|  | ||||
| #: ../src/ui/theme.c:235 | ||||
| msgid "bottom" | ||||
| msgstr "долния" | ||||
|  | ||||
| #: ../src/ui/theme.c:237 | ||||
| msgid "left" | ||||
| msgstr "левия" | ||||
|  | ||||
| #: ../src/ui/theme.c:239 | ||||
| msgid "right" | ||||
| msgstr "десния" | ||||
|  | ||||
| #: ../src/ui/theme.c:267 | ||||
| #, c-format | ||||
| msgid "frame geometry does not specify \"%s\" dimension" | ||||
| msgstr "геометрията на рамката не указва %s размер" | ||||
|  | ||||
| #: ../src/ui/theme.c:286 | ||||
| #, c-format | ||||
| msgid "frame geometry does not specify dimension \"%s\" for border \"%s\"" | ||||
| msgstr "геометрията на рамката не указва %s размер на %s ръб" | ||||
|  | ||||
| #: ../src/ui/theme.c:323 | ||||
| #, c-format | ||||
| msgid "Button aspect ratio %g is not reasonable" | ||||
| msgstr "Отношението на размерите на бутона %g е неподходящо" | ||||
|  | ||||
| #: ../src/ui/theme.c:335 | ||||
| #, c-format | ||||
| msgid "Frame geometry does not specify size of buttons" | ||||
| msgstr "Геометрията на рамката не указва размера на бутоните" | ||||
|  | ||||
| #: ../src/ui/theme.c:1061 | ||||
| #, c-format | ||||
| msgid "Gradients should have at least two colors" | ||||
| msgstr "Преливките трябва да имат поне два цвята" | ||||
|  | ||||
| #: ../src/ui/theme.c:1211 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "GTK custom color specification must have color name and fallback in " | ||||
| "parentheses, e.g. gtk:custom(foo,bar); could not parse \"%s\"" | ||||
| msgstr "" | ||||
| "Цветовата спецификация на GTK трябва да съдържа в скоби име на основен и " | ||||
| "резервен цвят: напр. gtk:custom(foo,bar). Неуспешен анализ на „%s“" | ||||
|  | ||||
| #: ../src/ui/theme.c:1227 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-" | ||||
| "_ are valid" | ||||
| msgstr "" | ||||
| "Неправилен знак „%c“ в параметъра за име на цвят (color_name) на gtk:custom. " | ||||
| "Позволени са само A-Za-z0-9-_." | ||||
|  | ||||
| #: ../src/ui/theme.c:1241 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not " | ||||
| "fit the format" | ||||
| msgstr "" | ||||
| "Форматът на Gtk:custom е „gtk:custom(основен_цвят,резервен_цвят)“, „%s“ не " | ||||
| "съответства на формата" | ||||
|  | ||||
| #: ../src/ui/theme.c:1286 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "GTK color specification must have the state in brackets, e.g. gtk:fg[NORMAL] " | ||||
| "where NORMAL is the state; could not parse \"%s\"" | ||||
| msgstr "" | ||||
| "Цветовата спецификация на GTK трябва да указва състоянието в квадратни " | ||||
| "скоби, напр. gtk:fg[NORMAL], където NORMAL е състоянието. Неуспешен анализ " | ||||
| "на „%s“" | ||||
|  | ||||
| #: ../src/ui/theme.c:1300 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "GTK color specification must have a close bracket after the state, e.g. gtk:" | ||||
| "fg[NORMAL] where NORMAL is the state; could not parse \"%s\"" | ||||
| msgstr "" | ||||
| "Цветовата спецификация на GTK трябва да съдържа квадратна скоба след " | ||||
| "състоянието, напр. gtk:fg[NORMAL], където NORMAL е състоянието. Неуспешен " | ||||
| "анализ на „%s“" | ||||
|  | ||||
| #: ../src/ui/theme.c:1311 | ||||
| #, c-format | ||||
| msgid "Did not understand state \"%s\" in color specification" | ||||
| msgstr "Неуспешен анализ на състоянието „%s“ в цветовата спецификация" | ||||
|  | ||||
| #: ../src/ui/theme.c:1324 | ||||
| #, c-format | ||||
| msgid "Did not understand color component \"%s\" in color specification" | ||||
| msgstr "Неуспешен анализ на цветови компонент „%s“ в цветовата спецификация" | ||||
|  | ||||
| #: ../src/ui/theme.c:1352 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Blend format is \"blend/bg_color/fg_color/alpha\", \"%s\" does not fit the " | ||||
| "format" | ||||
| msgstr "" | ||||
| "Форматът на смесването е „blend/bg_color/fg_color/alpha“, „%s“ не се " | ||||
| "подчинява на форма̀та" | ||||
|  | ||||
| #: ../src/ui/theme.c:1363 | ||||
| #, c-format | ||||
| msgid "Could not parse alpha value \"%s\" in blended color" | ||||
| msgstr "Неуспешен анализ на алфа стойността „%s“ в смесения цвят" | ||||
|  | ||||
| #: ../src/ui/theme.c:1373 | ||||
| #, c-format | ||||
| msgid "Alpha value \"%s\" in blended color is not between 0.0 and 1.0" | ||||
| msgstr "Алфа стойността „%s“ в смесения цвят не е между 0.0 и 1.0" | ||||
|  | ||||
| #: ../src/ui/theme.c:1419 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Shade format is \"shade/base_color/factor\", \"%s\" does not fit the format" | ||||
| msgstr "" | ||||
| "Форматът на навиването е един от „shade“/„base_color“/„factor“, „%s“ не " | ||||
| "съответства на формата" | ||||
|  | ||||
| #: ../src/ui/theme.c:1430 | ||||
| #, c-format | ||||
| msgid "Could not parse shade factor \"%s\" in shaded color" | ||||
| msgstr "Неуспешен анализа на фактора на навиването „%s“ в цвета за навиване" | ||||
|  | ||||
| #: ../src/ui/theme.c:1440 | ||||
| #, c-format | ||||
| msgid "Shade factor \"%s\" in shaded color is negative" | ||||
| msgstr "Факторът на навиване „%s“ в цвета за сянката е отрицателен" | ||||
|  | ||||
| #: ../src/ui/theme.c:1469 | ||||
| #, c-format | ||||
| msgid "Could not parse color \"%s\"" | ||||
| msgstr "Неуспешен анализ на цвета „%s“" | ||||
|  | ||||
| #: ../src/ui/theme.c:1778 | ||||
| #, c-format | ||||
| msgid "Coordinate expression contains character '%s' which is not allowed" | ||||
| msgstr "Изразът за координати съдържа символа „%s“, който не е позволен" | ||||
|  | ||||
| #: ../src/ui/theme.c:1805 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Coordinate expression contains floating point number '%s' which could not be " | ||||
| "parsed" | ||||
| msgstr "" | ||||
| "Изразът за координати съдържа числото с плаваща запетая „%s“, което не може " | ||||
| "да бъде анализирано" | ||||
|  | ||||
| #: ../src/ui/theme.c:1819 | ||||
| #, c-format | ||||
| msgid "Coordinate expression contains integer '%s' which could not be parsed" | ||||
| msgstr "" | ||||
| "Изразът за координати съдържа цялото число „%s“, което не може да бъде " | ||||
| "анализирано" | ||||
|  | ||||
| #: ../src/ui/theme.c:1940 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Coordinate expression contained unknown operator at the start of this text: " | ||||
| "\"%s\"" | ||||
| msgstr "" | ||||
| "Изразът за координати съдържа непознат оператор в началото на този текст: " | ||||
| "„%s“" | ||||
|  | ||||
| #: ../src/ui/theme.c:1997 | ||||
| #, c-format | ||||
| msgid "Coordinate expression was empty or not understood" | ||||
| msgstr "Изразът за координати бе празен или не бе разбран" | ||||
|  | ||||
| #: ../src/ui/theme.c:2110 ../src/ui/theme.c:2120 ../src/ui/theme.c:2154 | ||||
| #, c-format | ||||
| msgid "Coordinate expression results in division by zero" | ||||
| msgstr "Изразът за координати дава деление на нула" | ||||
|  | ||||
| #: ../src/ui/theme.c:2162 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Coordinate expression tries to use mod operator on a floating-point number" | ||||
| msgstr "" | ||||
| "Изразът за координати използва оператора mod върху число с плаваща запетая" | ||||
|  | ||||
| #: ../src/ui/theme.c:2218 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Coordinate expression has an operator \"%s\" where an operand was expected" | ||||
| msgstr "" | ||||
| "Изразът за координати използва оператора „%s“ на място, където се очаква " | ||||
| "операнд" | ||||
|  | ||||
| #: ../src/ui/theme.c:2227 | ||||
| #, c-format | ||||
| msgid "Coordinate expression had an operand where an operator was expected" | ||||
| msgstr "" | ||||
| "Изразът за координати използва оператор на място, където се очаква операнд" | ||||
|  | ||||
| #: ../src/ui/theme.c:2235 | ||||
| #, c-format | ||||
| msgid "Coordinate expression ended with an operator instead of an operand" | ||||
| msgstr "Изразът за координати завършва с оператор вместо с операнд" | ||||
|  | ||||
| #: ../src/ui/theme.c:2245 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Coordinate expression has operator \"%c\" following operator \"%c\" with no " | ||||
| "operand in between" | ||||
| msgstr "" | ||||
| "Изразът за координати използва оператора „%c“ след „%c“ без да има операнд " | ||||
| "между тях" | ||||
|  | ||||
| #: ../src/ui/theme.c:2396 ../src/ui/theme.c:2441 | ||||
| #, c-format | ||||
| msgid "Coordinate expression had unknown variable or constant \"%s\"" | ||||
| msgstr "" | ||||
| "Изразът за координати използва непознатата променлива или константа „%s“" | ||||
|  | ||||
| #: ../src/ui/theme.c:2495 | ||||
| #, c-format | ||||
| msgid "Coordinate expression parser overflowed its buffer." | ||||
| msgstr "Анализаторът на изрази за координати препълни буфера си." | ||||
|  | ||||
| #: ../src/ui/theme.c:2524 | ||||
| #, c-format | ||||
| msgid "Coordinate expression had a close parenthesis with no open parenthesis" | ||||
| msgstr "В израза за координати има затваряща скоба без съответна отваряща" | ||||
|  | ||||
| #: ../src/ui/theme.c:2588 | ||||
| #, c-format | ||||
| msgid "Coordinate expression had an open parenthesis with no close parenthesis" | ||||
| msgstr "В израза за координати има отваряща скоба без съответна затваряща" | ||||
|  | ||||
| #: ../src/ui/theme.c:2599 | ||||
| #, c-format | ||||
| msgid "Coordinate expression doesn't seem to have any operators or operands" | ||||
| msgstr "Изразът за координати не съдържа нито оператори, нито операнди" | ||||
|  | ||||
| #: ../src/ui/theme.c:2812 ../src/ui/theme.c:2832 ../src/ui/theme.c:2852 | ||||
| #, c-format | ||||
| msgid "Theme contained an expression that resulted in an error: %s\n" | ||||
| msgstr "Темата съдържа израз, който даде грешка: %s\n" | ||||
|  | ||||
| #: ../src/ui/theme.c:4455 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/> must be " | ||||
| "specified for this frame style" | ||||
| msgstr "" | ||||
| "За този стил на рамката трябва да се укаже <button function=\"%s\" state=\"%s" | ||||
| "\" draw_ops=\"нещо си\"/>" | ||||
|  | ||||
| #: ../src/ui/theme.c:4970 ../src/ui/theme.c:4995 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>" | ||||
| msgstr "" | ||||
| "Липсва <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"нещо си\"/>" | ||||
|  | ||||
| #: ../src/ui/theme.c:5041 | ||||
| #, c-format | ||||
| msgid "Failed to load theme \"%s\": %s\n" | ||||
| msgstr "Неуспешно зареждане на темата „%s“: %s\n" | ||||
|  | ||||
| #: ../src/ui/theme.c:5177 ../src/ui/theme.c:5184 ../src/ui/theme.c:5191 | ||||
| #: ../src/ui/theme.c:5198 ../src/ui/theme.c:5205 | ||||
| #, c-format | ||||
| msgid "No <%s> set for theme \"%s\"" | ||||
| msgstr "Не е даден елементът <%s> за темата „%s“" | ||||
|  | ||||
| #: ../src/ui/theme.c:5213 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "No frame style set for window type \"%s\" in theme \"%s\", add a <window " | ||||
| "type=\"%s\" style_set=\"whatever\"/> element" | ||||
| msgstr "" | ||||
| "Няма указан стил на рамката за „%s“ прозорците в тема „%s“. Добавете елемент " | ||||
| "<window type=\"%s\" style_set=\"нещо си\"/>" | ||||
|  | ||||
| #: ../src/ui/theme.c:5620 ../src/ui/theme.c:5682 ../src/ui/theme.c:5745 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "User-defined constants must begin with a capital letter; \"%s\" does not" | ||||
| msgstr "" | ||||
| "Константите определени от потребителя трябва да започват с главна буква, а " | ||||
| "„%s“ не започва така" | ||||
|  | ||||
| #: ../src/ui/theme.c:5628 ../src/ui/theme.c:5690 ../src/ui/theme.c:5753 | ||||
| #, c-format | ||||
| msgid "Constant \"%s\" has already been defined" | ||||
| msgstr "Константата „%s“ вече е дефинирана" | ||||
|  | ||||
| #. Translators: This means that an attribute which should have been found | ||||
| #. * on an XML element was not in fact found. | ||||
| #. | ||||
| #: ../src/ui/theme-parser.c:234 | ||||
| #, c-format | ||||
| msgid "No \"%s\" attribute on element <%s>" | ||||
| msgstr "Елементът <%s> няма атрибут „%s“" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:263 ../src/ui/theme-parser.c:281 | ||||
| #, c-format | ||||
| msgid "Line %d character %d: %s" | ||||
| msgstr "Ред %d, знак %d: %s" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:481 | ||||
| #, c-format | ||||
| msgid "Attribute \"%s\" repeated twice on the same <%s> element" | ||||
| msgstr "Атрибутът „%s“ се повтаря два пъти в един елемент <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:505 ../src/ui/theme-parser.c:554 | ||||
| #, c-format | ||||
| msgid "Attribute \"%s\" is invalid on <%s> element in this context" | ||||
| msgstr "Атрибутът „%s“ е невалиден за елемента <%s> в този контекст" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:596 | ||||
| #, c-format | ||||
| msgid "Could not parse \"%s\" as an integer" | ||||
| msgstr "„%s“ не може да се анализира като цяло число" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:605 ../src/ui/theme-parser.c:660 | ||||
| #, c-format | ||||
| msgid "Did not understand trailing characters \"%s\" in string \"%s\"" | ||||
| msgstr "Крайните символи „%s“ в низа „%s“ са неразбираеми" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:615 | ||||
| #, c-format | ||||
| msgid "Integer %ld must be positive" | ||||
| msgstr "Цялото число %ld трябва да е положително" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:623 | ||||
| #, c-format | ||||
| msgid "Integer %ld is too large, current max is %d" | ||||
| msgstr "Цялото число %ld е прекалено голямо, максимумът е %d" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:651 ../src/ui/theme-parser.c:767 | ||||
| #, c-format | ||||
| msgid "Could not parse \"%s\" as a floating point number" | ||||
| msgstr "„%s“ не може да се интерпретира като число с плаваща запетая" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:682 ../src/ui/theme-parser.c:710 | ||||
| #, c-format | ||||
| msgid "Boolean values must be \"true\" or \"false\" not \"%s\"" | ||||
| msgstr "" | ||||
| "Булевите стойности са или „true“ (истина), или „false“ (лъжа). Не са „%s“" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:737 | ||||
| #, c-format | ||||
| msgid "Angle must be between 0.0 and 360.0, was %g\n" | ||||
| msgstr "Ъгълът трябва да е между 0.0 и 360.0, а е %g\n" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:800 | ||||
| #, c-format | ||||
| msgid "Alpha must be between 0.0 (invisible) and 1.0 (fully opaque), was %g\n" | ||||
| msgstr "" | ||||
| "Алфа трябва да е между 0.0 (пълна прозрачност) и 1.0 (пълна непрозрачност), " | ||||
| "а е %g\n" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:865 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Invalid title scale \"%s\" (must be one of xx-small,x-small,small,medium," | ||||
| "large,x-large,xx-large)\n" | ||||
| msgstr "" | ||||
| "Невалидно увеличение на заглавието „%s“ (трябва да е едно от „xx-small“ (най-" | ||||
| "малко), „x-small“ (много малко), „small“ (малко), „medium“ (средно), " | ||||
| "„large“ (голямо), „x-large“ (много голямо), „xx-large“ (най-голямо))\n" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1021 ../src/ui/theme-parser.c:1084 | ||||
| #: ../src/ui/theme-parser.c:1118 ../src/ui/theme-parser.c:1221 | ||||
| #, c-format | ||||
| msgid "<%s> name \"%s\" used a second time" | ||||
| msgstr "Името „%2$s“ на <%1$s> е използвано втори път" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1033 ../src/ui/theme-parser.c:1130 | ||||
| #: ../src/ui/theme-parser.c:1233 | ||||
| #, c-format | ||||
| msgid "<%s> parent \"%s\" has not been defined" | ||||
| msgstr "Родителят „%2$s“ на <%1$s> не е дефиниран" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1143 | ||||
| #, c-format | ||||
| msgid "<%s> geometry \"%s\" has not been defined" | ||||
| msgstr "Геометрията „%2$s“ на <%1$s> не е дефинирана" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1156 | ||||
| #, c-format | ||||
| msgid "<%s> must specify either a geometry or a parent that has a geometry" | ||||
| msgstr "<%s> трябва да указва или геометрия, или родител с геометрия" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1198 | ||||
| msgid "You must specify a background for an alpha value to be meaningful" | ||||
| msgstr "За да бъде алфа стойността валидна, трябва да е указан фон" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1266 | ||||
| #, c-format | ||||
| msgid "Unknown type \"%s\" on <%s> element" | ||||
| msgstr "Непознат вид „%s“ на елемента <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1277 | ||||
| #, c-format | ||||
| msgid "Unknown style_set \"%s\" on <%s> element" | ||||
| msgstr "Непознат style_set „%s“ на елемента <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1285 | ||||
| #, c-format | ||||
| msgid "Window type \"%s\" has already been assigned a style set" | ||||
| msgstr "Видът прозорци „%s“ вече има установен вид на стила" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1315 ../src/ui/theme-parser.c:1379 | ||||
| #: ../src/ui/theme-parser.c:1605 ../src/ui/theme-parser.c:2840 | ||||
| #: ../src/ui/theme-parser.c:2886 ../src/ui/theme-parser.c:3036 | ||||
| #: ../src/ui/theme-parser.c:3272 ../src/ui/theme-parser.c:3310 | ||||
| #: ../src/ui/theme-parser.c:3348 ../src/ui/theme-parser.c:3386 | ||||
| #, c-format | ||||
| msgid "Element <%s> is not allowed below <%s>" | ||||
| msgstr "Елементът <%s> не е позволен под <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1429 ../src/ui/theme-parser.c:1443 | ||||
| #: ../src/ui/theme-parser.c:1488 | ||||
| msgid "" | ||||
| "Cannot specify both \"button_width\"/\"button_height\" and \"aspect_ratio\" " | ||||
| "for buttons" | ||||
| msgstr "" | ||||
| "Не може да се указват едновременно и двата размера („button_width“, " | ||||
| "„button_height“ — височина и широчина на бутоните), и съотношението на " | ||||
| "размерите им — „aspect_ratio“" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1452 | ||||
| #, c-format | ||||
| msgid "Distance \"%s\" is unknown" | ||||
| msgstr "Разстоянието „%s“ е неизвестно" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1497 | ||||
| #, c-format | ||||
| msgid "Aspect ratio \"%s\" is unknown" | ||||
| msgstr "Пропорцията „%s“ е неизвестна" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1559 | ||||
| #, c-format | ||||
| msgid "Border \"%s\" is unknown" | ||||
| msgstr "Границата „%s“ е непозната" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1870 | ||||
| #, c-format | ||||
| msgid "No \"start_angle\" or \"from\" attribute on element <%s>" | ||||
| msgstr "Елементът <%s> няма атрибут „start_angle“ или „from“" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1877 | ||||
| #, c-format | ||||
| msgid "No \"extent_angle\" or \"to\" attribute on element <%s>" | ||||
| msgstr "Елементът <%s> няма атрибут „extent_angle“ или „to“" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2117 | ||||
| #, c-format | ||||
| msgid "Did not understand value \"%s\" for type of gradient" | ||||
| msgstr "Стойността „%s“ не може да се анализира като вид градиент" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2195 ../src/ui/theme-parser.c:2570 | ||||
| #, c-format | ||||
| msgid "Did not understand fill type \"%s\" for <%s> element" | ||||
| msgstr "Непознато запълване „%s“ за елемента <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2362 ../src/ui/theme-parser.c:2445 | ||||
| #: ../src/ui/theme-parser.c:2508 | ||||
| #, c-format | ||||
| msgid "Did not understand state \"%s\" for <%s> element" | ||||
| msgstr "Неуспешен анализ на състоянието „%s“ на елемента <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2372 ../src/ui/theme-parser.c:2455 | ||||
| #, c-format | ||||
| msgid "Did not understand shadow \"%s\" for <%s> element" | ||||
| msgstr "Неуспешен анализ на сянката „%s“ на елемента <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2382 | ||||
| #, c-format | ||||
| msgid "Did not understand arrow \"%s\" for <%s> element" | ||||
| msgstr "Неуспешен анализ на стрелката „%s“ на елемента <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2696 ../src/ui/theme-parser.c:2792 | ||||
| #, c-format | ||||
| msgid "No <draw_ops> called \"%s\" has been defined" | ||||
| msgstr "Няма дефинирани <draw_ops> с име „%s“" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2708 ../src/ui/theme-parser.c:2804 | ||||
| #, c-format | ||||
| msgid "Including draw_ops \"%s\" here would create a circular reference" | ||||
| msgstr "Включването на draw_ops „%s“ тук би предизвикало циклична зависимост" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2919 | ||||
| #, c-format | ||||
| msgid "Unknown position \"%s\" for frame piece" | ||||
| msgstr "Непозната позиция „%s“ за елемент на рамката" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2927 | ||||
| #, c-format | ||||
| msgid "Frame style already has a piece at position %s" | ||||
| msgstr "Стилът на рамката вече има елемент на позицията %s" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2944 ../src/ui/theme-parser.c:3021 | ||||
| #, c-format | ||||
| msgid "No <draw_ops> with the name \"%s\" has been defined" | ||||
| msgstr "Няма дефиниран <draw_ops> с името „%s“" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2974 | ||||
| #, c-format | ||||
| msgid "Unknown function \"%s\" for button" | ||||
| msgstr "Непозната функция „%s“ за бутона" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2984 | ||||
| #, c-format | ||||
| msgid "Button function \"%s\" does not exist in this version (%d, need %d)" | ||||
| msgstr "" | ||||
| "Функцията на бутона „%s“ не съществува в тази версия (%d, а трябва да е %d)" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2996 | ||||
| #, c-format | ||||
| msgid "Unknown state \"%s\" for button" | ||||
| msgstr "Непознато състояние „%s“ за бутона" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3004 | ||||
| #, c-format | ||||
| msgid "Frame style already has a button for function %s state %s" | ||||
| msgstr "Стилът на рамката има бутон за функция %s, състояние %s" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3075 | ||||
| #, c-format | ||||
| msgid "\"%s\" is not a valid value for focus attribute" | ||||
| msgstr "„%s“ не е валидна стойност за атрибута фокус" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3084 | ||||
| #, c-format | ||||
| msgid "\"%s\" is not a valid value for state attribute" | ||||
| msgstr "„%s“ не е валидна стойност за атрибута състояние" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3094 | ||||
| #, c-format | ||||
| msgid "A style called \"%s\" has not been defined" | ||||
| msgstr "Не е дефиниран стил на име  „%s“" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3115 ../src/ui/theme-parser.c:3138 | ||||
| #, c-format | ||||
| msgid "\"%s\" is not a valid value for resize attribute" | ||||
| msgstr "„%s“ не е валидна стойност за атрибута оразмеряване" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3149 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Should not have \"resize\" attribute on <%s> element for maximized/shaded " | ||||
| "states" | ||||
| msgstr "" | ||||
| "Елементът <%s> не трябва да има атрибут „resize“ за състоянията максимизиран/" | ||||
| "засенчен" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3163 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Should not have \"resize\" attribute on <%s> element for maximized states" | ||||
| msgstr "" | ||||
| "Елементът <%s> не трябва да има атрибут „resize“ за състоянието максимизиран" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3177 ../src/ui/theme-parser.c:3221 | ||||
| #, c-format | ||||
| msgid "Style has already been specified for state %s resize %s focus %s" | ||||
| msgstr "Вече е указан стил за състояние %s, оразмеряване %s, фокус %s" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3188 ../src/ui/theme-parser.c:3199 | ||||
| #: ../src/ui/theme-parser.c:3210 ../src/ui/theme-parser.c:3232 | ||||
| #: ../src/ui/theme-parser.c:3243 ../src/ui/theme-parser.c:3254 | ||||
| #, c-format | ||||
| msgid "Style has already been specified for state %s focus %s" | ||||
| msgstr "Вече е указан стил за състояние %s, фокус %s" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3293 | ||||
| msgid "" | ||||
| "Can't have a two draw_ops for a <piece> element (theme specified a draw_ops " | ||||
| "attribute and also a <draw_ops> element, or specified two elements)" | ||||
| msgstr "" | ||||
| "Не може да има два draw_ops за елемент <piece> (темата е указала атрибут " | ||||
| "draw_ops и елемент <draw_ops> или два елемента)" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3331 | ||||
| msgid "" | ||||
| "Can't have a two draw_ops for a <button> element (theme specified a draw_ops " | ||||
| "attribute and also a <draw_ops> element, or specified two elements)" | ||||
| msgstr "" | ||||
| "Не може да има два draw_ops за елемент <button> (темата е указала атрибут " | ||||
| "draw_ops и елемент <draw_ops> или два елемента)" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3369 | ||||
| msgid "" | ||||
| "Can't have a two draw_ops for a <menu_icon> element (theme specified a " | ||||
| "draw_ops attribute and also a <draw_ops> element, or specified two elements)" | ||||
| msgstr "" | ||||
| "Не може да има два draw_ops за елемент <menu_icon> (темата е указала атрибут " | ||||
| "draw_ops и елемент <draw_ops> или два елемента)" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3433 | ||||
| #, c-format | ||||
| msgid "Bad version specification '%s'" | ||||
| msgstr "Неправилна версия „%s“" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3506 | ||||
| msgid "" | ||||
| "\"version\" attribute cannot be used in metacity-theme-1.xml or metacity-" | ||||
| "theme-2.xml" | ||||
| msgstr "" | ||||
| "Атрибутът „version“ (версия) не може да се използва в in metacity-theme-1." | ||||
| "xml или metacity-theme-2.xml" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3529 | ||||
| #, c-format | ||||
| msgid "Theme requires version %s but latest supported theme version is %d.%d" | ||||
| msgstr "Темата изисква версия %s, но най-високата поддържана версия е %d.%d" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3561 | ||||
| #, c-format | ||||
| msgid "Outermost element in theme must be <metacity_theme> not <%s>" | ||||
| msgstr "Най-външният елемент в темата трябва да е <metacity_theme>, а не <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3581 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Element <%s> is not allowed inside a name/author/date/description element" | ||||
| msgstr "Елементът <%s> не е разрешен в елементите name/author/date/description" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3586 | ||||
| #, c-format | ||||
| msgid "Element <%s> is not allowed inside a <constant> element" | ||||
| msgstr "Елементът <%s> не е позволен в <constant> елемент" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3598 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Element <%s> is not allowed inside a distance/border/aspect_ratio element" | ||||
| msgstr "Елементът <%s> не е позволен в елемент distance/border/aspect_ratio" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3620 | ||||
| #, c-format | ||||
| msgid "Element <%s> is not allowed inside a draw operation element" | ||||
| msgstr "Елементът <%s> не е позволен в елемент с операция за чертане" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3630 ../src/ui/theme-parser.c:3660 | ||||
| #: ../src/ui/theme-parser.c:3665 ../src/ui/theme-parser.c:3670 | ||||
| #, c-format | ||||
| msgid "Element <%s> is not allowed inside a <%s> element" | ||||
| msgstr "Елементът <%s> не е позволен в елемент <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3898 | ||||
| msgid "No draw_ops provided for frame piece" | ||||
| msgstr "Няма draw_ops за детайл от рамката" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3913 | ||||
| msgid "No draw_ops provided for button" | ||||
| msgstr "Няма draw_ops за бутон" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3967 | ||||
| #, c-format | ||||
| msgid "No text is allowed inside element <%s>" | ||||
| msgstr "Не е позволен текст в елемента <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:4025 ../src/ui/theme-parser.c:4037 | ||||
| #: ../src/ui/theme-parser.c:4049 ../src/ui/theme-parser.c:4061 | ||||
| #: ../src/ui/theme-parser.c:4073 | ||||
| #, c-format | ||||
| msgid "<%s> specified twice for this theme" | ||||
| msgstr "<%s> е указан два пъти за тази тема" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:4335 | ||||
| #, c-format | ||||
| msgid "Failed to find a valid file for theme %s\n" | ||||
| msgstr "Не е намерен валиден файл за темата %s\n" | ||||
|  | ||||
| #: ../src/x11/session.c:1815 | ||||
| msgid "" | ||||
| "These windows do not support "save current setup" and will have to " | ||||
| @@ -1291,7 +609,7 @@ msgstr "" | ||||
| "Тези прозорци не поддържат операцията по записване на текущото състояние и " | ||||
| "ще трябва да се стартират ръчно при следващото ви влизане." | ||||
|  | ||||
| #: ../src/x11/window-props.c:558 | ||||
| #: ../src/x11/window-props.c:549 | ||||
| #, c-format | ||||
| msgid "%s (on %s)" | ||||
| msgstr "%s (от %s)" | ||||
|   | ||||
							
								
								
									
										751
									
								
								po/bs.po
									
									
									
									
									
								
							
							
						
						
									
										751
									
								
								po/bs.po
									
									
									
									
									
								
							| @@ -8,8 +8,8 @@ msgstr "" | ||||
| "Project-Id-Version: gsettings-desktop-schemas\n" | ||||
| "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" | ||||
| "product=mutter&keywords=I18N+L10N&component=general\n" | ||||
| "POT-Creation-Date: 2015-02-26 23:15+0000\n" | ||||
| "PO-Revision-Date: 2015-02-04 15:40+0000\n" | ||||
| "POT-Creation-Date: 2015-02-26 23:17+0000\n" | ||||
| "PO-Revision-Date: 2015-03-02 14:51+0100\n" | ||||
| "Last-Translator: Belma Skopljakovic <belma_skop14@hotmail.com>\n" | ||||
| "Language-Team: Bosnian <bs@li.org>\n" | ||||
| "Language: bs\n" | ||||
| @@ -17,7 +17,7 @@ msgstr "" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
| "X-Launchpad-Export-Date: 2015-02-05 07:04+0000\n" | ||||
| "X-Generator: Launchpad (build 17331)\n" | ||||
| "X-Generator: Poedit 1.7.4\n" | ||||
|  | ||||
| #: ../data/50-mutter-navigation.xml.in.h:1 | ||||
| msgid "Navigation" | ||||
| @@ -435,22 +435,42 @@ msgstr "Prebaci na VT 6" | ||||
| msgid "Switch to VT 7" | ||||
| msgstr "Prebaci na VT 7" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:375 | ||||
| #: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:8 | ||||
| msgid "Switch to VT 8" | ||||
| msgstr "Prebaci na VT 8" | ||||
|  | ||||
| #: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:9 | ||||
| msgid "Switch to VT 9" | ||||
| msgstr "Prebaci na VT 9" | ||||
|  | ||||
| #: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:10 | ||||
| msgid "Switch to VT 10" | ||||
| msgstr "Prebaci na VT 10" | ||||
|  | ||||
| #: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:11 | ||||
| msgid "Switch to VT 11" | ||||
| msgstr "Prebaci na VT 11" | ||||
|  | ||||
| #: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:12 | ||||
| msgid "Switch to VT 12" | ||||
| msgstr "Prebaci na VT 12" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:364 | ||||
| msgid "Built-in display" | ||||
| msgstr "Konstruiši na display" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:400 | ||||
| #: ../src/backends/meta-monitor-manager.c:391 | ||||
| msgid "Unknown" | ||||
| msgstr "Nepoznato" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:402 | ||||
| #: ../src/backends/meta-monitor-manager.c:393 | ||||
| msgid "Unknown Display" | ||||
| msgstr "Nepoznat ekran" | ||||
|  | ||||
| #. TRANSLATORS: this is a monitor vendor nami, followed by a | ||||
| #. * size in inches, liki 'Dell 15"' | ||||
| #. | ||||
| #: ../src/backends/meta-monitor-manager.c:410 | ||||
| #: ../src/backends/meta-monitor-manager.c:401 | ||||
| #, c-format | ||||
| msgid "%s %s" | ||||
| msgstr "%s %s" | ||||
| @@ -495,7 +515,7 @@ msgstr "_Čekaj" | ||||
| msgid "_Force Quit" | ||||
| msgstr "_Prisili izlaz" | ||||
|  | ||||
| #: ../src/core/display.c:550 | ||||
| #: ../src/core/display.c:562 | ||||
| #, c-format | ||||
| msgid "Failed to open X Window System display '%s'\n" | ||||
| msgstr "Neuspjeh pri otvaranju X Window Sistem prikaza %s'\n" | ||||
| @@ -532,19 +552,6 @@ msgstr "Pokreni kao wayland kompozitor" | ||||
| msgid "Run as a full display server, rather than nested" | ||||
| msgstr "Pokreni kao puni prikaz servera, umjesto uklopljenog" | ||||
|  | ||||
| #: ../src/core/main.c:451 | ||||
| #, c-format | ||||
| msgid "Failed to scan themes directory: %s\n" | ||||
| msgstr "Neuspjeh pri skeniranju direktorija tema: %s\n" | ||||
|  | ||||
| #: ../src/core/main.c:467 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Could not find a theme! Be sure %s exists and contains the usual themes.\n" | ||||
| msgstr "" | ||||
| "Nisam mogao da pronđem temu! Provjerite da %s postoji i da sadrži uobičajne " | ||||
| "teme.\n" | ||||
|  | ||||
| #: ../src/core/mutter.c:39 | ||||
| #, c-format | ||||
| msgid "" | ||||
| @@ -568,707 +575,29 @@ msgstr "Ispiši verziju" | ||||
| msgid "Mutter plugin to use" | ||||
| msgstr "Mutter plugin to usi" | ||||
|  | ||||
| #: ../src/core/prefs.c:2064 | ||||
| #: ../src/core/prefs.c:2004 | ||||
| #, c-format | ||||
| msgid "Workspace %d" | ||||
| msgstr "Radni prostor %d" | ||||
|  | ||||
| #: ../src/core/screen.c:534 | ||||
| #: ../src/core/screen.c:525 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Display \"%s\" already has a window manager; try using the --replace option " | ||||
| "to replace the current window manager." | ||||
| msgstr "" | ||||
| "Ekran  \"%s\" već ima upravitelja prozora; pokušajte koristiti --replace " | ||||
| "opciju da zamjenite trenutni upravitelj prozora." | ||||
|  | ||||
| #: ../src/core/screen.c:607 | ||||
| #, c-format | ||||
| msgid "Screen %d on display '%s' is invalid\n" | ||||
| msgstr "Ekran %d na prikazu '%s' je neispravan\n" | ||||
|  | ||||
| #: ../src/core/screen.c:550 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Screen %d on display \"%s\" already has a window manager; try using the --" | ||||
| "replace option to replace the current window manager.\n" | ||||
| msgstr "" | ||||
| "Ekran %d na prikazu \"%s\" već ima upravitelja prozora; pokušajte koristiti " | ||||
| "--replace opciju da zamjenite trenutni upravitelj prozora.\n" | ||||
|  | ||||
| #: ../src/core/screen.c:643 | ||||
| #, c-format | ||||
| msgid "Screen %d on display \"%s\" already has a window manager\n" | ||||
| msgstr "Ekran %d na prikazu \"%s\" već ima rukovoditelja prozora\n" | ||||
|  | ||||
| #: ../src/core/util.c:118 | ||||
| msgid "Mutter was compiled without support for verbose mode\n" | ||||
| msgstr "Mutter je kompajliran bez podrške verbose načina\n" | ||||
|  | ||||
| #. Translators: This represents the size of a window.  The first number is | ||||
| #. * the width of the window and the second is the height. | ||||
| #. | ||||
| #: ../src/ui/resizepopup.c:134 | ||||
| #, c-format | ||||
| msgid "%d x %d" | ||||
| msgstr "%d x %d" | ||||
|  | ||||
| #: ../src/ui/theme.c:233 | ||||
| msgid "top" | ||||
| msgstr "vrh" | ||||
|  | ||||
| #: ../src/ui/theme.c:235 | ||||
| msgid "bottom" | ||||
| msgstr "dno" | ||||
|  | ||||
| #: ../src/ui/theme.c:237 | ||||
| msgid "left" | ||||
| msgstr "lijevo" | ||||
|  | ||||
| #: ../src/ui/theme.c:239 | ||||
| msgid "right" | ||||
| msgstr "desno" | ||||
|  | ||||
| #: ../src/ui/theme.c:267 | ||||
| #, c-format | ||||
| msgid "frame geometry does not specify \"%s\" dimension" | ||||
| msgstr "geometrija okvira ne navodi „%s“ dimenziju" | ||||
|  | ||||
| #: ../src/ui/theme.c:286 | ||||
| #, c-format | ||||
| msgid "frame geometry does not specify dimension \"%s\" for border \"%s\"" | ||||
| msgstr "geometrija okvira ne navodi „%s“ dimenziju za rub „%s“" | ||||
|  | ||||
| #: ../src/ui/theme.c:323 | ||||
| #, c-format | ||||
| msgid "Button aspect ratio %g is not reasonable" | ||||
| msgstr "Razmjera dugmeta %g nije razumna" | ||||
|  | ||||
| #: ../src/ui/theme.c:335 | ||||
| #, c-format | ||||
| msgid "Frame geometry does not specify size of buttons" | ||||
| msgstr "Geometrija oblika nije odredila veličinu dugmadi." | ||||
|  | ||||
| #: ../src/ui/theme.c:1061 | ||||
| #, c-format | ||||
| msgid "Gradients should have at least two colors" | ||||
| msgstr "Gradijent mora imati barem dvije boje" | ||||
|  | ||||
| #: ../src/ui/theme.c:1211 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "GTK custom color specification must have color name and fallback in " | ||||
| "parentheses, e.g. gtk:custom(foo,bar); could not parse \"%s\"" | ||||
| msgstr "" | ||||
| "GTK uobičajna specifikacija boje mora imati ime boje i zamjensko u " | ||||
| "zagradama, e.g. gtk:obično(foo,bar); ne može raščlaniti \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:1227 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-" | ||||
| "_ are valid" | ||||
| msgstr "" | ||||
| "Pogrešan znak '%c' u boja_ime parametar od gtk:obično, samo A-Za-z0-9-_su " | ||||
| "ispravni" | ||||
|  | ||||
| #: ../src/ui/theme.c:1241 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not " | ||||
| "fit the format" | ||||
| msgstr "" | ||||
| "Gtk:obično format je \"gtk:obično(boja_ime,fallback)\", \"%s\" se ne uklapa " | ||||
| "u format" | ||||
|  | ||||
| #: ../src/ui/theme.c:1286 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "GTK color specification must have the state in brackets, e.g. gtk:fg[NORMAL] " | ||||
| "where NORMAL is the state; could not parse \"%s\"" | ||||
| msgstr "" | ||||
| "GTK specifikacija boje mora imati stanje u zagradi,naprimjer  gtk:fg" | ||||
| "[NORMAL]  gdje je NORMAL stanje;nije moguće analizirati \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:1300 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "GTK color specification must have a close bracket after the state, e.g. gtk:" | ||||
| "fg[NORMAL] where NORMAL is the state; could not parse \"%s\"" | ||||
| msgstr "" | ||||
| "GTK specifikacija boje mora imati zatvorenu zagradu poslije stanja," | ||||
| "naprimjer  gtk:fg[NORMAL] gdje je NORMAL stanje;nije moguće analizirati \"%s" | ||||
| "\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:1311 | ||||
| #, c-format | ||||
| msgid "Did not understand state \"%s\" in color specification" | ||||
| msgstr "Nisam shvatio stanje \"%s\" u izboru boja" | ||||
|  | ||||
| #: ../src/ui/theme.c:1324 | ||||
| #, c-format | ||||
| msgid "Did not understand color component \"%s\" in color specification" | ||||
| msgstr "Ne razumijem komponentu boje \"%s\" u  izboru boja" | ||||
|  | ||||
| #: ../src/ui/theme.c:1352 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Blend format is \"blend/bg_color/fg_color/alpha\", \"%s\" does not fit the " | ||||
| "format" | ||||
| msgstr "" | ||||
| "Format miješanja „blend/bg_color/fg_color/alpha“, „%s“ se ne uklapa u " | ||||
| "traženi format zapisa" | ||||
|  | ||||
| #: ../src/ui/theme.c:1363 | ||||
| #, c-format | ||||
| msgid "Could not parse alpha value \"%s\" in blended color" | ||||
| msgstr "Nije moguće analizirati alfa vrijednost  \"%s\" u nijansnoj boji" | ||||
|  | ||||
| #: ../src/ui/theme.c:1373 | ||||
| #, c-format | ||||
| msgid "Alpha value \"%s\" in blended color is not between 0.0 and 1.0" | ||||
| msgstr "Alfa vrijednost \"%s\" u nijansiranoj boji nije između 0.0 i 1.0" | ||||
|  | ||||
| #: ../src/ui/theme.c:1419 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Shade format is \"shade/base_color/factor\", \"%s\" does not fit the format" | ||||
| msgstr "" | ||||
| "Format osjenčenja je \"shade/base_color/factor\", \"%s\" ne odgovara formatu" | ||||
|  | ||||
| #: ../src/ui/theme.c:1430 | ||||
| #, c-format | ||||
| msgid "Could not parse shade factor \"%s\" in shaded color" | ||||
| msgstr "Nije moguće analizirati faktor sjenčenja \"%s\" u sjenčenim bojama" | ||||
|  | ||||
| #: ../src/ui/theme.c:1440 | ||||
| #, c-format | ||||
| msgid "Shade factor \"%s\" in shaded color is negative" | ||||
| msgstr "Faktor sjenčenja \"%s\" u zasjenčenoj boji je negativan" | ||||
|  | ||||
| #: ../src/ui/theme.c:1469 | ||||
| #, c-format | ||||
| msgid "Could not parse color \"%s\"" | ||||
| msgstr "Nije moguće analizirati boju \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:1778 | ||||
| #, c-format | ||||
| msgid "Coordinate expression contains character '%s' which is not allowed" | ||||
| msgstr "Izraz koordinata sadrži karakter '%s'  koji nije dozvoljen" | ||||
|  | ||||
| #: ../src/ui/theme.c:1805 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Coordinate expression contains floating point number '%s' which could not be " | ||||
| "parsed" | ||||
| msgstr "" | ||||
| "Izraz koordinata sadrži broj sa pokretnom točkom '%s' koji nije mogao biti " | ||||
| "analiziran" | ||||
|  | ||||
| #: ../src/ui/theme.c:1819 | ||||
| #, c-format | ||||
| msgid "Coordinate expression contains integer '%s' which could not be parsed" | ||||
| msgstr "" | ||||
| "Izraz koordinata sadrži cijeli broj '%s' koji nije mogao biti analiziran" | ||||
|  | ||||
| #: ../src/ui/theme.c:1940 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Coordinate expression contained unknown operator at the start of this text: " | ||||
| "\"%s\"" | ||||
| msgstr "" | ||||
| "Izraz koordinata sadrži nepoznati operator na početku ovog teksta \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:1997 | ||||
| #, c-format | ||||
| msgid "Coordinate expression was empty or not understood" | ||||
| msgstr "Izraz koordinata je bio prazan ili nije shvatio" | ||||
|  | ||||
| #: ../src/ui/theme.c:2110 ../src/ui/theme.c:2120 ../src/ui/theme.c:2154 | ||||
| #, c-format | ||||
| msgid "Coordinate expression results in division by zero" | ||||
| msgstr "Izraz koordinata je rezultat podjele sa nulom" | ||||
|  | ||||
| #: ../src/ui/theme.c:2162 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Coordinate expression tries to use mod operator on a floating-point number" | ||||
| msgstr "" | ||||
| "Izraz koordinata pokušava upotrijebiti mod operator na broju sa pomičnim " | ||||
| "zarezom" | ||||
|  | ||||
| #: ../src/ui/theme.c:2218 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Coordinate expression has an operator \"%s\" where an operand was expected" | ||||
| msgstr "Izraz koordinata ima operator \"%s\" gdje se očekivao operand" | ||||
|  | ||||
| #: ../src/ui/theme.c:2227 | ||||
| #, c-format | ||||
| msgid "Coordinate expression had an operand where an operator was expected" | ||||
| msgstr "Izraz koordinata je imao operand a očekivao se operator" | ||||
|  | ||||
| #: ../src/ui/theme.c:2235 | ||||
| #, c-format | ||||
| msgid "Coordinate expression ended with an operator instead of an operand" | ||||
| msgstr "Izraz koordinata je završio sa operatorom umjesto operanda" | ||||
|  | ||||
| #: ../src/ui/theme.c:2245 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Coordinate expression has operator \"%c\" following operator \"%c\" with no " | ||||
| "operand in between" | ||||
| msgstr "" | ||||
| "Izraz koordinata ima operator \"%c\" koji prati operator  \"%c\" ali bez " | ||||
| "operacija između" | ||||
|  | ||||
| #: ../src/ui/theme.c:2396 ../src/ui/theme.c:2441 | ||||
| #, c-format | ||||
| msgid "Coordinate expression had unknown variable or constant \"%s\"" | ||||
| msgstr "Izraz koordinata je imao nepoznatu varijablu ili konstantu  \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:2495 | ||||
| #, c-format | ||||
| msgid "Coordinate expression parser overflowed its buffer." | ||||
| msgstr "Izraz sa koordinatama je bio preveliki za smještaj i obradu." | ||||
|  | ||||
| #: ../src/ui/theme.c:2524 | ||||
| #, c-format | ||||
| msgid "Coordinate expression had a close parenthesis with no open parenthesis" | ||||
| msgstr "Izraz koordinata je morao zatvoriti zagrade sa ne otvorenim zagradama." | ||||
|  | ||||
| #: ../src/ui/theme.c:2588 | ||||
| #, c-format | ||||
| msgid "Coordinate expression had an open parenthesis with no close parenthesis" | ||||
| msgstr "Izraz koordinata je imao otvorene zagrade sa ne zatvorenim zagradama" | ||||
|  | ||||
| #: ../src/ui/theme.c:2599 | ||||
| #, c-format | ||||
| msgid "Coordinate expression doesn't seem to have any operators or operands" | ||||
| msgstr "Izraz koordinata izgleda ne sadrži operacije ili operante." | ||||
|  | ||||
| #: ../src/ui/theme.c:2812 ../src/ui/theme.c:2832 ../src/ui/theme.c:2852 | ||||
| #, c-format | ||||
| msgid "Theme contained an expression that resulted in an error: %s\n" | ||||
| msgstr "Tema je sadržavala izraz koji je rezultirao greškom: %s\n" | ||||
|  | ||||
| #: ../src/ui/theme.c:4455 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/> must be " | ||||
| "specified for this frame style" | ||||
| msgstr "" | ||||
| "<button function=\"%s\" state=\"%s\" draw_ops=\"svejedno\"/> mora biti " | ||||
| "određeno za format ovog okvira" | ||||
|  | ||||
| #: ../src/ui/theme.c:4970 ../src/ui/theme.c:4995 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>" | ||||
| msgstr "" | ||||
| "Nedostaje <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"svejedno\"/>" | ||||
|  | ||||
| #: ../src/ui/theme.c:5041 | ||||
| #, c-format | ||||
| msgid "Failed to load theme \"%s\": %s\n" | ||||
| msgstr "Nije uspjelo učitavanje teme \"%s\": %s\n" | ||||
|  | ||||
| #: ../src/ui/theme.c:5177 ../src/ui/theme.c:5184 ../src/ui/theme.c:5191 | ||||
| #: ../src/ui/theme.c:5198 ../src/ui/theme.c:5205 | ||||
| #, c-format | ||||
| msgid "No <%s> set for theme \"%s\"" | ||||
| msgstr "Nije podešen <%s> za temu \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:5213 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "No frame style set for window type \"%s\" in theme \"%s\", add a <window " | ||||
| "type=\"%s\" style_set=\"whatever\"/> element" | ||||
| msgstr "" | ||||
| "Nije odabrana vrsta okvira za prozor tipa  \"%s\" u temi  \"%s\", dodajte " | ||||
| "<window type=\"%s\" style_set=\"svejedno\"/> element" | ||||
|  | ||||
| #: ../src/ui/theme.c:5620 ../src/ui/theme.c:5682 ../src/ui/theme.c:5745 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "User-defined constants must begin with a capital letter; \"%s\" does not" | ||||
| msgstr "" | ||||
| "Korisnički definisane konstante moraju početi velikim slovom; \"%s\" ne " | ||||
| "počinje" | ||||
|  | ||||
| #: ../src/ui/theme.c:5628 ../src/ui/theme.c:5690 ../src/ui/theme.c:5753 | ||||
| #, c-format | ||||
| msgid "Constant \"%s\" has already been defined" | ||||
| msgstr "Konstanta \"%s\" je već definisana" | ||||
|  | ||||
| #. Translators: This means that an attribute which should have been found | ||||
| #. * on an XML element was not in fact found. | ||||
| #. | ||||
| #: ../src/ui/theme-parser.c:234 | ||||
| #, c-format | ||||
| msgid "No \"%s\" attribute on element <%s>" | ||||
| msgstr "Nije definisan „%s“ atribut u elementu <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:263 ../src/ui/theme-parser.c:281 | ||||
| #, c-format | ||||
| msgid "Line %d character %d: %s" | ||||
| msgstr "Linija %d karakter %d: %s" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:481 | ||||
| #, c-format | ||||
| msgid "Attribute \"%s\" repeated twice on the same <%s> element" | ||||
| msgstr "Atribut „%s“ je ponovljen dva puta u istom elementu <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:505 ../src/ui/theme-parser.c:554 | ||||
| #, c-format | ||||
| msgid "Attribute \"%s\" is invalid on <%s> element in this context" | ||||
| msgstr "Atribut \"%s\" je nevažeći na <%s> elementu u ovom kontekstu" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:596 | ||||
| #, c-format | ||||
| msgid "Could not parse \"%s\" as an integer" | ||||
| msgstr "Nije moguće analizirati  \"%s\" kao cijeli broj" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:605 ../src/ui/theme-parser.c:660 | ||||
| #, c-format | ||||
| msgid "Did not understand trailing characters \"%s\" in string \"%s\"" | ||||
| msgstr "Ne razumijem karaktere \"%s\" u stringu \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:615 | ||||
| #, c-format | ||||
| msgid "Integer %ld must be positive" | ||||
| msgstr "Cijeli broj %ld mora biti pozitivan" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:623 | ||||
| #, c-format | ||||
| msgid "Integer %ld is too large, current max is %d" | ||||
| msgstr "Cijeli broj  %ld je prevelik ,trenutno najveći je %d" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:651 ../src/ui/theme-parser.c:767 | ||||
| #, c-format | ||||
| msgid "Could not parse \"%s\" as a floating point number" | ||||
| msgstr "Nije moguće analizirati  \"%s\" kao broj sa pomičnim  zarezom" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:682 ../src/ui/theme-parser.c:710 | ||||
| #, c-format | ||||
| msgid "Boolean values must be \"true\" or \"false\" not \"%s\"" | ||||
| msgstr "Logičke vrijednosti moraju biti \"true\" ili \"false\", a ne \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:737 | ||||
| #, c-format | ||||
| msgid "Angle must be between 0.0 and 360.0, was %g\n" | ||||
| msgstr "Ugao mora biti između 0.0 i 360.0, bio %g\n" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:800 | ||||
| #, c-format | ||||
| msgid "Alpha must be between 0.0 (invisible) and 1.0 (fully opaque), was %g\n" | ||||
| msgstr "" | ||||
| "Alfa osobina mora biti između 0.0 (nevidljivo) i 1.0 (potpuno neprozirno), " | ||||
| "bila je %g\n" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:865 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Invalid title scale \"%s\" (must be one of xx-small,x-small,small,medium," | ||||
| "large,x-large,xx-large)\n" | ||||
| msgstr "" | ||||
| "Neispravna veličina naslova \"%s\" (mora biti jedna od xx-mala,x-mala,mala," | ||||
| "srednja,velika,x-velika,xx-velika)\n" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1021 ../src/ui/theme-parser.c:1084 | ||||
| #: ../src/ui/theme-parser.c:1118 ../src/ui/theme-parser.c:1221 | ||||
| #, c-format | ||||
| msgid "<%s> name \"%s\" used a second time" | ||||
| msgstr "<%s> ime \"%s\" se  već drugi put koristi" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1033 ../src/ui/theme-parser.c:1130 | ||||
| #: ../src/ui/theme-parser.c:1233 | ||||
| #, c-format | ||||
| msgid "<%s> parent \"%s\" has not been defined" | ||||
| msgstr "<%s> izvor \"%s\" nije definisan" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1143 | ||||
| #, c-format | ||||
| msgid "<%s> geometry \"%s\" has not been defined" | ||||
| msgstr "<%s> geometrija \"%s\" se nije definisala" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1156 | ||||
| #, c-format | ||||
| msgid "<%s> must specify either a geometry or a parent that has a geometry" | ||||
| msgstr "<%s> mora odrediti geometriju ili izvor koji ima geometriju" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1198 | ||||
| msgid "You must specify a background for an alpha value to be meaningful" | ||||
| msgstr "Morate navesti pozadinu da bi alfa vrijednost imala smisla" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1266 | ||||
| #, c-format | ||||
| msgid "Unknown type \"%s\" on <%s> element" | ||||
| msgstr "Nepoznat tip \"%s\" na elementu <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1277 | ||||
| #, c-format | ||||
| msgid "Unknown style_set \"%s\" on <%s> element" | ||||
| msgstr "Nepoznat style_set \"%s\" na elementu <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1285 | ||||
| #, c-format | ||||
| msgid "Window type \"%s\" has already been assigned a style set" | ||||
| msgstr "Vrsti prozora \"%s\" je već dodijeljena grupa stilova" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1315 ../src/ui/theme-parser.c:1379 | ||||
| #: ../src/ui/theme-parser.c:1605 ../src/ui/theme-parser.c:2840 | ||||
| #: ../src/ui/theme-parser.c:2886 ../src/ui/theme-parser.c:3036 | ||||
| #: ../src/ui/theme-parser.c:3272 ../src/ui/theme-parser.c:3310 | ||||
| #: ../src/ui/theme-parser.c:3348 ../src/ui/theme-parser.c:3386 | ||||
| #, c-format | ||||
| msgid "Element <%s> is not allowed below <%s>" | ||||
| msgstr "Element  <%s> nije dozvoljen ispod <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1429 ../src/ui/theme-parser.c:1443 | ||||
| #: ../src/ui/theme-parser.c:1488 | ||||
| msgid "" | ||||
| "Cannot specify both \"button_width\"/\"button_height\" and \"aspect_ratio\" " | ||||
| "for buttons" | ||||
| msgstr "Ne mogu da podesim i širinu/visinu i razmjeru dugmadi" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1452 | ||||
| #, c-format | ||||
| msgid "Distance \"%s\" is unknown" | ||||
| msgstr "Udaljenost \"%s\" je nepoznata" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1497 | ||||
| #, c-format | ||||
| msgid "Aspect ratio \"%s\" is unknown" | ||||
| msgstr "Odnos \"%s\" je nepoznat" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1559 | ||||
| #, c-format | ||||
| msgid "Border \"%s\" is unknown" | ||||
| msgstr "Okvir „%s“ je nepoznat" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1870 | ||||
| #, c-format | ||||
| msgid "No \"start_angle\" or \"from\" attribute on element <%s>" | ||||
| msgstr "Nije definisan „start_angle“ ili „from“ atribut u elementu <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1877 | ||||
| #, c-format | ||||
| msgid "No \"extent_angle\" or \"to\" attribute on element <%s>" | ||||
| msgstr "Nije definisan „extent_angle“ ili „to“ atribut u elementu <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2117 | ||||
| #, c-format | ||||
| msgid "Did not understand value \"%s\" for type of gradient" | ||||
| msgstr "Nisam shvatio vrijednost \"%s\" za vrstu stepenovanja" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2195 ../src/ui/theme-parser.c:2570 | ||||
| #, c-format | ||||
| msgid "Did not understand fill type \"%s\" for <%s> element" | ||||
| msgstr "Nisam shvatio vrstu popunjavanja  \"%s\" za <%s> element" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2362 ../src/ui/theme-parser.c:2445 | ||||
| #: ../src/ui/theme-parser.c:2508 | ||||
| #, c-format | ||||
| msgid "Did not understand state \"%s\" for <%s> element" | ||||
| msgstr "Nisam shvatio stanje \"%s\" za <%s> element" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2372 ../src/ui/theme-parser.c:2455 | ||||
| #, c-format | ||||
| msgid "Did not understand shadow \"%s\" for <%s> element" | ||||
| msgstr "Nisam shvatio sjenu \"%s\" za <%s> element" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2382 | ||||
| #, c-format | ||||
| msgid "Did not understand arrow \"%s\" for <%s> element" | ||||
| msgstr "Ne razumijmem strelicu \"%s\" za <%s> element" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2696 ../src/ui/theme-parser.c:2792 | ||||
| #, c-format | ||||
| msgid "No <draw_ops> called \"%s\" has been defined" | ||||
| msgstr "Nije podešen <draw_ops> imena  \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2708 ../src/ui/theme-parser.c:2804 | ||||
| #, c-format | ||||
| msgid "Including draw_ops \"%s\" here would create a circular reference" | ||||
| msgstr "Uključivanje draw_ops \"%s\" ovdje bi kreiralo kružnu napomenu" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2919 | ||||
| #, c-format | ||||
| msgid "Unknown position \"%s\" for frame piece" | ||||
| msgstr "Nepoznata pozicija \"%s\" za dio okvira" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2927 | ||||
| #, c-format | ||||
| msgid "Frame style already has a piece at position %s" | ||||
| msgstr "Stil okvira već ima dio na poziciji %s" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2944 ../src/ui/theme-parser.c:3021 | ||||
| #, c-format | ||||
| msgid "No <draw_ops> with the name \"%s\" has been defined" | ||||
| msgstr "Nije podešen <draw_ops>sa imenom  \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2974 | ||||
| #, c-format | ||||
| msgid "Unknown function \"%s\" for button" | ||||
| msgstr "Nepoznata funkcija \"%s\" za dugme" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2984 | ||||
| #, c-format | ||||
| msgid "Button function \"%s\" does not exist in this version (%d, need %d)" | ||||
| msgstr "" | ||||
| "Funkcija „%s“ za dugme ne postoji u ovoj verziji (verzija %d, a treba vam %d)" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2996 | ||||
| #, c-format | ||||
| msgid "Unknown state \"%s\" for button" | ||||
| msgstr "Nepoznato stanje \"%s\" za dugme" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3004 | ||||
| #, c-format | ||||
| msgid "Frame style already has a button for function %s state %s" | ||||
| msgstr "Stil okvira već ima dugme za funkciju %s stanja %s" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3075 | ||||
| #, c-format | ||||
| msgid "\"%s\" is not a valid value for focus attribute" | ||||
| msgstr "\"%s“ nije dozvoljena vrijednost za osobinu fokusa" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3084 | ||||
| #, c-format | ||||
| msgid "\"%s\" is not a valid value for state attribute" | ||||
| msgstr "\"%s\" nije dozvoljena vrijednost za svojstvo stanja" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3094 | ||||
| #, c-format | ||||
| msgid "A style called \"%s\" has not been defined" | ||||
| msgstr "Stil nazvan \"%s\" nije bio određen" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3115 ../src/ui/theme-parser.c:3138 | ||||
| #, c-format | ||||
| msgid "\"%s\" is not a valid value for resize attribute" | ||||
| msgstr "\"%s\" nije dozvoljena vrijednost za osobinu resize" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3149 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Should not have \"resize\" attribute on <%s> element for maximized/shaded " | ||||
| "states" | ||||
| msgstr "" | ||||
| "Nikako ne treba imati „resize“ atribut u elementu <%s> za uvećana/zasjenčena " | ||||
| "stanja" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3163 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Should not have \"resize\" attribute on <%s> element for maximized states" | ||||
| msgstr "" | ||||
| "Nikako ne treba imati „resize“ atribut u elementu <%s> za uvećana stanja" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3177 ../src/ui/theme-parser.c:3221 | ||||
| #, c-format | ||||
| msgid "Style has already been specified for state %s resize %s focus %s" | ||||
| msgstr "Stil je već odabran za stanje %s promjene veličine %s fokusiranja %s" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3188 ../src/ui/theme-parser.c:3199 | ||||
| #: ../src/ui/theme-parser.c:3210 ../src/ui/theme-parser.c:3232 | ||||
| #: ../src/ui/theme-parser.c:3243 ../src/ui/theme-parser.c:3254 | ||||
| #, c-format | ||||
| msgid "Style has already been specified for state %s focus %s" | ||||
| msgstr "Stil je već odabran za stanje %s fokusiranja %s" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3293 | ||||
| msgid "" | ||||
| "Can't have a two draw_ops for a <piece> element (theme specified a draw_ops " | ||||
| "attribute and also a <draw_ops> element, or specified two elements)" | ||||
| msgstr "" | ||||
| "Ne mogu postojati dva draw_ops-a za element <piece> (tema navodi svojstvo " | ||||
| "draw_ops  i <draw_ops> element ili navodi dva elementa)" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3331 | ||||
| msgid "" | ||||
| "Can't have a two draw_ops for a <button> element (theme specified a draw_ops " | ||||
| "attribute and also a <draw_ops> element, or specified two elements)" | ||||
| msgstr "" | ||||
| "Ne mogu postojati dva draw_ops-a za element <button> (tema navodi draw_ops " | ||||
| "svojstvo i <draw_ops> element ili navodi dva elementa)" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3369 | ||||
| msgid "" | ||||
| "Can't have a two draw_ops for a <menu_icon> element (theme specified a " | ||||
| "draw_ops attribute and also a <draw_ops> element, or specified two elements)" | ||||
| msgstr "" | ||||
| "Ne mogu postojati dva draw_ops-a za element <menu_icon> (tema navodi " | ||||
| "svojstvo draw_ops i <draw_ops> element ili navodi dva elementa)" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3433 | ||||
| #, c-format | ||||
| msgid "Bad version specification '%s'" | ||||
| msgstr "Neispravna verzija specifikacije '%s'" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3506 | ||||
| msgid "" | ||||
| "\"version\" attribute cannot be used in metacity-theme-1.xml or metacity-" | ||||
| "theme-2.xml" | ||||
| msgstr "" | ||||
| "\"version\" atribut se ne može koristiti u metacity-theme-1.xml ili metacity-" | ||||
| "theme-2.xml" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3529 | ||||
| #, c-format | ||||
| msgid "Theme requires version %s but latest supported theme version is %d.%d" | ||||
| msgstr "Tema zahtjeva verziju %s ali posljednja podržana verzija teme je %d.%d" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3561 | ||||
| #, c-format | ||||
| msgid "Outermost element in theme must be <metacity_theme> not <%s>" | ||||
| msgstr "Najdalji element u temi mora biti <metacity_theme> a ne<%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3581 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Element <%s> is not allowed inside a name/author/date/description element" | ||||
| msgstr "Element <%s> nije dozvoljen unutar imena/autora/datuma/opisa ." | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3586 | ||||
| #, c-format | ||||
| msgid "Element <%s> is not allowed inside a <constant> element" | ||||
| msgstr "Element <%s> nije dozvoljen unutar <constant> elementa" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3598 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Element <%s> is not allowed inside a distance/border/aspect_ratio element" | ||||
| msgstr "" | ||||
| "Element <%s> nije dozvoljen unutar udaljenost/granica/omjer_slike elementa" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3620 | ||||
| #, c-format | ||||
| msgid "Element <%s> is not allowed inside a draw operation element" | ||||
| msgstr "Element <%s> nije dozvoljen unutar operacije crtanja" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3630 ../src/ui/theme-parser.c:3660 | ||||
| #: ../src/ui/theme-parser.c:3665 ../src/ui/theme-parser.c:3670 | ||||
| #, c-format | ||||
| msgid "Element <%s> is not allowed inside a <%s> element" | ||||
| msgstr "Element <%s> nije dozvoljen unutar <%s> elementa" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3898 | ||||
| msgid "No draw_ops provided for frame piece" | ||||
| msgstr "Bez draw_ops datih komadu okvira" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3913 | ||||
| msgid "No draw_ops provided for button" | ||||
| msgstr "Bez draw_ops datih dugmetu" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3967 | ||||
| #, c-format | ||||
| msgid "No text is allowed inside element <%s>" | ||||
| msgstr "Tekst nije dozvoljen unutar elementa<%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:4025 ../src/ui/theme-parser.c:4037 | ||||
| #: ../src/ui/theme-parser.c:4049 ../src/ui/theme-parser.c:4061 | ||||
| #: ../src/ui/theme-parser.c:4073 | ||||
| #, c-format | ||||
| msgid "<%s> specified twice for this theme" | ||||
| msgstr "Element <%s> je naveden dva puta u ovoj temi" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:4335 | ||||
| #, c-format | ||||
| msgid "Failed to find a valid file for theme %s\n" | ||||
| msgstr "Nisam uspio da pronađem ispravnu datoteku za temu %s\n" | ||||
|  | ||||
| #: ../src/x11/session.c:1815 | ||||
| msgid "" | ||||
| "These windows do not support "save current setup" and will have to " | ||||
| @@ -1277,7 +606,7 @@ msgstr "" | ||||
| "Ovi prozori ne podržavaju mogućnost „snimi trenutna podešavanja“ pa ćete " | ||||
| "morati da ih ručno ponovo pokrenete kada se sljedeći put prijavite." | ||||
|  | ||||
| #: ../src/x11/window-props.c:558 | ||||
| #: ../src/x11/window-props.c:549 | ||||
| #, c-format | ||||
| msgid "%s (on %s)" | ||||
| msgstr "%s (na %s)" | ||||
|   | ||||
							
								
								
									
										818
									
								
								po/fr.po
									
									
									
									
									
								
							
							
						
						
									
										818
									
								
								po/fr.po
									
									
									
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| # French translation of mutter. | ||||
| # Copyright (C) 2002-2014 Free Software Foundation, Inc. | ||||
| # Copyright (C) 2002-2015 Free Software Foundation, Inc. | ||||
| # This file is distributed under the same license as the metacity package. | ||||
| # | ||||
| # Christophe Fergeau <teuf@users.sourceforge.net>, 2002. | ||||
| @@ -11,17 +11,16 @@ | ||||
| # Cyprien Le Pannérer <cyplp@free.fr>, 2006. | ||||
| # Robert-André Mauchin <zebob.m@gmail.com>, 2007.  | ||||
| # Stéphane Raimbault <stephane.raimbault@gmail.com>, 2007. | ||||
| # Claude Paroz <claude@2xlibre.net>, 2008-2014. | ||||
| # Claude Paroz <claude@2xlibre.net>, 2008-2015. | ||||
| # Bruno Brouard <annoa.b@gmail.com>, 2011-12. | ||||
| # | ||||
| msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: mutter masterReport-Msgid-Bugs-To: http://bugzilla.gnome." | ||||
| "org/enter_bug.cgi?product=mutter&component=general\n" | ||||
| "Project-Id-Version: mutter master\n" | ||||
| "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" | ||||
| "product=mutter&keywords=I18N+L10N&component=general\n" | ||||
| "POT-Creation-Date: 2014-08-29 21:52+0000\n" | ||||
| "PO-Revision-Date: 2014-08-30 11:59+0200\n" | ||||
| "POT-Creation-Date: 2015-02-23 23:11+0000\n" | ||||
| "PO-Revision-Date: 2015-02-24 10:08+0100\n" | ||||
| "Last-Translator: Claude Paroz <claude@2xlibre.net>\n" | ||||
| "Language-Team: GNOME French Team <gnomefr@traduc.org>\n" | ||||
| "Language: fr\n" | ||||
| @@ -408,8 +407,8 @@ msgid "" | ||||
| "When true, the new windows will always be put in the center of the active " | ||||
| "screen of the monitor." | ||||
| msgstr "" | ||||
| "Si true (vrai), les nouvelles fenêtres seront toujours placées au centre " | ||||
| "de l'écran actif du moniteur." | ||||
| "Si true (vrai), les nouvelles fenêtres seront toujours placées au centre de " | ||||
| "l'écran actif du moniteur." | ||||
|  | ||||
| #: ../data/org.gnome.mutter.gschema.xml.in.h:21 | ||||
| msgid "Select window from tab popup" | ||||
| @@ -449,29 +448,49 @@ msgstr "Passer à l'émulateur de terminal 6" | ||||
| msgid "Switch to VT 7" | ||||
| msgstr "Passer à l'émulateur de terminal 7" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:412 | ||||
| #: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:8 | ||||
| msgid "Switch to VT 8" | ||||
| msgstr "Passer à l'émulateur de terminal 8" | ||||
|  | ||||
| #: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:9 | ||||
| msgid "Switch to VT 9" | ||||
| msgstr "Passer à l'émulateur de terminal 9" | ||||
|  | ||||
| #: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:10 | ||||
| msgid "Switch to VT 10" | ||||
| msgstr "Passer à l'émulateur de terminal 10" | ||||
|  | ||||
| #: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:11 | ||||
| msgid "Switch to VT 11" | ||||
| msgstr "Passer à l'émulateur de terminal 11" | ||||
|  | ||||
| #: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:12 | ||||
| msgid "Switch to VT 12" | ||||
| msgstr "Passer à l'émulateur de terminal 12" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:364 | ||||
| msgid "Built-in display" | ||||
| msgstr "Affichage intégré" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:437 | ||||
| #: ../src/backends/meta-monitor-manager.c:391 | ||||
| msgid "Unknown" | ||||
| msgstr "Inconnu" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:439 | ||||
| #: ../src/backends/meta-monitor-manager.c:393 | ||||
| msgid "Unknown Display" | ||||
| msgstr "Affichage inconnu" | ||||
|  | ||||
| #. TRANSLATORS: this is a monitor vendor name, followed by a | ||||
| #. * size in inches, like 'Dell 15"' | ||||
| #. | ||||
| #: ../src/backends/meta-monitor-manager.c:447 | ||||
| #: ../src/backends/meta-monitor-manager.c:401 | ||||
| #, c-format | ||||
| msgid "%s %s" | ||||
| msgstr "%s %s" | ||||
|  | ||||
| #. This probably means that a non-WM compositor like xcompmgr is running; | ||||
| #. * we have no way to get it to exit | ||||
| #: ../src/compositor/compositor.c:443 | ||||
| #: ../src/compositor/compositor.c:456 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Another compositing manager is already running on screen %i on display \"%s" | ||||
| @@ -480,10 +499,6 @@ msgstr "" | ||||
| "Un autre gestionnaire de composition est déjà lancé sur l'écran %i de " | ||||
| "l'affichage « %s »." | ||||
|  | ||||
| #: ../src/compositor/meta-background.c:1044 | ||||
| msgid "background texture could not be created from file" | ||||
| msgstr "la texture d'arrière-plan n'a pas pu être créée depuis le fichier" | ||||
|  | ||||
| #: ../src/core/bell.c:185 | ||||
| msgid "Bell event" | ||||
| msgstr "Évènement sonore" | ||||
| @@ -513,7 +528,7 @@ msgstr "_Attendre" | ||||
| msgid "_Force Quit" | ||||
| msgstr "_Forcer à quitter" | ||||
|  | ||||
| #: ../src/core/display.c:547 | ||||
| #: ../src/core/display.c:562 | ||||
| #, c-format | ||||
| msgid "Failed to open X Window System display '%s'\n" | ||||
| msgstr "Impossible d'ouvrir l'affichage « %s » du système X Window\n" | ||||
| @@ -550,19 +565,6 @@ msgstr "Lancer comme un compositeur wayland" | ||||
| msgid "Run as a full display server, rather than nested" | ||||
| msgstr "Lancer comme un serveur d'affichage complet, plutôt qu'imbriqué" | ||||
|  | ||||
| #: ../src/core/main.c:459 | ||||
| #, c-format | ||||
| msgid "Failed to scan themes directory: %s\n" | ||||
| msgstr "Le parcours du répertoire de thèmes a échoué : %s\n" | ||||
|  | ||||
| #: ../src/core/main.c:475 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Could not find a theme! Be sure %s exists and contains the usual themes.\n" | ||||
| msgstr "" | ||||
| "Impossible de trouver un thème ! Assurez-vous que %s existe et contient les " | ||||
| "thèmes habituels.\n" | ||||
|  | ||||
| #: ../src/core/mutter.c:39 | ||||
| #, c-format | ||||
| msgid "" | ||||
| @@ -587,759 +589,29 @@ msgstr "Afficher la version" | ||||
| msgid "Mutter plugin to use" | ||||
| msgstr "Greffon de Mutter à utiliser" | ||||
|  | ||||
| #: ../src/core/prefs.c:2101 | ||||
| #: ../src/core/prefs.c:2004 | ||||
| #, c-format | ||||
| msgid "Workspace %d" | ||||
| msgstr "Espace de travail %d" | ||||
|  | ||||
| #: ../src/core/screen.c:548 | ||||
| #: ../src/core/screen.c:525 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Display \"%s\" already has a window manager; try using the --replace option " | ||||
| "to replace the current window manager." | ||||
| msgstr "" | ||||
| "L'affichage « %s » a déjà un gestionnaire de fenêtres ; essayez d'utiliser " | ||||
| "l'option --replace pour remplacer le gestionnaire de fenêtres actuel." | ||||
|  | ||||
| #: ../src/core/screen.c:607 | ||||
| #, c-format | ||||
| msgid "Screen %d on display '%s' is invalid\n" | ||||
| msgstr "L'écran %d sur l'affichage « %s » n'est pas valide\n" | ||||
|  | ||||
| #: ../src/core/screen.c:564 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Screen %d on display \"%s\" already has a window manager; try using the --" | ||||
| "replace option to replace the current window manager.\n" | ||||
| msgstr "" | ||||
| "L'écran %d sur l'affichage « %s » a déjà un gestionnaire de fenêtres ; " | ||||
| "essayez d'utiliser l'option --replace pour remplacer le gestionnaire de " | ||||
| "fenêtres actuel.\n" | ||||
|  | ||||
| #: ../src/core/screen.c:657 | ||||
| #, c-format | ||||
| msgid "Screen %d on display \"%s\" already has a window manager\n" | ||||
| msgstr "L'écran %d sur l'affichage « %s » a déjà un gestionnaire de fenêtres\n" | ||||
|  | ||||
| #: ../src/core/util.c:118 | ||||
| msgid "Mutter was compiled without support for verbose mode\n" | ||||
| msgstr "Mutter a été compilé sans la prise en charge du mode bavard\n" | ||||
|  | ||||
| #. Translators: This represents the size of a window.  The first number is | ||||
| #. * the width of the window and the second is the height. | ||||
| #. | ||||
| #: ../src/ui/resizepopup.c:134 | ||||
| #, c-format | ||||
| msgid "%d x %d" | ||||
| msgstr "%d x %d" | ||||
|  | ||||
| #: ../src/ui/theme.c:233 | ||||
| msgid "top" | ||||
| msgstr "haut" | ||||
|  | ||||
| #: ../src/ui/theme.c:235 | ||||
| msgid "bottom" | ||||
| msgstr "bas" | ||||
|  | ||||
| #: ../src/ui/theme.c:237 | ||||
| msgid "left" | ||||
| msgstr "gauche" | ||||
|  | ||||
| #: ../src/ui/theme.c:239 | ||||
| msgid "right" | ||||
| msgstr "droite" | ||||
|  | ||||
| #: ../src/ui/theme.c:267 | ||||
| #, c-format | ||||
| msgid "frame geometry does not specify \"%s\" dimension" | ||||
| msgstr "la géométrie du cadre n'indique pas la dimension « %s »" | ||||
|  | ||||
| #: ../src/ui/theme.c:286 | ||||
| #, c-format | ||||
| msgid "frame geometry does not specify dimension \"%s\" for border \"%s\"" | ||||
| msgstr "" | ||||
| "la géométrie du cadre n'indique pas la dimension « %s » pour la bordure " | ||||
| "« %s »" | ||||
|  | ||||
| #: ../src/ui/theme.c:323 | ||||
| #, c-format | ||||
| msgid "Button aspect ratio %g is not reasonable" | ||||
| msgstr "La proportion du bouton %g n'est pas raisonnable" | ||||
|  | ||||
| #: ../src/ui/theme.c:335 | ||||
| #, c-format | ||||
| msgid "Frame geometry does not specify size of buttons" | ||||
| msgstr "La géométrie du cadre n'indique pas la taille des boutons" | ||||
|  | ||||
| #: ../src/ui/theme.c:1061 | ||||
| #, c-format | ||||
| msgid "Gradients should have at least two colors" | ||||
| msgstr "Les dégradés doivent comporter au moins deux couleurs" | ||||
|  | ||||
| #: ../src/ui/theme.c:1211 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "GTK custom color specification must have color name and fallback in " | ||||
| "parentheses, e.g. gtk:custom(foo,bar); could not parse \"%s\"" | ||||
| msgstr "" | ||||
| "Une spécification de couleur personnalisée GTK doit comporter un nom de " | ||||
| "couleur et un substitut entre parenthèses, par ex. gtk:custom(foo,bar) ; " | ||||
| "impossible d'analyser « %s »" | ||||
|  | ||||
| #: ../src/ui/theme.c:1227 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-" | ||||
| "_ are valid" | ||||
| msgstr "" | ||||
| "Caractère « %c » non valide dans le paramètre color_name de gtk:custom, " | ||||
| "seuls A-Za-z0-9-_ sont acceptés" | ||||
|  | ||||
| #: ../src/ui/theme.c:1241 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not " | ||||
| "fit the format" | ||||
| msgstr "" | ||||
| "Le format de gtk:custom est « gtk:custom(nom_couleur,substitut) », « %s » ne " | ||||
| "correspond pas à ce format" | ||||
|  | ||||
| #: ../src/ui/theme.c:1286 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "GTK color specification must have the state in brackets, e.g. gtk:fg[NORMAL] " | ||||
| "where NORMAL is the state; could not parse \"%s\"" | ||||
| msgstr "" | ||||
| "La spécification de couleur GTK doit présenter l'état entre crochets, p. ex. " | ||||
| "gtk:fg[NORMAL] où NORMAL est l'état ; impossible d'analyser « %s »" | ||||
|  | ||||
| #: ../src/ui/theme.c:1300 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "GTK color specification must have a close bracket after the state, e.g. gtk:" | ||||
| "fg[NORMAL] where NORMAL is the state; could not parse \"%s\"" | ||||
| msgstr "" | ||||
| "La spécification de couleur GTK doit comporter un crochet de fermeture après " | ||||
| "l'état, p. ex. gtk:fg[NORMAL] où NORMAL est l'état ; impossible d'analyser " | ||||
| "« %s »" | ||||
|  | ||||
| #: ../src/ui/theme.c:1311 | ||||
| #, c-format | ||||
| msgid "Did not understand state \"%s\" in color specification" | ||||
| msgstr "" | ||||
| "Impossible de comprendre l'état « %s » dans la spécification de couleur" | ||||
|  | ||||
| #: ../src/ui/theme.c:1324 | ||||
| #, c-format | ||||
| msgid "Did not understand color component \"%s\" in color specification" | ||||
| msgstr "" | ||||
| "Impossible de comprendre le composant de couleur « %s » dans la " | ||||
| "spécification de couleur" | ||||
|  | ||||
| #: ../src/ui/theme.c:1352 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Blend format is \"blend/bg_color/fg_color/alpha\", \"%s\" does not fit the " | ||||
| "format" | ||||
| msgstr "" | ||||
| "Le format de mélange est « blend/bg_color/fg_color/alpha », « %s » ne " | ||||
| "correspond pas à ce format ." | ||||
|  | ||||
| #: ../src/ui/theme.c:1363 | ||||
| #, c-format | ||||
| msgid "Could not parse alpha value \"%s\" in blended color" | ||||
| msgstr "Impossible d'analyser la valeur alpha « %s » en couleur mélangée" | ||||
|  | ||||
| #: ../src/ui/theme.c:1373 | ||||
| #, c-format | ||||
| msgid "Alpha value \"%s\" in blended color is not between 0.0 and 1.0" | ||||
| msgstr "" | ||||
| "La valeur alpha « %s » en couleur mélangée n'est pas comprise entre 0,0 et " | ||||
| "1,0" | ||||
|  | ||||
| #: ../src/ui/theme.c:1419 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Shade format is \"shade/base_color/factor\", \"%s\" does not fit the format" | ||||
| msgstr "" | ||||
| "Le format d'ombre est « shade/base_color/factor », « %s » ne correspond pas " | ||||
| "au format" | ||||
|  | ||||
| #: ../src/ui/theme.c:1430 | ||||
| #, c-format | ||||
| msgid "Could not parse shade factor \"%s\" in shaded color" | ||||
| msgstr "Impossible d'analyser le facteur d'ombre « %s » en couleur ombrée" | ||||
|  | ||||
| #: ../src/ui/theme.c:1440 | ||||
| #, c-format | ||||
| msgid "Shade factor \"%s\" in shaded color is negative" | ||||
| msgstr "Le facteur d'ombre « %s » en couleur ombrée est négatif" | ||||
|  | ||||
| #: ../src/ui/theme.c:1469 | ||||
| #, c-format | ||||
| msgid "Could not parse color \"%s\"" | ||||
| msgstr "Impossible d'analyser la couleur « %s »" | ||||
|  | ||||
| #: ../src/ui/theme.c:1778 | ||||
| #, c-format | ||||
| msgid "Coordinate expression contains character '%s' which is not allowed" | ||||
| msgstr "" | ||||
| "L'expression de la coordonnée contient le caractère « %s » qui n'est pas " | ||||
| "autorisé" | ||||
|  | ||||
| #: ../src/ui/theme.c:1805 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Coordinate expression contains floating point number '%s' which could not be " | ||||
| "parsed" | ||||
| msgstr "" | ||||
| "L'expression de la coordonnée contient la valeur en virgule flottante « %s » " | ||||
| "qui ne peut pas être analysée" | ||||
|  | ||||
| #: ../src/ui/theme.c:1819 | ||||
| #, c-format | ||||
| msgid "Coordinate expression contains integer '%s' which could not be parsed" | ||||
| msgstr "" | ||||
| "L'expression de la coordonnée contient l'entier « %s » qui n'a pas pu être " | ||||
| "analysé" | ||||
|  | ||||
| #: ../src/ui/theme.c:1940 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Coordinate expression contained unknown operator at the start of this text: " | ||||
| "\"%s\"" | ||||
| msgstr "" | ||||
| "L'expression de la coordonnée contenait un opérateur inconnu au début de ce " | ||||
| "texte : « %s »" | ||||
|  | ||||
| #: ../src/ui/theme.c:1997 | ||||
| #, c-format | ||||
| msgid "Coordinate expression was empty or not understood" | ||||
| msgstr "L'expression de la coordonnée était vide ou incomprise" | ||||
|  | ||||
| #: ../src/ui/theme.c:2110 ../src/ui/theme.c:2120 ../src/ui/theme.c:2154 | ||||
| #, c-format | ||||
| msgid "Coordinate expression results in division by zero" | ||||
| msgstr "L'expression de la coordonnée entraîne une division par zéro" | ||||
|  | ||||
| #: ../src/ui/theme.c:2162 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Coordinate expression tries to use mod operator on a floating-point number" | ||||
| msgstr "" | ||||
| "L'expression de la coordonnée tente d'utiliser l'opérateur mod sur une " | ||||
| "valeur en virgule flottante" | ||||
|  | ||||
| #: ../src/ui/theme.c:2218 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Coordinate expression has an operator \"%s\" where an operand was expected" | ||||
| msgstr "" | ||||
| "L'expression de la coordonnée a un opérateur « %s » là où un opérande était " | ||||
| "attendu" | ||||
|  | ||||
| #: ../src/ui/theme.c:2227 | ||||
| #, c-format | ||||
| msgid "Coordinate expression had an operand where an operator was expected" | ||||
| msgstr "" | ||||
| "L'expression de la coordonnée a un opérande là où un opérateur était attendu" | ||||
|  | ||||
| #: ../src/ui/theme.c:2235 | ||||
| #, c-format | ||||
| msgid "Coordinate expression ended with an operator instead of an operand" | ||||
| msgstr "" | ||||
| "L'expression de la coordonnée était terminée par un opérateur au lieu d'un " | ||||
| "opérande" | ||||
|  | ||||
| #: ../src/ui/theme.c:2245 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Coordinate expression has operator \"%c\" following operator \"%c\" with no " | ||||
| "operand in between" | ||||
| msgstr "" | ||||
| "L'expression de la coordonnée a un opérateur « %c » suivant l'opérateur " | ||||
| "« %c » sans opérande entre eux" | ||||
|  | ||||
| #: ../src/ui/theme.c:2396 ../src/ui/theme.c:2441 | ||||
| #, c-format | ||||
| msgid "Coordinate expression had unknown variable or constant \"%s\"" | ||||
| msgstr "" | ||||
| "L'expression de la coordonnée possède une variable ou constante inconnue " | ||||
| "« %s »" | ||||
|  | ||||
| #: ../src/ui/theme.c:2495 | ||||
| #, c-format | ||||
| msgid "Coordinate expression parser overflowed its buffer." | ||||
| msgstr "" | ||||
| "L'analyseur d'expression de coordonnées a dépassé la capacité de son tampon." | ||||
|  | ||||
| #: ../src/ui/theme.c:2524 | ||||
| #, c-format | ||||
| msgid "Coordinate expression had a close parenthesis with no open parenthesis" | ||||
| msgstr "" | ||||
| "L'expression de la coordonnée comporte une parenthèse de fermeture, mais pas " | ||||
| "de parenthèse d'ouverture" | ||||
|  | ||||
| #: ../src/ui/theme.c:2588 | ||||
| #, c-format | ||||
| msgid "Coordinate expression had an open parenthesis with no close parenthesis" | ||||
| msgstr "" | ||||
| "L'expression de la coordonnée comporte une parenthèse d'ouverture, mais pas " | ||||
| "de parenthèse de fermeture" | ||||
|  | ||||
| #: ../src/ui/theme.c:2599 | ||||
| #, c-format | ||||
| msgid "Coordinate expression doesn't seem to have any operators or operands" | ||||
| msgstr "" | ||||
| "L'expression de la coordonnée ne semble pas comprendre d'opérateur ni " | ||||
| "d'opérande" | ||||
|  | ||||
| #: ../src/ui/theme.c:2812 ../src/ui/theme.c:2832 ../src/ui/theme.c:2852 | ||||
| #, c-format | ||||
| msgid "Theme contained an expression that resulted in an error: %s\n" | ||||
| msgstr "Le thème contient une expression qui a entraîné une erreur : %s\n" | ||||
|  | ||||
| #: ../src/ui/theme.c:4455 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/> must be " | ||||
| "specified for this frame style" | ||||
| msgstr "" | ||||
| "<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/> doit être " | ||||
| "indiqué pour ce style de cadre" | ||||
|  | ||||
| #: ../src/ui/theme.c:4970 ../src/ui/theme.c:4995 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>" | ||||
| msgstr "" | ||||
| "<frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/> manquant" | ||||
|  | ||||
| #: ../src/ui/theme.c:5041 | ||||
| #, c-format | ||||
| msgid "Failed to load theme \"%s\": %s\n" | ||||
| msgstr "Impossible de charger le thème « %s » : %s\n" | ||||
|  | ||||
| #: ../src/ui/theme.c:5177 ../src/ui/theme.c:5184 ../src/ui/theme.c:5191 | ||||
| #: ../src/ui/theme.c:5198 ../src/ui/theme.c:5205 | ||||
| #, c-format | ||||
| msgid "No <%s> set for theme \"%s\"" | ||||
| msgstr "Aucun <%s> défini pour le thème « %s »" | ||||
|  | ||||
| #: ../src/ui/theme.c:5213 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "No frame style set for window type \"%s\" in theme \"%s\", add a <window " | ||||
| "type=\"%s\" style_set=\"whatever\"/> element" | ||||
| msgstr "" | ||||
| "Aucun style de cadre défini pour le type de fenêtre « %s » dans le thème " | ||||
| "« %s », ajoutez un élément <window type=\"%s\" style_set=\"whatever\"/>" | ||||
|  | ||||
| #: ../src/ui/theme.c:5620 ../src/ui/theme.c:5682 ../src/ui/theme.c:5745 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "User-defined constants must begin with a capital letter; \"%s\" does not" | ||||
| msgstr "" | ||||
| "Les constantes définies par l'utilisateur doivent commencer par une " | ||||
| "majuscule ; « %s » commence par une minuscule" | ||||
|  | ||||
| #: ../src/ui/theme.c:5628 ../src/ui/theme.c:5690 ../src/ui/theme.c:5753 | ||||
| #, c-format | ||||
| msgid "Constant \"%s\" has already been defined" | ||||
| msgstr "La constante « %s » a déjà été définie" | ||||
|  | ||||
| #. Translators: This means that an attribute which should have been found | ||||
| #. * on an XML element was not in fact found. | ||||
| #. | ||||
| #: ../src/ui/theme-parser.c:234 | ||||
| #, c-format | ||||
| msgid "No \"%s\" attribute on element <%s>" | ||||
| msgstr "Aucun attribut « %s » sur l'élément <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:263 ../src/ui/theme-parser.c:281 | ||||
| #, c-format | ||||
| msgid "Line %d character %d: %s" | ||||
| msgstr "Ligne %d caractère %d: %s" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:481 | ||||
| #, c-format | ||||
| msgid "Attribute \"%s\" repeated twice on the same <%s> element" | ||||
| msgstr "Attribut « %s » répété deux fois sur le même élément <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:505 ../src/ui/theme-parser.c:554 | ||||
| #, c-format | ||||
| msgid "Attribute \"%s\" is invalid on <%s> element in this context" | ||||
| msgstr "Attribut « %s » non valide sur l'élément <%s> dans ce contexte" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:596 | ||||
| #, c-format | ||||
| msgid "Could not parse \"%s\" as an integer" | ||||
| msgstr "Impossible d'analyser « %s » en tant qu'entier" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:605 ../src/ui/theme-parser.c:660 | ||||
| #, c-format | ||||
| msgid "Did not understand trailing characters \"%s\" in string \"%s\"" | ||||
| msgstr "Caractères de fin « %s » non compris dans la chaîne « %s »" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:615 | ||||
| #, c-format | ||||
| msgid "Integer %ld must be positive" | ||||
| msgstr "L'entier %ld doit être positif" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:623 | ||||
| #, c-format | ||||
| msgid "Integer %ld is too large, current max is %d" | ||||
| msgstr "L'entier %ld est trop élevé, le max. actuel est %d" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:651 ../src/ui/theme-parser.c:767 | ||||
| #, c-format | ||||
| msgid "Could not parse \"%s\" as a floating point number" | ||||
| msgstr "Impossible d'analyser « %s » en tant que valeur en virgule flottante" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:682 ../src/ui/theme-parser.c:710 | ||||
| #, c-format | ||||
| msgid "Boolean values must be \"true\" or \"false\" not \"%s\"" | ||||
| msgstr "" | ||||
| "Les valeurs booléennes doivent être « true » ou « false » et non « %s »" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:737 | ||||
| #, c-format | ||||
| msgid "Angle must be between 0.0 and 360.0, was %g\n" | ||||
| msgstr "L'angle doit être compris entre 0,0 et 360,0. Il était de %g\n" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:800 | ||||
| #, c-format | ||||
| msgid "Alpha must be between 0.0 (invisible) and 1.0 (fully opaque), was %g\n" | ||||
| msgstr "" | ||||
| "La valeur alpha doit être comprise entre 0,0 (invisible) et 1,0 (entièrement " | ||||
| "opaque). Elle était de %g\n" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:865 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Invalid title scale \"%s\" (must be one of xx-small,x-small,small,medium," | ||||
| "large,x-large,xx-large)\n" | ||||
| msgstr "" | ||||
| "Échelle de titre non valide « %s » (elle doit avoir l'une des valeurs " | ||||
| "suivantes : xx-small, x-small, small, medium,large, x-large, xx-large)\n" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1021 ../src/ui/theme-parser.c:1084 | ||||
| #: ../src/ui/theme-parser.c:1118 ../src/ui/theme-parser.c:1221 | ||||
| #, c-format | ||||
| msgid "<%s> name \"%s\" used a second time" | ||||
| msgstr "<%s> - nom « %s » utilisé une deuxième fois" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1033 ../src/ui/theme-parser.c:1130 | ||||
| #: ../src/ui/theme-parser.c:1233 | ||||
| #, c-format | ||||
| msgid "<%s> parent \"%s\" has not been defined" | ||||
| msgstr "<%s> - parent « %s » non défini" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1143 | ||||
| #, c-format | ||||
| msgid "<%s> geometry \"%s\" has not been defined" | ||||
| msgstr "<%s> - géométrie « %s » non définie" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1156 | ||||
| #, c-format | ||||
| msgid "<%s> must specify either a geometry or a parent that has a geometry" | ||||
| msgstr "<%s> doit indiquer une géométrie ou un parent qui en possède une" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1198 | ||||
| msgid "You must specify a background for an alpha value to be meaningful" | ||||
| msgstr "" | ||||
| "Vous devez indiquer un arrière-plan pour qu'une valeur alpha ait du sens." | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1266 | ||||
| #, c-format | ||||
| msgid "Unknown type \"%s\" on <%s> element" | ||||
| msgstr "Type inconnu « %s » sur l'élément <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1277 | ||||
| #, c-format | ||||
| msgid "Unknown style_set \"%s\" on <%s> element" | ||||
| msgstr "style_set inconnu « %s » sur l'élément <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1285 | ||||
| #, c-format | ||||
| msgid "Window type \"%s\" has already been assigned a style set" | ||||
| msgstr "Le type de fenêtre « %s » s'est déjà vu attribuer un jeu de styles" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1315 ../src/ui/theme-parser.c:1379 | ||||
| #: ../src/ui/theme-parser.c:1605 ../src/ui/theme-parser.c:2840 | ||||
| #: ../src/ui/theme-parser.c:2886 ../src/ui/theme-parser.c:3036 | ||||
| #: ../src/ui/theme-parser.c:3272 ../src/ui/theme-parser.c:3310 | ||||
| #: ../src/ui/theme-parser.c:3348 ../src/ui/theme-parser.c:3386 | ||||
| #, c-format | ||||
| msgid "Element <%s> is not allowed below <%s>" | ||||
| msgstr "L'élément <%s> n'est pas autorisé sous <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1429 ../src/ui/theme-parser.c:1443 | ||||
| #: ../src/ui/theme-parser.c:1488 | ||||
| msgid "" | ||||
| "Cannot specify both \"button_width\"/\"button_height\" and \"aspect_ratio\" " | ||||
| "for buttons" | ||||
| msgstr "" | ||||
| "Impossible d'indiquer à la fois « button_width » / " | ||||
| "« button_height » (largeur/hauteur) et « aspect_ratio » (proportion) pour " | ||||
| "les boutons" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1452 | ||||
| #, c-format | ||||
| msgid "Distance \"%s\" is unknown" | ||||
| msgstr "Distance « %s » inconnue" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1497 | ||||
| #, c-format | ||||
| msgid "Aspect ratio \"%s\" is unknown" | ||||
| msgstr "Proportion « %s » inconnue" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1559 | ||||
| #, c-format | ||||
| msgid "Border \"%s\" is unknown" | ||||
| msgstr "Bordure « %s » inconnue" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1870 | ||||
| #, c-format | ||||
| msgid "No \"start_angle\" or \"from\" attribute on element <%s>" | ||||
| msgstr "" | ||||
| "Aucun attribut « start_angle » (« début d'angle ») ou « from » (« depuis ») " | ||||
| "sur l'élément <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1877 | ||||
| #, c-format | ||||
| msgid "No \"extent_angle\" or \"to\" attribute on element <%s>" | ||||
| msgstr "" | ||||
| "Aucun attribut « extent_angle » (« extension d'angle ») ou « to » (« vers ») " | ||||
| "sur l'élément <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2117 | ||||
| #, c-format | ||||
| msgid "Did not understand value \"%s\" for type of gradient" | ||||
| msgstr "Impossible de comprendre la valeur « %s » pour le type de dégradé" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2195 ../src/ui/theme-parser.c:2570 | ||||
| #, c-format | ||||
| msgid "Did not understand fill type \"%s\" for <%s> element" | ||||
| msgstr "" | ||||
| "Impossible de comprendre le type de remplissage « %s » pour l'élément <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2362 ../src/ui/theme-parser.c:2445 | ||||
| #: ../src/ui/theme-parser.c:2508 | ||||
| #, c-format | ||||
| msgid "Did not understand state \"%s\" for <%s> element" | ||||
| msgstr "Impossible de comprendre l'état « %s » pour l'élément <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2372 ../src/ui/theme-parser.c:2455 | ||||
| #, c-format | ||||
| msgid "Did not understand shadow \"%s\" for <%s> element" | ||||
| msgstr "Impossible de comprendre l'ombre « %s » pour l'élément <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2382 | ||||
| #, c-format | ||||
| msgid "Did not understand arrow \"%s\" for <%s> element" | ||||
| msgstr "Impossible de comprendre la flèche « %s » pour l'élément <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2696 ../src/ui/theme-parser.c:2792 | ||||
| #, c-format | ||||
| msgid "No <draw_ops> called \"%s\" has been defined" | ||||
| msgstr "Aucun <draw_ops> appelé « %s » n'a été défini" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2708 ../src/ui/theme-parser.c:2804 | ||||
| #, c-format | ||||
| msgid "Including draw_ops \"%s\" here would create a circular reference" | ||||
| msgstr "L'inclusion du draw_ops « %s » ici créerait une référence circulaire" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2919 | ||||
| #, c-format | ||||
| msgid "Unknown position \"%s\" for frame piece" | ||||
| msgstr "Position inconnue « %s » de la pièce du cadre" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2927 | ||||
| #, c-format | ||||
| msgid "Frame style already has a piece at position %s" | ||||
| msgstr "Le style de cadre a déjà une pièce à la position %s" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2944 ../src/ui/theme-parser.c:3021 | ||||
| #, c-format | ||||
| msgid "No <draw_ops> with the name \"%s\" has been defined" | ||||
| msgstr "Aucun <draw_ops> avec le nom « %s » n'a été défini" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2974 | ||||
| #, c-format | ||||
| msgid "Unknown function \"%s\" for button" | ||||
| msgstr "Fonction inconnue « %s » pour le bouton" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2984 | ||||
| #, c-format | ||||
| msgid "Button function \"%s\" does not exist in this version (%d, need %d)" | ||||
| msgstr "" | ||||
| "La fonction « %s » du bouton n'existe pas dans la version (%d, a besoin de " | ||||
| "%d)" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2996 | ||||
| #, c-format | ||||
| msgid "Unknown state \"%s\" for button" | ||||
| msgstr "État inconnu « %s » pour le bouton" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3004 | ||||
| #, c-format | ||||
| msgid "Frame style already has a button for function %s state %s" | ||||
| msgstr "Le style de cadre a déjà un bouton pour la fonction %s, état %s" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3075 | ||||
| #, c-format | ||||
| msgid "\"%s\" is not a valid value for focus attribute" | ||||
| msgstr "« %s » n'est pas une valeur valide pour l'attribut de focus" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3084 | ||||
| #, c-format | ||||
| msgid "\"%s\" is not a valid value for state attribute" | ||||
| msgstr "« %s » n'est pas une valeur valide pour l'attribut d'état" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3094 | ||||
| #, c-format | ||||
| msgid "A style called \"%s\" has not been defined" | ||||
| msgstr "Aucun style appelé « %s » n'a été défini" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3115 ../src/ui/theme-parser.c:3138 | ||||
| #, c-format | ||||
| msgid "\"%s\" is not a valid value for resize attribute" | ||||
| msgstr "" | ||||
| "« %s » n'est pas une valeur valide pour l'attribut de redimensionnement" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3149 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Should not have \"resize\" attribute on <%s> element for maximized/shaded " | ||||
| "states" | ||||
| msgstr "" | ||||
| "L'attribut « resize » (« redimensionnement ») ne devrait pas figurer sur " | ||||
| "l'élément <%s> pour les états maximisé/réduit dans la barre de titre" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3163 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Should not have \"resize\" attribute on <%s> element for maximized states" | ||||
| msgstr "" | ||||
| "L'attribut « resize » (« redimensionnement ») ne devrait pas figurer sur " | ||||
| "l'élément <%s> pour l'état maximisé" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3177 ../src/ui/theme-parser.c:3221 | ||||
| #, c-format | ||||
| msgid "Style has already been specified for state %s resize %s focus %s" | ||||
| msgstr "" | ||||
| "Le style a déjà été indiqué pour l'état %s, redimensionnement %s, focus %s" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3188 ../src/ui/theme-parser.c:3199 | ||||
| #: ../src/ui/theme-parser.c:3210 ../src/ui/theme-parser.c:3232 | ||||
| #: ../src/ui/theme-parser.c:3243 ../src/ui/theme-parser.c:3254 | ||||
| #, c-format | ||||
| msgid "Style has already been specified for state %s focus %s" | ||||
| msgstr "Le style a déjà été indiqué pour l'état %s, focus %s" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3293 | ||||
| msgid "" | ||||
| "Can't have a two draw_ops for a <piece> element (theme specified a draw_ops " | ||||
| "attribute and also a <draw_ops> element, or specified two elements)" | ||||
| msgstr "" | ||||
| "Impossible d'avoir deux attributs draw_ops pour un élément <piece> (le thème " | ||||
| "indiquait un attribut draw_ops et un élément <draw_ops> ou deux éléments)" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3331 | ||||
| msgid "" | ||||
| "Can't have a two draw_ops for a <button> element (theme specified a draw_ops " | ||||
| "attribute and also a <draw_ops> element, or specified two elements)" | ||||
| msgstr "" | ||||
| "Impossible d'avoir deux attributs draw_ops pour un élément <button> (le " | ||||
| "thème indiquait un attribut draw_ops et un élément <draw_ops> ou deux " | ||||
| "éléments)" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3369 | ||||
| msgid "" | ||||
| "Can't have a two draw_ops for a <menu_icon> element (theme specified a " | ||||
| "draw_ops attribute and also a <draw_ops> element, or specified two elements)" | ||||
| msgstr "" | ||||
| "Impossible d'avoir deux attributs draw_ops pour un élément <menu_icon> (le " | ||||
| "thème indiquait un attribut draw_ops et un élément <draw_ops> ou deux " | ||||
| "éléments)" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3433 | ||||
| #, c-format | ||||
| msgid "Bad version specification '%s'" | ||||
| msgstr "Mauvaise spécification de version « %s »" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3506 | ||||
| msgid "" | ||||
| "\"version\" attribute cannot be used in metacity-theme-1.xml or metacity-" | ||||
| "theme-2.xml" | ||||
| msgstr "" | ||||
| "L'attribut « version » ne peut pas être utilisé dans metacity-theme-1.xml or " | ||||
| "metacity-theme-2.xml" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3529 | ||||
| #, c-format | ||||
| msgid "Theme requires version %s but latest supported theme version is %d.%d" | ||||
| msgstr "" | ||||
| "Le thème nécessite la version %s mais la version de thème la plus récente " | ||||
| "prise en charge est %d.%d" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3561 | ||||
| #, c-format | ||||
| msgid "Outermost element in theme must be <metacity_theme> not <%s>" | ||||
| msgstr "" | ||||
| "L'élément le plus extérieur dans le thème doit être <metacity_theme> et non <" | ||||
| "%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3581 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Element <%s> is not allowed inside a name/author/date/description element" | ||||
| msgstr "" | ||||
| "L'élément <%s> n'est pas autorisé dans un élément name/author/date/" | ||||
| "description" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3586 | ||||
| #, c-format | ||||
| msgid "Element <%s> is not allowed inside a <constant> element" | ||||
| msgstr "L'élément <%s> n'est pas autorisé dans un élément <constant>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3598 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Element <%s> is not allowed inside a distance/border/aspect_ratio element" | ||||
| msgstr "" | ||||
| "L'élément <%s> n'est pas autorisé dans un élément distance/border/" | ||||
| "aspect_ratio" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3620 | ||||
| #, c-format | ||||
| msgid "Element <%s> is not allowed inside a draw operation element" | ||||
| msgstr "" | ||||
| "L'élément <%s> n'est pas autorisé dans un élément d'opération de dessin" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3630 ../src/ui/theme-parser.c:3660 | ||||
| #: ../src/ui/theme-parser.c:3665 ../src/ui/theme-parser.c:3670 | ||||
| #, c-format | ||||
| msgid "Element <%s> is not allowed inside a <%s> element" | ||||
| msgstr "L'élément <%s> n'est pas autorisé dans un élément <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3898 | ||||
| msgid "No draw_ops provided for frame piece" | ||||
| msgstr "Aucun attribut draw_ops fourni pour la pièce du cadre" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3913 | ||||
| msgid "No draw_ops provided for button" | ||||
| msgstr "Aucun attribut draw_ops fourni pour le bouton" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3967 | ||||
| #, c-format | ||||
| msgid "No text is allowed inside element <%s>" | ||||
| msgstr "Aucun texte autorisé dans l'élément <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:4025 ../src/ui/theme-parser.c:4037 | ||||
| #: ../src/ui/theme-parser.c:4049 ../src/ui/theme-parser.c:4061 | ||||
| #: ../src/ui/theme-parser.c:4073 | ||||
| #, c-format | ||||
| msgid "<%s> specified twice for this theme" | ||||
| msgstr "<%s> indiqué deux fois pour ce thème" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:4335 | ||||
| #, c-format | ||||
| msgid "Failed to find a valid file for theme %s\n" | ||||
| msgstr "Impossible de trouver un fichier valide pour le thème %s\n" | ||||
|  | ||||
| #: ../src/x11/session.c:1815 | ||||
| msgid "" | ||||
| "These windows do not support "save current setup" and will have to " | ||||
| @@ -1349,7 +621,7 @@ msgstr "" | ||||
| "configuration actuelle » et devront être redémarrées manuellement à la " | ||||
| "prochaine connexion." | ||||
|  | ||||
| #: ../src/x11/window-props.c:515 | ||||
| #: ../src/x11/window-props.c:549 | ||||
| #, c-format | ||||
| msgid "%s (on %s)" | ||||
| msgstr "%s (sur %s)" | ||||
|   | ||||
							
								
								
									
										764
									
								
								po/id.po
									
									
									
									
									
								
							
							
						
						
									
										764
									
								
								po/id.po
									
									
									
									
									
								
							| @@ -5,21 +5,21 @@ | ||||
| # Mohammad DAMT <mdamt@bisnisweb.com>, 2003-2005. | ||||
| # Ahmad Riza H Nst  <rizahnst@eriagempita.co.id>, 2006. | ||||
| # Dirgita <dirgitadevina@yahoo.co.id>, 2011, 2012, 2014. | ||||
| # Andika Triwidada <andika@gmail.com>, 2011, 2012, 2013, 2014. | ||||
| # Andika Triwidada <andika@gmail.com>, 2011-2015. | ||||
| msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: mutter master\n" | ||||
| "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" | ||||
| "product=mutter&keywords=I18N+L10N&component=general\n" | ||||
| "POT-Creation-Date: 2014-09-01 21:52+0000\n" | ||||
| "PO-Revision-Date: 2014-09-03 20:56+0700\n" | ||||
| "POT-Creation-Date: 2015-03-21 11:13+0000\n" | ||||
| "PO-Revision-Date: 2015-03-21 19:04+0700\n" | ||||
| "Last-Translator: Andika Triwidada <andika@gmail.com>\n" | ||||
| "Language-Team: Indonesian <gnome-l10n-id@googlegroups.com>\n" | ||||
| "Language: id\n" | ||||
| "MIME-Version: 1.0\n" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
| "X-Generator: Poedit 1.6.9\n" | ||||
| "X-Generator: Poedit 1.7.1\n" | ||||
| "Plural-Forms: nplurals=1; plural=0;\n" | ||||
|  | ||||
| #: ../data/50-mutter-navigation.xml.in.h:1 | ||||
| @@ -434,29 +434,49 @@ msgstr "Pindah ke VT 6" | ||||
| msgid "Switch to VT 7" | ||||
| msgstr "Pindah ke VT 7" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:412 | ||||
| #: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:8 | ||||
| msgid "Switch to VT 8" | ||||
| msgstr "Pindah ke VT 8" | ||||
|  | ||||
| #: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:9 | ||||
| msgid "Switch to VT 9" | ||||
| msgstr "Pindah ke VT 9" | ||||
|  | ||||
| #: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:10 | ||||
| msgid "Switch to VT 10" | ||||
| msgstr "Pindah ke VT 10" | ||||
|  | ||||
| #: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:11 | ||||
| msgid "Switch to VT 11" | ||||
| msgstr "Pindah ke VT 11" | ||||
|  | ||||
| #: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:12 | ||||
| msgid "Switch to VT 12" | ||||
| msgstr "Pindah ke VT 12" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:364 | ||||
| msgid "Built-in display" | ||||
| msgstr "Tampilan bawaan" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:437 | ||||
| #: ../src/backends/meta-monitor-manager.c:391 | ||||
| msgid "Unknown" | ||||
| msgstr "Tak Dikenal" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:439 | ||||
| #: ../src/backends/meta-monitor-manager.c:393 | ||||
| msgid "Unknown Display" | ||||
| msgstr "Tampilan Tak Dikenal" | ||||
|  | ||||
| #. TRANSLATORS: this is a monitor vendor name, followed by a | ||||
| #. * size in inches, like 'Dell 15"' | ||||
| #. | ||||
| #: ../src/backends/meta-monitor-manager.c:447 | ||||
| #: ../src/backends/meta-monitor-manager.c:401 | ||||
| #, c-format | ||||
| msgid "%s %s" | ||||
| msgstr "%s %s" | ||||
|  | ||||
| #. This probably means that a non-WM compositor like xcompmgr is running; | ||||
| #. * we have no way to get it to exit | ||||
| #: ../src/compositor/compositor.c:443 | ||||
| #: ../src/compositor/compositor.c:456 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Another compositing manager is already running on screen %i on display \"%s" | ||||
| @@ -464,10 +484,6 @@ msgid "" | ||||
| msgstr "" | ||||
| "Manajer komposit lain telah berjalan pada layar %i pada tampilan \"%s\"." | ||||
|  | ||||
| #: ../src/compositor/meta-background.c:1044 | ||||
| msgid "background texture could not be created from file" | ||||
| msgstr "tekstur latar tak bisa dibuat dari berkas" | ||||
|  | ||||
| #: ../src/core/bell.c:185 | ||||
| msgid "Bell event" | ||||
| msgstr "Bel peristiwa" | ||||
| @@ -496,7 +512,7 @@ msgstr "_Tunggu" | ||||
| msgid "_Force Quit" | ||||
| msgstr "_Matikan Paksa" | ||||
|  | ||||
| #: ../src/core/display.c:547 | ||||
| #: ../src/core/display.c:562 | ||||
| #, c-format | ||||
| msgid "Failed to open X Window System display '%s'\n" | ||||
| msgstr "Gagal membuka tampilan X Window System '%s'\n" | ||||
| @@ -533,17 +549,6 @@ msgstr "Jalankan sebagai kompositor wayland" | ||||
| msgid "Run as a full display server, rather than nested" | ||||
| msgstr "Jalankan sebagai server tampilan penuh, ketimbang tampilan bersarang" | ||||
|  | ||||
| #: ../src/core/main.c:459 | ||||
| #, c-format | ||||
| msgid "Failed to scan themes directory: %s\n" | ||||
| msgstr "Gagal memeriksa direktori tema: %s\n" | ||||
|  | ||||
| #: ../src/core/main.c:475 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Could not find a theme! Be sure %s exists and contains the usual themes.\n" | ||||
| msgstr "Tak menemukan tema! Pastikan %s ada dan berisi tema yang biasa.\n" | ||||
|  | ||||
| #: ../src/core/mutter.c:39 | ||||
| #, c-format | ||||
| msgid "" | ||||
| @@ -568,714 +573,29 @@ msgstr "Cetak versi" | ||||
| msgid "Mutter plugin to use" | ||||
| msgstr "Pengaya Mutter yang dipakai" | ||||
|  | ||||
| #: ../src/core/prefs.c:2101 | ||||
| #: ../src/core/prefs.c:2004 | ||||
| #, c-format | ||||
| msgid "Workspace %d" | ||||
| msgstr "Area kerja %d" | ||||
|  | ||||
| #: ../src/core/screen.c:548 | ||||
| #: ../src/core/screen.c:525 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Display \"%s\" already has a window manager; try using the --replace option " | ||||
| "to replace the current window manager." | ||||
| msgstr "" | ||||
| "Tampilan \"%s\" sudah memiliki manajer jendela; cobalah gunakan pilihan --" | ||||
| "replace untuk mengganti manajer jendela saat ini." | ||||
|  | ||||
| #: ../src/core/screen.c:607 | ||||
| #, c-format | ||||
| msgid "Screen %d on display '%s' is invalid\n" | ||||
| msgstr "Layar %d pada tampilan '%s' tidak benar\n" | ||||
|  | ||||
| #: ../src/core/screen.c:564 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Screen %d on display \"%s\" already has a window manager; try using the --" | ||||
| "replace option to replace the current window manager.\n" | ||||
| msgstr "" | ||||
| "Layar %d pada tampilan \"%s\" sudah memiliki pengatur jendela. Cobalah " | ||||
| "gunakan pilihan --replace untuk mengganti pengatur jendela yang aktif.\n" | ||||
|  | ||||
| #: ../src/core/screen.c:657 | ||||
| #, c-format | ||||
| msgid "Screen %d on display \"%s\" already has a window manager\n" | ||||
| msgstr "Layar %d pada tampilan \"%s\" sudah ada pengatur jendelanya\n" | ||||
|  | ||||
| #: ../src/core/util.c:118 | ||||
| msgid "Mutter was compiled without support for verbose mode\n" | ||||
| msgstr "Muter dikompilasi tanpa dukungan mode riuh\n" | ||||
|  | ||||
| #. Translators: This represents the size of a window.  The first number is | ||||
| #. * the width of the window and the second is the height. | ||||
| #. | ||||
| #: ../src/ui/resizepopup.c:134 | ||||
| #, c-format | ||||
| msgid "%d x %d" | ||||
| msgstr "%d x %d" | ||||
|  | ||||
| #: ../src/ui/theme.c:233 | ||||
| msgid "top" | ||||
| msgstr "atas" | ||||
|  | ||||
| #: ../src/ui/theme.c:235 | ||||
| msgid "bottom" | ||||
| msgstr "bawah" | ||||
|  | ||||
| #: ../src/ui/theme.c:237 | ||||
| msgid "left" | ||||
| msgstr "kiri" | ||||
|  | ||||
| #: ../src/ui/theme.c:239 | ||||
| msgid "right" | ||||
| msgstr "kanan" | ||||
|  | ||||
| #: ../src/ui/theme.c:267 | ||||
| #, c-format | ||||
| msgid "frame geometry does not specify \"%s\" dimension" | ||||
| msgstr "ukuran frame tidak menyebutkan dimensi \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:286 | ||||
| #, c-format | ||||
| msgid "frame geometry does not specify dimension \"%s\" for border \"%s\"" | ||||
| msgstr "ukuran frame tidak menyebutkan dimensi \"%s\" untuk batas \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:323 | ||||
| #, c-format | ||||
| msgid "Button aspect ratio %g is not reasonable" | ||||
| msgstr "Aspek rasio tombol %g tidak wajar" | ||||
|  | ||||
| #: ../src/ui/theme.c:335 | ||||
| #, c-format | ||||
| msgid "Frame geometry does not specify size of buttons" | ||||
| msgstr "Ukuran frame tidak menyebutkan ukuran tombol" | ||||
|  | ||||
| #: ../src/ui/theme.c:1061 | ||||
| #, c-format | ||||
| msgid "Gradients should have at least two colors" | ||||
| msgstr "Gradien harus paling tidak ada dua warna" | ||||
|  | ||||
| #: ../src/ui/theme.c:1211 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "GTK custom color specification must have color name and fallback in " | ||||
| "parentheses, e.g. gtk:custom(foo,bar); could not parse \"%s\"" | ||||
| msgstr "" | ||||
| "Spesifikasi warna ubahan GTK mesti memiliki nama warna dan cadangan dalam " | ||||
| "kurung, mis. gtk:custom(foo,bar); tak bisa mengurai \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:1227 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-" | ||||
| "_ are valid" | ||||
| msgstr "" | ||||
| "Karakter tak valid '%c' dalam parameter color_name dari gtk:custom, hanya A-" | ||||
| "Za-z0-9-_ yang valid" | ||||
|  | ||||
| #: ../src/ui/theme.c:1241 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not " | ||||
| "fit the format" | ||||
| msgstr "" | ||||
| "Format Gtk:custom adalah \"gtk:custom(color_name,fallback)\", \"%s\" tak " | ||||
| "memenuhi format" | ||||
|  | ||||
| #: ../src/ui/theme.c:1286 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "GTK color specification must have the state in brackets, e.g. gtk:fg[NORMAL] " | ||||
| "where NORMAL is the state; could not parse \"%s\"" | ||||
| msgstr "" | ||||
| "Spesifikasi warna GTK harus memiliki kondisi pada kurung, misal gtk:" | ||||
| "fg[NORMAL] dengan NORMAL adalah jenis kondisinya, tidak dapat membaca \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:1300 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "GTK color specification must have a close bracket after the state, e.g. gtk:" | ||||
| "fg[NORMAL] where NORMAL is the state; could not parse \"%s\"" | ||||
| msgstr "" | ||||
| "Spesifikasi warna GTK harus memiliki kurung tutup pada kondisinya, misal gtk:" | ||||
| "fg[NORMAL] dengan NORMAL adalah jenis kondisinya, tidak dapat membaca \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:1311 | ||||
| #, c-format | ||||
| msgid "Did not understand state \"%s\" in color specification" | ||||
| msgstr "Kondisi \"%s\" tidak benar pada spesifikasi warna" | ||||
|  | ||||
| #: ../src/ui/theme.c:1324 | ||||
| #, c-format | ||||
| msgid "Did not understand color component \"%s\" in color specification" | ||||
| msgstr "Komponen warna \"%s\" tidak benar pada spesifikasi warna" | ||||
|  | ||||
| #: ../src/ui/theme.c:1352 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Blend format is \"blend/bg_color/fg_color/alpha\", \"%s\" does not fit the " | ||||
| "format" | ||||
| msgstr "" | ||||
| "Format pencampuran adalah \"blend/bg_color/fg_color/alpha\", \"%s\" bukan " | ||||
| "ditulis dalam format yang benar" | ||||
|  | ||||
| #: ../src/ui/theme.c:1363 | ||||
| #, c-format | ||||
| msgid "Could not parse alpha value \"%s\" in blended color" | ||||
| msgstr "Tak dapat membaca nilai alpha \"%s\" pada pencampuran warna" | ||||
|  | ||||
| #: ../src/ui/theme.c:1373 | ||||
| #, c-format | ||||
| msgid "Alpha value \"%s\" in blended color is not between 0.0 and 1.0" | ||||
| msgstr "" | ||||
| "Nilai alpha \"%s\" pada warna yang dicampur tidak ada dalam rentang 0.0 dan " | ||||
| "1.0" | ||||
|  | ||||
| #: ../src/ui/theme.c:1419 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Shade format is \"shade/base_color/factor\", \"%s\" does not fit the format" | ||||
| msgstr "" | ||||
| "Format bayangan adalah \"shade/base_color/factor\", \"%s\" ditulis dalam " | ||||
| "format yang keliru" | ||||
|  | ||||
| #: ../src/ui/theme.c:1430 | ||||
| #, c-format | ||||
| msgid "Could not parse shade factor \"%s\" in shaded color" | ||||
| msgstr "Tak dapat membaca faktor bayangan \"%s\" pada warna berbayang" | ||||
|  | ||||
| #: ../src/ui/theme.c:1440 | ||||
| #, c-format | ||||
| msgid "Shade factor \"%s\" in shaded color is negative" | ||||
| msgstr "Faktor bayangan \"%s\" pada warna berbayang bernilai negatif" | ||||
|  | ||||
| #: ../src/ui/theme.c:1469 | ||||
| #, c-format | ||||
| msgid "Could not parse color \"%s\"" | ||||
| msgstr "Tak dapat membaca warna \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:1778 | ||||
| #, c-format | ||||
| msgid "Coordinate expression contains character '%s' which is not allowed" | ||||
| msgstr "Ekspresi koordinat berisi karakter '%s' yang tidak diperbolehkan" | ||||
|  | ||||
| #: ../src/ui/theme.c:1805 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Coordinate expression contains floating point number '%s' which could not be " | ||||
| "parsed" | ||||
| msgstr "" | ||||
| "Ekspresi koordinat berisi angka floating point '%s' yang tidak dapat dibaca" | ||||
|  | ||||
| #: ../src/ui/theme.c:1819 | ||||
| #, c-format | ||||
| msgid "Coordinate expression contains integer '%s' which could not be parsed" | ||||
| msgstr "Ekspresi koordinat berisi integer '%s' yang tidak dapat dibaca" | ||||
|  | ||||
| #: ../src/ui/theme.c:1940 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Coordinate expression contained unknown operator at the start of this text: " | ||||
| "\"%s\"" | ||||
| msgstr "" | ||||
| "Ekspresi koordinat berisi operator tak dikenal pada awal teks berikut: \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:1997 | ||||
| #, c-format | ||||
| msgid "Coordinate expression was empty or not understood" | ||||
| msgstr "Ekspresi koordinat kosong atau tidak dapat dimengerti" | ||||
|  | ||||
| #: ../src/ui/theme.c:2110 ../src/ui/theme.c:2120 ../src/ui/theme.c:2154 | ||||
| #, c-format | ||||
| msgid "Coordinate expression results in division by zero" | ||||
| msgstr "Ekspresi koordinat menghasilkan pembagian dengan nol" | ||||
|  | ||||
| #: ../src/ui/theme.c:2162 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Coordinate expression tries to use mod operator on a floating-point number" | ||||
| msgstr "Ekspresi koordinat menggunakan operator mod pada angka bilangan nyata" | ||||
|  | ||||
| #: ../src/ui/theme.c:2218 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Coordinate expression has an operator \"%s\" where an operand was expected" | ||||
| msgstr "Ekspresi koordinat menggunakan operator \"%s\" tanpa adanya operan" | ||||
|  | ||||
| #: ../src/ui/theme.c:2227 | ||||
| #, c-format | ||||
| msgid "Coordinate expression had an operand where an operator was expected" | ||||
| msgstr "Ekspresi koordinat menggunakan operand tanpa operator" | ||||
|  | ||||
| #: ../src/ui/theme.c:2235 | ||||
| #, c-format | ||||
| msgid "Coordinate expression ended with an operator instead of an operand" | ||||
| msgstr "" | ||||
| "Ekspresi koordinat diakhiri dengan operator, seharusnya diakhiri dengan " | ||||
| "operand" | ||||
|  | ||||
| #: ../src/ui/theme.c:2245 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Coordinate expression has operator \"%c\" following operator \"%c\" with no " | ||||
| "operand in between" | ||||
| msgstr "" | ||||
| "Ekspresi koordinat memiliki operator \"%c\" diikuti operator \"%c\" tanpa " | ||||
| "adanya operand di antarany" | ||||
|  | ||||
| #: ../src/ui/theme.c:2396 ../src/ui/theme.c:2441 | ||||
| #, c-format | ||||
| msgid "Coordinate expression had unknown variable or constant \"%s\"" | ||||
| msgstr "" | ||||
| "Ada variabel atau konstanta \"%s\" tidak diketahui pada ekspresi koordinat" | ||||
|  | ||||
| #: ../src/ui/theme.c:2495 | ||||
| #, c-format | ||||
| msgid "Coordinate expression parser overflowed its buffer." | ||||
| msgstr "Ekspresi koordinat melampaui batasannya." | ||||
|  | ||||
| #: ../src/ui/theme.c:2524 | ||||
| #, c-format | ||||
| msgid "Coordinate expression had a close parenthesis with no open parenthesis" | ||||
| msgstr "Terdapat kurung tutup tanpa kurung buka pada ekspresi koordinat" | ||||
|  | ||||
| #: ../src/ui/theme.c:2588 | ||||
| #, c-format | ||||
| msgid "Coordinate expression had an open parenthesis with no close parenthesis" | ||||
| msgstr "Terdapat kurung buka tanpa kurung tutup pada ekspresi koordinat" | ||||
|  | ||||
| #: ../src/ui/theme.c:2599 | ||||
| #, c-format | ||||
| msgid "Coordinate expression doesn't seem to have any operators or operands" | ||||
| msgstr "Ekspresi koordinat sepertinya tidak memiliki operator atau operan" | ||||
|  | ||||
| #: ../src/ui/theme.c:2812 ../src/ui/theme.c:2832 ../src/ui/theme.c:2852 | ||||
| #, c-format | ||||
| msgid "Theme contained an expression that resulted in an error: %s\n" | ||||
| msgstr "Tema mengandung ekspresi yang menghasilkan galat: %s\n" | ||||
|  | ||||
| #: ../src/ui/theme.c:4455 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/> must be " | ||||
| "specified for this frame style" | ||||
| msgstr "" | ||||
| "<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/> tidak " | ||||
| "disebutkan pada gaya frame ini" | ||||
|  | ||||
| #: ../src/ui/theme.c:4970 ../src/ui/theme.c:4995 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>" | ||||
| msgstr "" | ||||
| "<frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/> tidak ada" | ||||
|  | ||||
| #: ../src/ui/theme.c:5041 | ||||
| #, c-format | ||||
| msgid "Failed to load theme \"%s\": %s\n" | ||||
| msgstr "Gagal membuka tema \"%s\": %s\n" | ||||
|  | ||||
| #: ../src/ui/theme.c:5177 ../src/ui/theme.c:5184 ../src/ui/theme.c:5191 | ||||
| #: ../src/ui/theme.c:5198 ../src/ui/theme.c:5205 | ||||
| #, c-format | ||||
| msgid "No <%s> set for theme \"%s\"" | ||||
| msgstr "Tak ada <%s> yang ditentukan untuk tema \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:5213 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "No frame style set for window type \"%s\" in theme \"%s\", add a <window " | ||||
| "type=\"%s\" style_set=\"whatever\"/> element" | ||||
| msgstr "" | ||||
| "Tak ada gaya frame untuk tipe window \"%s\" pada tema \"%s\". Tambah dulu " | ||||
| "elemen <window type=\"%s\" style_set=\"whatever\"/>" | ||||
|  | ||||
| #: ../src/ui/theme.c:5620 ../src/ui/theme.c:5682 ../src/ui/theme.c:5745 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "User-defined constants must begin with a capital letter; \"%s\" does not" | ||||
| msgstr "" | ||||
| "Konstanta buatan pengguna harus dimulai dengan huruf besar: \"%s\" tidak" | ||||
|  | ||||
| #: ../src/ui/theme.c:5628 ../src/ui/theme.c:5690 ../src/ui/theme.c:5753 | ||||
| #, c-format | ||||
| msgid "Constant \"%s\" has already been defined" | ||||
| msgstr "Konstanta \"%s\" telah didefinisikan sebelumnya" | ||||
|  | ||||
| #. Translators: This means that an attribute which should have been found | ||||
| #. * on an XML element was not in fact found. | ||||
| #. | ||||
| #: ../src/ui/theme-parser.c:234 | ||||
| #, c-format | ||||
| msgid "No \"%s\" attribute on element <%s>" | ||||
| msgstr "Tak ada atribut \"%s\" pada elemen <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:263 ../src/ui/theme-parser.c:281 | ||||
| #, c-format | ||||
| msgid "Line %d character %d: %s" | ||||
| msgstr "Baris %d karakter %d: %s" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:481 | ||||
| #, c-format | ||||
| msgid "Attribute \"%s\" repeated twice on the same <%s> element" | ||||
| msgstr "Atribut \"%s\" diulangi dua kali pada elemen <%s> yang sama" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:505 ../src/ui/theme-parser.c:554 | ||||
| #, c-format | ||||
| msgid "Attribute \"%s\" is invalid on <%s> element in this context" | ||||
| msgstr "Atribut \"%s\" tidak diperkenankan pada elemen <%s> pada konteks ini" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:596 | ||||
| #, c-format | ||||
| msgid "Could not parse \"%s\" as an integer" | ||||
| msgstr "Tak dapat menguraikan \"%s\" sebagai integer" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:605 ../src/ui/theme-parser.c:660 | ||||
| #, c-format | ||||
| msgid "Did not understand trailing characters \"%s\" in string \"%s\"" | ||||
| msgstr "Tak mengerti karakter \"%s\" kenapa ada dibuntut string \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:615 | ||||
| #, c-format | ||||
| msgid "Integer %ld must be positive" | ||||
| msgstr "Integer %ld harus bernilai positif" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:623 | ||||
| #, c-format | ||||
| msgid "Integer %ld is too large, current max is %d" | ||||
| msgstr "Integer %ld terlalu besar, maksimal %d" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:651 ../src/ui/theme-parser.c:767 | ||||
| #, c-format | ||||
| msgid "Could not parse \"%s\" as a floating point number" | ||||
| msgstr "Tak dapat membaca \"%s\" sebagai angka floating point" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:682 ../src/ui/theme-parser.c:710 | ||||
| #, c-format | ||||
| msgid "Boolean values must be \"true\" or \"false\" not \"%s\"" | ||||
| msgstr "Nilai boolean harus \"true\" atau \"false\" dan bukannya \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:737 | ||||
| #, c-format | ||||
| msgid "Angle must be between 0.0 and 360.0, was %g\n" | ||||
| msgstr "Sudut harus ada dalam rentang 0.0 dan 360.0, dalam berkas didapat %g\n" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:800 | ||||
| #, c-format | ||||
| msgid "Alpha must be between 0.0 (invisible) and 1.0 (fully opaque), was %g\n" | ||||
| msgstr "" | ||||
| "Alpha harus ada dalam rentang 0.0 (tidak kelihatan) dan 1.0 (nampak  semua, " | ||||
| "dalam berkas didapat %g\n" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:865 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Invalid title scale \"%s\" (must be one of xx-small,x-small,small,medium," | ||||
| "large,x-large,xx-large)\n" | ||||
| msgstr "" | ||||
| "Skala judul \"%s\" tidak benar (harusnya bernilai xx-small, x-small, small, " | ||||
| "medium, large, x-large, xx-large)\n" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1021 ../src/ui/theme-parser.c:1084 | ||||
| #: ../src/ui/theme-parser.c:1118 ../src/ui/theme-parser.c:1221 | ||||
| #, c-format | ||||
| msgid "<%s> name \"%s\" used a second time" | ||||
| msgstr "Nama <%s> \"%s\" digunakan kedua kali" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1033 ../src/ui/theme-parser.c:1130 | ||||
| #: ../src/ui/theme-parser.c:1233 | ||||
| #, c-format | ||||
| msgid "<%s> parent \"%s\" has not been defined" | ||||
| msgstr "Induk <%s> \"%s\" belum didefinisikan" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1143 | ||||
| #, c-format | ||||
| msgid "<%s> geometry \"%s\" has not been defined" | ||||
| msgstr "Geometri <%s> \"%s\" belum didefinisikan" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1156 | ||||
| #, c-format | ||||
| msgid "<%s> must specify either a geometry or a parent that has a geometry" | ||||
| msgstr "<%s> harus menentukan geometri atau induk yang ada geometrinya" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1198 | ||||
| msgid "You must specify a background for an alpha value to be meaningful" | ||||
| msgstr "" | ||||
| "Anda mesti menyatakan suatu latar belakang bagi nilai alfa agar berarti" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1266 | ||||
| #, c-format | ||||
| msgid "Unknown type \"%s\" on <%s> element" | ||||
| msgstr "Tipe \"%s\" tidak dikenal pada elemen <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1277 | ||||
| #, c-format | ||||
| msgid "Unknown style_set \"%s\" on <%s> element" | ||||
| msgstr "style_set \"%s\" tidak dikenali pada elemen <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1285 | ||||
| #, c-format | ||||
| msgid "Window type \"%s\" has already been assigned a style set" | ||||
| msgstr "Tipe jendela \"%s\" sudah memiliki set gaya" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1315 ../src/ui/theme-parser.c:1379 | ||||
| #: ../src/ui/theme-parser.c:1605 ../src/ui/theme-parser.c:2840 | ||||
| #: ../src/ui/theme-parser.c:2886 ../src/ui/theme-parser.c:3036 | ||||
| #: ../src/ui/theme-parser.c:3272 ../src/ui/theme-parser.c:3310 | ||||
| #: ../src/ui/theme-parser.c:3348 ../src/ui/theme-parser.c:3386 | ||||
| #, c-format | ||||
| msgid "Element <%s> is not allowed below <%s>" | ||||
| msgstr "Elemen <%s> tidak diperkenankan ada di bawah <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1429 ../src/ui/theme-parser.c:1443 | ||||
| #: ../src/ui/theme-parser.c:1488 | ||||
| msgid "" | ||||
| "Cannot specify both \"button_width\"/\"button_height\" and \"aspect_ratio\" " | ||||
| "for buttons" | ||||
| msgstr "" | ||||
| "Tak dapat menyatakan \"button_width\"/\"button_height\" dan \"aspect_ratio\" " | ||||
| "sekaligus untuk tombol" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1452 | ||||
| #, c-format | ||||
| msgid "Distance \"%s\" is unknown" | ||||
| msgstr "Jarak \"%s\" tidak dikenal" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1497 | ||||
| #, c-format | ||||
| msgid "Aspect ratio \"%s\" is unknown" | ||||
| msgstr "Rasio aspek \"%s\" tidak dikenal" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1559 | ||||
| #, c-format | ||||
| msgid "Border \"%s\" is unknown" | ||||
| msgstr "Batas \"%s\" tidak dikenal" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1870 | ||||
| #, c-format | ||||
| msgid "No \"start_angle\" or \"from\" attribute on element <%s>" | ||||
| msgstr "Tak ada atribut \"start_angle\" atau \"from\" pada elemen <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1877 | ||||
| #, c-format | ||||
| msgid "No \"extent_angle\" or \"to\" attribute on element <%s>" | ||||
| msgstr "Tak ada atribut \"extent_angle\" atau \"to\" pada elemen <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2117 | ||||
| #, c-format | ||||
| msgid "Did not understand value \"%s\" for type of gradient" | ||||
| msgstr "Nilai \"%s\" bukan nilai yang sah untuk tipe gradien" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2195 ../src/ui/theme-parser.c:2570 | ||||
| #, c-format | ||||
| msgid "Did not understand fill type \"%s\" for <%s> element" | ||||
| msgstr "Tipe isian \"%s\" tidak dikenal untuk elemen <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2362 ../src/ui/theme-parser.c:2445 | ||||
| #: ../src/ui/theme-parser.c:2508 | ||||
| #, c-format | ||||
| msgid "Did not understand state \"%s\" for <%s> element" | ||||
| msgstr "Kondisi \"%s\" tidak dikenal untuk elemen <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2372 ../src/ui/theme-parser.c:2455 | ||||
| #, c-format | ||||
| msgid "Did not understand shadow \"%s\" for <%s> element" | ||||
| msgstr "Bayangan \"%s\" tidak dikenal untuk elemen <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2382 | ||||
| #, c-format | ||||
| msgid "Did not understand arrow \"%s\" for <%s> element" | ||||
| msgstr "Panah \"%s\" tidak dikenal untuk elemen <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2696 ../src/ui/theme-parser.c:2792 | ||||
| #, c-format | ||||
| msgid "No <draw_ops> called \"%s\" has been defined" | ||||
| msgstr "Tak ada <draw_ops> bernama \"%s\" yang telah didefinisikan" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2708 ../src/ui/theme-parser.c:2804 | ||||
| #, c-format | ||||
| msgid "Including draw_ops \"%s\" here would create a circular reference" | ||||
| msgstr "" | ||||
| "Menyertakan draw_ops \"%s\" di sini akan membuat referensi tak berujung" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2919 | ||||
| #, c-format | ||||
| msgid "Unknown position \"%s\" for frame piece" | ||||
| msgstr "Posisi \"%s\" tidak dikenal untuk bagian frame" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2927 | ||||
| #, c-format | ||||
| msgid "Frame style already has a piece at position %s" | ||||
| msgstr "Gaya frame sudah memiliki bagian pada posisi %s" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2944 ../src/ui/theme-parser.c:3021 | ||||
| #, c-format | ||||
| msgid "No <draw_ops> with the name \"%s\" has been defined" | ||||
| msgstr "Tak ada <draw_ops> dengan nama \"%s\" yang didefinisikan" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2974 | ||||
| #, c-format | ||||
| msgid "Unknown function \"%s\" for button" | ||||
| msgstr "Fungsi \"%s\" tidak dikenal untuk tombol" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2984 | ||||
| #, c-format | ||||
| msgid "Button function \"%s\" does not exist in this version (%d, need %d)" | ||||
| msgstr "" | ||||
| "Tombol fungsi \"%s\" tidak tersedia untuk versi ini (%d, memerlukan %d)" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2996 | ||||
| #, c-format | ||||
| msgid "Unknown state \"%s\" for button" | ||||
| msgstr "Kondisi \"%s\" tidak dikenal untuk tombol" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3004 | ||||
| #, c-format | ||||
| msgid "Frame style already has a button for function %s state %s" | ||||
| msgstr "Gaya bingkai sudah memiliki tombol untuk fungsi %s kondisi %s" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3075 | ||||
| #, c-format | ||||
| msgid "\"%s\" is not a valid value for focus attribute" | ||||
| msgstr "\"%s\" bukan nilai yang benar untuk atribut focus" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3084 | ||||
| #, c-format | ||||
| msgid "\"%s\" is not a valid value for state attribute" | ||||
| msgstr "\"%s\" bukan nilai yang benar untuk atribut state" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3094 | ||||
| #, c-format | ||||
| msgid "A style called \"%s\" has not been defined" | ||||
| msgstr "Gaya bernama \"%s\" belum didefinisikan" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3115 ../src/ui/theme-parser.c:3138 | ||||
| #, c-format | ||||
| msgid "\"%s\" is not a valid value for resize attribute" | ||||
| msgstr "\"%s\" bukan nilai yang benar untuk atribut resize" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3149 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Should not have \"resize\" attribute on <%s> element for maximized/shaded " | ||||
| "states" | ||||
| msgstr "" | ||||
| "Atribut \"resize\" tidak boleh ada pada elemen <%s> untuk kondisi ukuran " | ||||
| "window maksimum/tergulung" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3163 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Should not have \"resize\" attribute on <%s> element for maximized states" | ||||
| msgstr "" | ||||
| "Atribut \"resize\" tidak boleh ada pada elemen <%s> untuk kondisi ukuran " | ||||
| "jendela maksimal" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3177 ../src/ui/theme-parser.c:3221 | ||||
| #, c-format | ||||
| msgid "Style has already been specified for state %s resize %s focus %s" | ||||
| msgstr "Gaya sudah menjelaskan kondisi %s resize %s focus %s" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3188 ../src/ui/theme-parser.c:3199 | ||||
| #: ../src/ui/theme-parser.c:3210 ../src/ui/theme-parser.c:3232 | ||||
| #: ../src/ui/theme-parser.c:3243 ../src/ui/theme-parser.c:3254 | ||||
| #, c-format | ||||
| msgid "Style has already been specified for state %s focus %s" | ||||
| msgstr "Gaya sudah menjelaskan kondisi %s focus %s" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3293 | ||||
| msgid "" | ||||
| "Can't have a two draw_ops for a <piece> element (theme specified a draw_ops " | ||||
| "attribute and also a <draw_ops> element, or specified two elements)" | ||||
| msgstr "" | ||||
| "Tak boleh ada dua draw_ops untuk elemen <piece> (tema menyebutkan atribut " | ||||
| "draw_ops dan juga elemen <draw_ops> atau meyebutkan dua elemen tersebut " | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3331 | ||||
| msgid "" | ||||
| "Can't have a two draw_ops for a <button> element (theme specified a draw_ops " | ||||
| "attribute and also a <draw_ops> element, or specified two elements)" | ||||
| msgstr "" | ||||
| "Tak boleh ada dua draw_ops untuk elemen <button> (tema menyebutkan atribut " | ||||
| "draw_ops dan juga elemen <draw_ops> atau meyebutkan dua elemen tersebut " | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3369 | ||||
| msgid "" | ||||
| "Can't have a two draw_ops for a <menu_icon> element (theme specified a " | ||||
| "draw_ops attribute and also a <draw_ops> element, or specified two elements)" | ||||
| msgstr "" | ||||
| "Tak boleh ada dua draw_ops untuk elemen <menu_icon> (tema menyebutkan " | ||||
| "atribut draw_ops dan juga elemen <draw_ops> atau meyebutkan dua elemen " | ||||
| "tersebut " | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3433 | ||||
| #, c-format | ||||
| msgid "Bad version specification '%s'" | ||||
| msgstr "Spesifikasi versi '%s' jelek" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3506 | ||||
| msgid "" | ||||
| "\"version\" attribute cannot be used in metacity-theme-1.xml or metacity-" | ||||
| "theme-2.xml" | ||||
| msgstr "" | ||||
| "Atribut \"version\" tidak dapat dipakai dalam metacity-theme-1.xml atau " | ||||
| "metacity-theme-2.xml" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3529 | ||||
| #, c-format | ||||
| msgid "Theme requires version %s but latest supported theme version is %d.%d" | ||||
| msgstr "Tema memerlukan versi %s tetapi versi yang didukung adalah %d.%d" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3561 | ||||
| #, c-format | ||||
| msgid "Outermost element in theme must be <metacity_theme> not <%s>" | ||||
| msgstr "Elemen tema paling luar haruslah <metacity_theme> dan bukan <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3581 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Element <%s> is not allowed inside a name/author/date/description element" | ||||
| msgstr "" | ||||
| "Elemen <%s> tidak diperbolehkan berada elemen name/author/date/description" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3586 | ||||
| #, c-format | ||||
| msgid "Element <%s> is not allowed inside a <constant> element" | ||||
| msgstr "Elemen <%s> tidak boleh ada dalam elemen <constat>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3598 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Element <%s> is not allowed inside a distance/border/aspect_ratio element" | ||||
| msgstr "" | ||||
| "Elemen <%s> tidak boleh ada di dalam elemen distance/border/aspec_ratio" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3620 | ||||
| #, c-format | ||||
| msgid "Element <%s> is not allowed inside a draw operation element" | ||||
| msgstr "Elemen <%s> tidak boleh ada di dalam elemen operasi gambar" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3630 ../src/ui/theme-parser.c:3660 | ||||
| #: ../src/ui/theme-parser.c:3665 ../src/ui/theme-parser.c:3670 | ||||
| #, c-format | ||||
| msgid "Element <%s> is not allowed inside a <%s> element" | ||||
| msgstr "Elemen <%s> tidak boleh ada di dalam elemen <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3898 | ||||
| msgid "No draw_ops provided for frame piece" | ||||
| msgstr "Tak ada draw_ops yang disediakan untuk bagian frame" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3913 | ||||
| msgid "No draw_ops provided for button" | ||||
| msgstr "Tak ada draw_ops yang disediakan untuk tombol" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3967 | ||||
| #, c-format | ||||
| msgid "No text is allowed inside element <%s>" | ||||
| msgstr "Tak boleh ada teks di dalam elemen <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:4025 ../src/ui/theme-parser.c:4037 | ||||
| #: ../src/ui/theme-parser.c:4049 ../src/ui/theme-parser.c:4061 | ||||
| #: ../src/ui/theme-parser.c:4073 | ||||
| #, c-format | ||||
| msgid "<%s> specified twice for this theme" | ||||
| msgstr "<%s> disebutkan dua kali pada tema ini" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:4335 | ||||
| #, c-format | ||||
| msgid "Failed to find a valid file for theme %s\n" | ||||
| msgstr "Gagal menemukan berkas yang sah untuk tema %s\n" | ||||
|  | ||||
| #: ../src/x11/session.c:1815 | ||||
| msgid "" | ||||
| "These windows do not support "save current setup" and will have to " | ||||
| @@ -1284,7 +604,7 @@ msgstr "" | ||||
| "Jendela ini tidak bisa "menyimpan setelan aktif saat ini" dan bila " | ||||
| "log masuk kali lain Anda harus menjalankannya ulang." | ||||
|  | ||||
| #: ../src/x11/window-props.c:515 | ||||
| #: ../src/x11/window-props.c:549 | ||||
| #, c-format | ||||
| msgid "%s (on %s)" | ||||
| msgstr "%s (pada %s)" | ||||
|   | ||||
							
								
								
									
										822
									
								
								po/pl.po
									
									
									
									
									
								
							
							
						
						
									
										822
									
								
								po/pl.po
									
									
									
									
									
								
							| @@ -9,14 +9,14 @@ | ||||
| # Marek Stępień <marcoos@aviary.pl>, 2007. | ||||
| # Wadim Dziedzic <wdziedzic@aviary.pl>, 2007. | ||||
| # Tomasz Dominikowski <dominikowski@gmail.com>, 2008-2009. | ||||
| # Piotr Drąg <piotrdrag@gmail.com>, 2010-2014. | ||||
| # Aviary.pl <gnomepl@aviary.pl>, 2007-2014. | ||||
| # Piotr Drąg <piotrdrag@gmail.com>, 2010-2015. | ||||
| # Aviary.pl <gnomepl@aviary.pl>, 2007-2015. | ||||
| msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: mutter\n" | ||||
| "Report-Msgid-Bugs-To: \n" | ||||
| "POT-Creation-Date: 2014-09-03 15:55+0200\n" | ||||
| "PO-Revision-Date: 2014-09-03 15:58+0200\n" | ||||
| "POT-Creation-Date: 2015-08-26 18:49+0200\n" | ||||
| "PO-Revision-Date: 2015-08-26 18:50+0200\n" | ||||
| "Last-Translator: Piotr Drąg <piotrdrag@gmail.com>\n" | ||||
| "Language-Team: Polish <gnomepl@aviary.pl>\n" | ||||
| "Language: pl\n" | ||||
| @@ -285,9 +285,9 @@ msgid "" | ||||
| "\"Windows key\" on PC hardware. It's expected that this binding either the " | ||||
| "default or set to the empty string." | ||||
| msgstr "" | ||||
| "Ten klawisz inicjuje tryb \"overlay\", który jest połączeniem podglądu okien " | ||||
| "i systemu uruchamiania programów. Domyślnie jest przeznaczony do powiązania " | ||||
| "z klawiszem \"Windows\" na komputerach typu PC. Ustawienie tego powiązania " | ||||
| "Ten klawisz inicjuje tryb „overlay”, który jest połączeniem podglądu okien i " | ||||
| "systemu uruchamiania programów. Domyślnie jest przeznaczony do powiązania z " | ||||
| "klawiszem „Windows” na komputerach typu PC. Ustawienie tego powiązania " | ||||
| "powinno być domyślne lub puste." | ||||
|  | ||||
| #: ../data/org.gnome.mutter.gschema.xml.in.h:3 | ||||
| @@ -300,9 +300,9 @@ msgid "" | ||||
| "attached to the titlebar of the parent window and are moved together with " | ||||
| "the parent window." | ||||
| msgstr "" | ||||
| "Jeśli wynosi \"true\", to modalne okna dialogowe pojawiają się dołączone do " | ||||
| "paska tytułowego okna nadrzędnego zamiast posiadać oddzielne paski tytułowe " | ||||
| "i są przenoszone razem z nim." | ||||
| "Jeśli wynosi wartość „true”, to modalne okna dialogowe pojawiają się " | ||||
| "dołączone do paska tytułowego okna nadrzędnego zamiast posiadać oddzielne " | ||||
| "paski tytułowe i są przenoszone razem z nim." | ||||
|  | ||||
| #: ../data/org.gnome.mutter.gschema.xml.in.h:5 | ||||
| msgid "Enable edge tiling when dropping windows on screen edges" | ||||
| @@ -332,7 +332,7 @@ msgid "" | ||||
| "gnome.desktop.wm.preferences)." | ||||
| msgstr "" | ||||
| "Określa, czy obszary robocze są zarządzane dynamicznie, czy istnieje " | ||||
| "statyczna liczba obszarów (określona przez klucz \"num-workspaces\" w org." | ||||
| "statyczna liczba obszarów (określona przez klucz „num-workspaces” w org." | ||||
| "gnome.desktop.wm.preferences)." | ||||
|  | ||||
| #: ../data/org.gnome.mutter.gschema.xml.in.h:9 | ||||
| @@ -369,9 +369,9 @@ msgid "" | ||||
| "the focus will not be changed immediately when entering a window, but only " | ||||
| "after the pointer stops moving." | ||||
| msgstr "" | ||||
| "Jeśli jest ustawione na wartość \"true\", a tryb aktywności to \"sloppy\" " | ||||
| "lub \"mouse\", to aktywność nie będzie zmieniana od razu po przejściu do " | ||||
| "okna, ale dopiero po zatrzymaniu ruchu kursora." | ||||
| "Jeśli jest ustawione na wartość „true”, a tryb aktywności to „sloppy” lub " | ||||
| "„mouse”, to aktywność nie będzie zmieniana od razu po przejściu do okna, ale " | ||||
| "dopiero po zatrzymaniu ruchu kursora." | ||||
|  | ||||
| #: ../data/org.gnome.mutter.gschema.xml.in.h:15 | ||||
| msgid "Draggable border width" | ||||
| @@ -409,7 +409,7 @@ msgid "" | ||||
| "When true, the new windows will always be put in the center of the active " | ||||
| "screen of the monitor." | ||||
| msgstr "" | ||||
| "Jeśli wynosi \"true\", to nowe okna będą zawsze umieszczane na środku " | ||||
| "Jeśli wynosi wartość „true”, to nowe okna będą zawsze umieszczane na środku " | ||||
| "aktywnego ekranu monitora." | ||||
|  | ||||
| #: ../data/org.gnome.mutter.gschema.xml.in.h:21 | ||||
| @@ -448,39 +448,55 @@ msgstr "Przełączenie na 6. konsolę wirtualną" | ||||
| msgid "Switch to VT 7" | ||||
| msgstr "Przełączenie na 7. konsolę wirtualną" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:412 | ||||
| #: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:8 | ||||
| msgid "Switch to VT 8" | ||||
| msgstr "Przełączenie na 8. konsolę wirtualną" | ||||
|  | ||||
| #: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:9 | ||||
| msgid "Switch to VT 9" | ||||
| msgstr "Przełączenie na 9. konsolę wirtualną" | ||||
|  | ||||
| #: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:10 | ||||
| msgid "Switch to VT 10" | ||||
| msgstr "Przełączenie na 10. konsolę wirtualną" | ||||
|  | ||||
| #: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:11 | ||||
| msgid "Switch to VT 11" | ||||
| msgstr "Przełączenie na 11. konsolę wirtualną" | ||||
|  | ||||
| #: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:12 | ||||
| msgid "Switch to VT 12" | ||||
| msgstr "Przełączenie na 12. konsolę wirtualną" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:500 | ||||
| msgid "Built-in display" | ||||
| msgstr "Wbudowany ekran" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:437 | ||||
| #: ../src/backends/meta-monitor-manager.c:526 | ||||
| msgid "Unknown" | ||||
| msgstr "Nieznany" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:439 | ||||
| #: ../src/backends/meta-monitor-manager.c:528 | ||||
| msgid "Unknown Display" | ||||
| msgstr "Nieznany ekran" | ||||
|  | ||||
| #. TRANSLATORS: this is a monitor vendor name, followed by a | ||||
| #. * size in inches, like 'Dell 15"' | ||||
| #. | ||||
| #: ../src/backends/meta-monitor-manager.c:447 | ||||
| #: ../src/backends/meta-monitor-manager.c:536 | ||||
| #, c-format | ||||
| msgid "%s %s" | ||||
| msgstr "%s %s" | ||||
|  | ||||
| #. This probably means that a non-WM compositor like xcompmgr is running; | ||||
| #. * we have no way to get it to exit | ||||
| #: ../src/compositor/compositor.c:443 | ||||
| #: ../src/compositor/compositor.c:456 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Another compositing manager is already running on screen %i on display \"%s" | ||||
| "\"." | ||||
| msgstr "" | ||||
| "Inny menedżer składania jest już uruchomiony na podekranie %i ekranu \"%s\"." | ||||
|  | ||||
| #: ../src/compositor/meta-background.c:1044 | ||||
| msgid "background texture could not be created from file" | ||||
| msgstr "nie można utworzyć tekstury tła z pliku" | ||||
| "Inny menedżer składania jest już uruchomiony na podekranie %i ekranu „%s”." | ||||
|  | ||||
| #: ../src/core/bell.c:185 | ||||
| msgid "Bell event" | ||||
| @@ -489,7 +505,7 @@ msgstr "Zdarzenie sygnału dźwiękowego" | ||||
| #: ../src/core/delete.c:127 | ||||
| #, c-format | ||||
| msgid "“%s” is not responding." | ||||
| msgstr "Okno \"%s\" nie odpowiada." | ||||
| msgstr "Okno „%s” nie odpowiada." | ||||
|  | ||||
| #: ../src/core/delete.c:129 | ||||
| msgid "Application is not responding." | ||||
| @@ -509,11 +525,10 @@ msgstr "_Czekaj" | ||||
| msgid "_Force Quit" | ||||
| msgstr "_Zakończ" | ||||
|  | ||||
| #: ../src/core/display.c:547 | ||||
| #: ../src/core/display.c:563 | ||||
| #, c-format | ||||
| msgid "Failed to open X Window System display '%s'\n" | ||||
| msgstr "" | ||||
| "Otwarcie połączenia z ekranem \"%s\" systemu X Window się nie powiodło\n" | ||||
| msgstr "Otwarcie połączenia z ekranem „%s” systemu X Window się nie powiodło\n" | ||||
|  | ||||
| #: ../src/core/main.c:176 | ||||
| msgid "Disable connection to session manager" | ||||
| @@ -547,19 +562,6 @@ msgstr "Uruchamia jako menedżer składania Wayland" | ||||
| msgid "Run as a full display server, rather than nested" | ||||
| msgstr "Uruchamia pełny serwer wyświetlania zamiast osadzonego" | ||||
|  | ||||
| #: ../src/core/main.c:459 | ||||
| #, c-format | ||||
| msgid "Failed to scan themes directory: %s\n" | ||||
| msgstr "Przejrzenie katalogu z motywami się nie powiodło: %s\n" | ||||
|  | ||||
| #: ../src/core/main.c:475 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Could not find a theme! Be sure %s exists and contains the usual themes.\n" | ||||
| msgstr "" | ||||
| "Nie można odnaleźć żadnego motywu. Proszę sprawdzić, czy katalog %s istnieje " | ||||
| "i zawiera standardowe motywy.\n" | ||||
|  | ||||
| #: ../src/core/mutter.c:39 | ||||
| #, c-format | ||||
| msgid "" | ||||
| @@ -570,7 +572,7 @@ msgid "" | ||||
| "PARTICULAR PURPOSE.\n" | ||||
| msgstr "" | ||||
| "mutter %s\n" | ||||
| "Copyright (C) 2001-%d Havoc Pennington, Red Hat, Inc., oraz inni\n" | ||||
| "Copyright (C) 2001—%d Havoc Pennington, Red Hat, Inc., oraz inni\n" | ||||
| "Niniejszy program jest wolnym oprogramowaniem, aby poznać warunki, pod\n" | ||||
| "jakimi dopuszczalne jest kopiowanie programu, zajrzyj do jego źródeł.\n" | ||||
| "Na program nie udziela się ŻADNYCH GWARANCJI, nawet domyślnej gwarancji\n" | ||||
| @@ -584,749 +586,39 @@ msgstr "Wyświetla wersję" | ||||
| msgid "Mutter plugin to use" | ||||
| msgstr "Używana wtyczka programu Mutter" | ||||
|  | ||||
| #: ../src/core/prefs.c:2101 | ||||
| #: ../src/core/prefs.c:2004 | ||||
| #, c-format | ||||
| msgid "Workspace %d" | ||||
| msgstr "Obszar roboczy %d" | ||||
|  | ||||
| #: ../src/core/screen.c:548 | ||||
| #, c-format | ||||
| msgid "Screen %d on display '%s' is invalid\n" | ||||
| msgstr "Podekran %d ekranu \"%s\" jest nieprawidłowy\n" | ||||
|  | ||||
| #: ../src/core/screen.c:564 | ||||
| #: ../src/core/screen.c:525 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Screen %d on display \"%s\" already has a window manager; try using the --" | ||||
| "replace option to replace the current window manager.\n" | ||||
| "Display \"%s\" already has a window manager; try using the --replace option " | ||||
| "to replace the current window manager." | ||||
| msgstr "" | ||||
| "Na podekranie %d ekranu \"%s\" działa już menedżer okien. Aby zastąpić " | ||||
| "działającego menedżera okien, proszę spróbować użyć opcji --replace.\n" | ||||
| "Na ekranie „%s” działa już menedżer okien. Aby zastąpić działającego " | ||||
| "menedżera okien, proszę spróbować użyć opcji --replace." | ||||
|  | ||||
| #: ../src/core/screen.c:657 | ||||
| #: ../src/core/screen.c:607 | ||||
| #, c-format | ||||
| msgid "Screen %d on display \"%s\" already has a window manager\n" | ||||
| msgstr "Na podekranie %d ekranu \"%s\" działa już menedżer okien\n" | ||||
| msgid "Screen %d on display '%s' is invalid\n" | ||||
| msgstr "Podekran %d ekranu „%s” jest nieprawidłowy\n" | ||||
|  | ||||
| #: ../src/core/util.c:118 | ||||
| msgid "Mutter was compiled without support for verbose mode\n" | ||||
| msgstr "" | ||||
| "Program Mutter został skompilowany bez obsługi trybu z obszerną informacją\n" | ||||
|  | ||||
| #. Translators: This represents the size of a window.  The first number is | ||||
| #. * the width of the window and the second is the height. | ||||
| #. | ||||
| #: ../src/ui/resizepopup.c:134 | ||||
| #, c-format | ||||
| msgid "%d x %d" | ||||
| msgstr "%d x %d" | ||||
|  | ||||
| #: ../src/ui/theme.c:233 | ||||
| msgid "top" | ||||
| msgstr "góra" | ||||
|  | ||||
| #: ../src/ui/theme.c:235 | ||||
| msgid "bottom" | ||||
| msgstr "dół" | ||||
|  | ||||
| #: ../src/ui/theme.c:237 | ||||
| msgid "left" | ||||
| msgstr "lewa" | ||||
|  | ||||
| #: ../src/ui/theme.c:239 | ||||
| msgid "right" | ||||
| msgstr "prawa" | ||||
|  | ||||
| #: ../src/ui/theme.c:267 | ||||
| #, c-format | ||||
| msgid "frame geometry does not specify \"%s\" dimension" | ||||
| msgstr "Rozmiar ramki nie określa wymiaru \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:286 | ||||
| #, c-format | ||||
| msgid "frame geometry does not specify dimension \"%s\" for border \"%s\"" | ||||
| msgstr "Rozmiar ramki nie określa wymiaru \"%s\" dla krawędzi \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:323 | ||||
| #, c-format | ||||
| msgid "Button aspect ratio %g is not reasonable" | ||||
| msgstr "" | ||||
| "Współczynnik proporcji przycisku %g nie mieści się w rozsądnych granicach" | ||||
|  | ||||
| #: ../src/ui/theme.c:335 | ||||
| #, c-format | ||||
| msgid "Frame geometry does not specify size of buttons" | ||||
| msgstr "Rozmiar ramki nie określa liczby przycisków" | ||||
|  | ||||
| #: ../src/ui/theme.c:1061 | ||||
| #, c-format | ||||
| msgid "Gradients should have at least two colors" | ||||
| msgstr "Gradienty powinny się składać co najmniej z dwóch kolorów" | ||||
|  | ||||
| #: ../src/ui/theme.c:1211 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "GTK custom color specification must have color name and fallback in " | ||||
| "parentheses, e.g. gtk:custom(foo,bar); could not parse \"%s\"" | ||||
| msgstr "" | ||||
| "Własna specyfikacja koloru biblioteki GTK+ musi posiadać nazwę koloru i " | ||||
| "kolor zastępczy w nawiasach, np. gtk:custom(foo,bar); nie można przetworzyć " | ||||
| "\"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:1227 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-" | ||||
| "_ are valid" | ||||
| msgstr "" | ||||
| "Nieprawidłowy znak \"%c\" w parametrze nazwa_koloru opcji gtk:custom, tylko " | ||||
| "znaki A-Za-z0-9-_ są prawidłowe" | ||||
|  | ||||
| #: ../src/ui/theme.c:1241 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not " | ||||
| "fit the format" | ||||
| msgstr "" | ||||
| "Formatem Gtk:custom jest \"gtk:custom(nazwa_koloru,kolor_zastępczy)\", \"%s" | ||||
| "\" nie pasuje do formatu" | ||||
|  | ||||
| #: ../src/ui/theme.c:1286 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "GTK color specification must have the state in brackets, e.g. gtk:fg[NORMAL] " | ||||
| "where NORMAL is the state; could not parse \"%s\"" | ||||
| msgstr "" | ||||
| "Specyfikacja koloru biblioteki GTK+ musi zawierać stan w nawiasach " | ||||
| "kwadratowych, np. gtk:fg[NORMAL], gdzie NORMAL jest nazwą stanu; nie można " | ||||
| "przetworzyć \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:1300 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "GTK color specification must have a close bracket after the state, e.g. gtk:" | ||||
| "fg[NORMAL] where NORMAL is the state; could not parse \"%s\"" | ||||
| msgstr "" | ||||
| "Specyfikacja koloru biblioteki GTK+ musi po nazwie stanu zawierać zamykający " | ||||
| "nawias kwadratowy, np. gtk:fg[NORMAL], gdzie NORMAL jest nazwą stanu; nie " | ||||
| "można przetworzyć \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:1311 | ||||
| #, c-format | ||||
| msgid "Did not understand state \"%s\" in color specification" | ||||
| msgstr "Niezrozumiały stan \"%s\" w specyfikacji koloru" | ||||
|  | ||||
| #: ../src/ui/theme.c:1324 | ||||
| #, c-format | ||||
| msgid "Did not understand color component \"%s\" in color specification" | ||||
| msgstr "Niezrozumiała definicja koloru \"%s\" w specyfikacji koloru" | ||||
|  | ||||
| #: ../src/ui/theme.c:1352 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Blend format is \"blend/bg_color/fg_color/alpha\", \"%s\" does not fit the " | ||||
| "format" | ||||
| msgstr "" | ||||
| "Formatem przenikania jest \"blend/bg_color/fg_color/alpha\", \"%s\" nie " | ||||
| "pasuje do formatu" | ||||
|  | ||||
| #: ../src/ui/theme.c:1363 | ||||
| #, c-format | ||||
| msgid "Could not parse alpha value \"%s\" in blended color" | ||||
| msgstr "Nie można przetworzyć wartości alfa \"%s\" w przenikającym kolorze" | ||||
|  | ||||
| #: ../src/ui/theme.c:1373 | ||||
| #, c-format | ||||
| msgid "Alpha value \"%s\" in blended color is not between 0.0 and 1.0" | ||||
| msgstr "" | ||||
| "Wartość alfa \"%s\" w przenikającym kolorze nie zawiera się pomiędzy 0,0 i " | ||||
| "1,0" | ||||
|  | ||||
| #: ../src/ui/theme.c:1419 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Shade format is \"shade/base_color/factor\", \"%s\" does not fit the format" | ||||
| msgstr "" | ||||
| "Formatem przenikania jest \"shade/base_color/factor\", \"%s\" nie pasuje do " | ||||
| "formatu" | ||||
|  | ||||
| #: ../src/ui/theme.c:1430 | ||||
| #, c-format | ||||
| msgid "Could not parse shade factor \"%s\" in shaded color" | ||||
| msgstr "" | ||||
| "Nie można przetworzyć współczynnika przenikania \"%s\" w przenikającym " | ||||
| "kolorze" | ||||
|  | ||||
| #: ../src/ui/theme.c:1440 | ||||
| #, c-format | ||||
| msgid "Shade factor \"%s\" in shaded color is negative" | ||||
| msgstr "Współczynnik przenikania \"%s\" w przenikającym kolorze jest ujemny" | ||||
|  | ||||
| #: ../src/ui/theme.c:1469 | ||||
| #, c-format | ||||
| msgid "Could not parse color \"%s\"" | ||||
| msgstr "Nie można przetworzyć koloru \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:1778 | ||||
| #, c-format | ||||
| msgid "Coordinate expression contains character '%s' which is not allowed" | ||||
| msgstr "Wyrażenie określające współrzędne zawiera niedozwolony znak \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:1805 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Coordinate expression contains floating point number '%s' which could not be " | ||||
| "parsed" | ||||
| msgstr "" | ||||
| "Wyrażenie określające współrzędne zawiera liczbę zmiennoprzecinkową \"%s\", " | ||||
| "której nie można przetworzyć" | ||||
|  | ||||
| #: ../src/ui/theme.c:1819 | ||||
| #, c-format | ||||
| msgid "Coordinate expression contains integer '%s' which could not be parsed" | ||||
| msgstr "" | ||||
| "Wyrażenie określające współrzędne zawiera liczbę całkowitą \"%s\", której " | ||||
| "nie można przetworzyć" | ||||
|  | ||||
| #: ../src/ui/theme.c:1940 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Coordinate expression contained unknown operator at the start of this text: " | ||||
| "\"%s\"" | ||||
| msgstr "" | ||||
| "Wyrażenie określające współrzędne zawiera nieznany operator na początku " | ||||
| "tekstu: \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:1997 | ||||
| #, c-format | ||||
| msgid "Coordinate expression was empty or not understood" | ||||
| msgstr "" | ||||
| "Wyrażenie określające współrzędne jest puste lub nie można go rozpoznać" | ||||
|  | ||||
| #: ../src/ui/theme.c:2110 ../src/ui/theme.c:2120 ../src/ui/theme.c:2154 | ||||
| #, c-format | ||||
| msgid "Coordinate expression results in division by zero" | ||||
| msgstr "Wyrażenie opisujące położenie zawiera dzielenie przez zero" | ||||
|  | ||||
| #: ../src/ui/theme.c:2162 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Coordinate expression tries to use mod operator on a floating-point number" | ||||
| msgstr "" | ||||
| "Wyrażenie opisujące położenie używa operatora dzielenia modulo z liczbą " | ||||
| "zmiennoprzecinkową" | ||||
|  | ||||
| #: ../src/ui/theme.c:2218 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Coordinate expression has an operator \"%s\" where an operand was expected" | ||||
| msgstr "" | ||||
| "Wyrażenie opisujące położenie zawiera operator \"%s\" w miejscu, w którym " | ||||
| "oczekiwano operandu" | ||||
|  | ||||
| #: ../src/ui/theme.c:2227 | ||||
| #, c-format | ||||
| msgid "Coordinate expression had an operand where an operator was expected" | ||||
| msgstr "" | ||||
| "Wyrażenie opisujące położenie zawiera operand w miejscu, w którym oczekiwano " | ||||
| "operatora" | ||||
|  | ||||
| #: ../src/ui/theme.c:2235 | ||||
| #, c-format | ||||
| msgid "Coordinate expression ended with an operator instead of an operand" | ||||
| msgstr "Wyrażenie opisujące położenie kończy się operatorem zamiast operandem" | ||||
|  | ||||
| #: ../src/ui/theme.c:2245 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Coordinate expression has operator \"%c\" following operator \"%c\" with no " | ||||
| "operand in between" | ||||
| msgstr "" | ||||
| "Wyrażenie opisujące położenie zawiera operator \"%c\" bezpośrednio po " | ||||
| "operatorze \"%c\" bez rozdzielającego ich operandu" | ||||
|  | ||||
| #: ../src/ui/theme.c:2396 ../src/ui/theme.c:2441 | ||||
| #, c-format | ||||
| msgid "Coordinate expression had unknown variable or constant \"%s\"" | ||||
| msgstr "" | ||||
| "Wyrażenie opisujące położenie zawiera nieznaną zmienną lub stałą \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:2495 | ||||
| #, c-format | ||||
| msgid "Coordinate expression parser overflowed its buffer." | ||||
| msgstr "Parser wyrażeń określających współrzędne przepełnił swój bufor." | ||||
|  | ||||
| #: ../src/ui/theme.c:2524 | ||||
| #, c-format | ||||
| msgid "Coordinate expression had a close parenthesis with no open parenthesis" | ||||
| msgstr "" | ||||
| "Wyrażenie opisujące położenie zawiera nawias zamykający bez odpowiadającego " | ||||
| "mu nawiasu otwierającego" | ||||
|  | ||||
| #: ../src/ui/theme.c:2588 | ||||
| #, c-format | ||||
| msgid "Coordinate expression had an open parenthesis with no close parenthesis" | ||||
| msgstr "" | ||||
| "Wyrażenie opisujące położenie zawiera nawias otwierający bez odpowiadającego " | ||||
| "mu nawiasu zamykającego" | ||||
|  | ||||
| #: ../src/ui/theme.c:2599 | ||||
| #, c-format | ||||
| msgid "Coordinate expression doesn't seem to have any operators or operands" | ||||
| msgstr "" | ||||
| "Wyrażenie opisujące położenie nie zawiera żadnych operatorów ani operandów" | ||||
|  | ||||
| #: ../src/ui/theme.c:2812 ../src/ui/theme.c:2832 ../src/ui/theme.c:2852 | ||||
| #, c-format | ||||
| msgid "Theme contained an expression that resulted in an error: %s\n" | ||||
| msgstr "Motyw zawiera wyrażenie, przy którego obliczaniu wystąpił błąd: %s\n" | ||||
|  | ||||
| #: ../src/ui/theme.c:4455 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/> must be " | ||||
| "specified for this frame style" | ||||
| msgstr "" | ||||
| "Przy tym stylu ramki należy podać <button function=\"%s\" state=\"%s\" " | ||||
| "draw_ops=\"cokolwiek\"/>" | ||||
|  | ||||
| #: ../src/ui/theme.c:4970 ../src/ui/theme.c:4995 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>" | ||||
| msgstr "" | ||||
| "Brak <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"cokolwiek\"/>" | ||||
|  | ||||
| #: ../src/ui/theme.c:5041 | ||||
| #, c-format | ||||
| msgid "Failed to load theme \"%s\": %s\n" | ||||
| msgstr "Wczytanie motywu \"%s\" się nie powiodło: %s\n" | ||||
|  | ||||
| #: ../src/ui/theme.c:5177 ../src/ui/theme.c:5184 ../src/ui/theme.c:5191 | ||||
| #: ../src/ui/theme.c:5198 ../src/ui/theme.c:5205 | ||||
| #, c-format | ||||
| msgid "No <%s> set for theme \"%s\"" | ||||
| msgstr "Nie określono elementu <%s> dla motywu \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:5213 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "No frame style set for window type \"%s\" in theme \"%s\", add a <window " | ||||
| "type=\"%s\" style_set=\"whatever\"/> element" | ||||
| msgstr "" | ||||
| "Przy typie okna \"%s\" w motywie \"%s\" nie ustawiono stylu ramki. Należy " | ||||
| "dodać element <window type=\"%s\" style_set=\"cokolwiek\"/>" | ||||
|  | ||||
| #: ../src/ui/theme.c:5620 ../src/ui/theme.c:5682 ../src/ui/theme.c:5745 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "User-defined constants must begin with a capital letter; \"%s\" does not" | ||||
| msgstr "" | ||||
| "Stałe definiowane przez użytkownika powinny rozpoczynać się wielką literą, " | ||||
| "natomiast \"%s\" nie spełnia tego warunku" | ||||
|  | ||||
| #: ../src/ui/theme.c:5628 ../src/ui/theme.c:5690 ../src/ui/theme.c:5753 | ||||
| #, c-format | ||||
| msgid "Constant \"%s\" has already been defined" | ||||
| msgstr "Stała \"%s\" została już określona" | ||||
|  | ||||
| #. Translators: This means that an attribute which should have been found | ||||
| #. * on an XML element was not in fact found. | ||||
| #. | ||||
| #: ../src/ui/theme-parser.c:234 | ||||
| #, c-format | ||||
| msgid "No \"%s\" attribute on element <%s>" | ||||
| msgstr "Brak atrybutu \"%s\" w elemencie <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:263 ../src/ui/theme-parser.c:281 | ||||
| #, c-format | ||||
| msgid "Line %d character %d: %s" | ||||
| msgstr "Wiersz %d, znak %d: %s" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:481 | ||||
| #, c-format | ||||
| msgid "Attribute \"%s\" repeated twice on the same <%s> element" | ||||
| msgstr "Atrybut \"%s\" wystąpił dwukrotnie wewnątrz jednego elementu <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:505 ../src/ui/theme-parser.c:554 | ||||
| #, c-format | ||||
| msgid "Attribute \"%s\" is invalid on <%s> element in this context" | ||||
| msgstr "" | ||||
| "Atrybut \"%s\" jest nieprawidłowy wewnątrz elementu <%s> w tym kontekście" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:596 | ||||
| #, c-format | ||||
| msgid "Could not parse \"%s\" as an integer" | ||||
| msgstr "Nie można przetworzyć \"%s\" jako liczby całkowitej" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:605 ../src/ui/theme-parser.c:660 | ||||
| #, c-format | ||||
| msgid "Did not understand trailing characters \"%s\" in string \"%s\"" | ||||
| msgstr "Nie można rozpoznać końcowych znaków \"%s\" w napisie \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:615 | ||||
| #, c-format | ||||
| msgid "Integer %ld must be positive" | ||||
| msgstr "Liczba całkowita %ld musi być dodatnia" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:623 | ||||
| #, c-format | ||||
| msgid "Integer %ld is too large, current max is %d" | ||||
| msgstr "Liczba całkowita %ld jest za duża, obecne maksimum to %d" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:651 ../src/ui/theme-parser.c:767 | ||||
| #, c-format | ||||
| msgid "Could not parse \"%s\" as a floating point number" | ||||
| msgstr "Napis \"%s\" nie jest zapisem liczby zmiennoprzecinkowej" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:682 ../src/ui/theme-parser.c:710 | ||||
| #, c-format | ||||
| msgid "Boolean values must be \"true\" or \"false\" not \"%s\"" | ||||
| msgstr "Wartościami logicznymi są \"true\" i \"false\", a nie \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:737 | ||||
| #, c-format | ||||
| msgid "Angle must be between 0.0 and 360.0, was %g\n" | ||||
| msgstr "Wartość kąta musi się mieścić pomiędzy 0,0 i 360,0, odczytano %g\n" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:800 | ||||
| #, c-format | ||||
| msgid "Alpha must be between 0.0 (invisible) and 1.0 (fully opaque), was %g\n" | ||||
| msgstr "" | ||||
| "Wartość alfa musi się mieścić pomiędzy 0,0 (niewidoczne) i 1,0 (w pełni " | ||||
| "nieprzezroczyste), odczytano %g\n" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:865 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Invalid title scale \"%s\" (must be one of xx-small,x-small,small,medium," | ||||
| "large,x-large,xx-large)\n" | ||||
| msgstr "" | ||||
| "Nieprawidłowy rozmiar tytułu \"%s\" (musi on być jedną z wartości: xx-small, " | ||||
| "x-small, small, medium, large, x-large, xx-large)\n" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1021 ../src/ui/theme-parser.c:1084 | ||||
| #: ../src/ui/theme-parser.c:1118 ../src/ui/theme-parser.c:1221 | ||||
| #, c-format | ||||
| msgid "<%s> name \"%s\" used a second time" | ||||
| msgstr "<%s>: użyto nazwy \"%s\" po raz drugi" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1033 ../src/ui/theme-parser.c:1130 | ||||
| #: ../src/ui/theme-parser.c:1233 | ||||
| #, c-format | ||||
| msgid "<%s> parent \"%s\" has not been defined" | ||||
| msgstr "<%s>: nie określono elementu nadrzędnego o nazwie \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1143 | ||||
| #, c-format | ||||
| msgid "<%s> geometry \"%s\" has not been defined" | ||||
| msgstr "<%s>: nie określono geometrii o nazwie \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1156 | ||||
| #, c-format | ||||
| msgid "<%s> must specify either a geometry or a parent that has a geometry" | ||||
| msgstr "<%s> musi albo określać geometrię, albo element nadrzędny z geometrią" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1198 | ||||
| msgid "You must specify a background for an alpha value to be meaningful" | ||||
| msgstr "Aby wartość alfa miała sens, należy określić tło" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1266 | ||||
| #, c-format | ||||
| msgid "Unknown type \"%s\" on <%s> element" | ||||
| msgstr "Nieznany typ \"%s\" wewnątrz elementu <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1277 | ||||
| #, c-format | ||||
| msgid "Unknown style_set \"%s\" on <%s> element" | ||||
| msgstr "Nieznana wartość atrybutu \"style_set\" (%s) wewnątrz elementu <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1285 | ||||
| #, c-format | ||||
| msgid "Window type \"%s\" has already been assigned a style set" | ||||
| msgstr "Z typem okna \"%s\" powiązano już zbiór stylów" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1315 ../src/ui/theme-parser.c:1379 | ||||
| #: ../src/ui/theme-parser.c:1605 ../src/ui/theme-parser.c:2840 | ||||
| #: ../src/ui/theme-parser.c:2886 ../src/ui/theme-parser.c:3036 | ||||
| #: ../src/ui/theme-parser.c:3272 ../src/ui/theme-parser.c:3310 | ||||
| #: ../src/ui/theme-parser.c:3348 ../src/ui/theme-parser.c:3386 | ||||
| #, c-format | ||||
| msgid "Element <%s> is not allowed below <%s>" | ||||
| msgstr "Element <%s> nie jest dopuszczalny poniżej <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1429 ../src/ui/theme-parser.c:1443 | ||||
| #: ../src/ui/theme-parser.c:1488 | ||||
| msgid "" | ||||
| "Cannot specify both \"button_width\"/\"button_height\" and \"aspect_ratio\" " | ||||
| "for buttons" | ||||
| msgstr "" | ||||
| "Nie można jednocześnie określać dla przycisku jego szerokości i wysokości " | ||||
| "oraz współczynnika proporcji" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1452 | ||||
| #, c-format | ||||
| msgid "Distance \"%s\" is unknown" | ||||
| msgstr "Odległość \"%s\" jest nieznana" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1497 | ||||
| #, c-format | ||||
| msgid "Aspect ratio \"%s\" is unknown" | ||||
| msgstr "Współczynnik proporcji \"%s\" jest nieznany" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1559 | ||||
| #, c-format | ||||
| msgid "Border \"%s\" is unknown" | ||||
| msgstr "Krawędź \"%s\" jest nieznana" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1870 | ||||
| #, c-format | ||||
| msgid "No \"start_angle\" or \"from\" attribute on element <%s>" | ||||
| msgstr "Brak atrybutu \"start_angle\" wewnątrz elementu <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1877 | ||||
| #, c-format | ||||
| msgid "No \"extent_angle\" or \"to\" attribute on element <%s>" | ||||
| msgstr "Brak atrybutu \"extent_angle\" wewnątrz elementu <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2117 | ||||
| #, c-format | ||||
| msgid "Did not understand value \"%s\" for type of gradient" | ||||
| msgstr "Niezrozumiała wartość \"%s\" typu gradientu" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2195 ../src/ui/theme-parser.c:2570 | ||||
| #, c-format | ||||
| msgid "Did not understand fill type \"%s\" for <%s> element" | ||||
| msgstr "Niezrozumiały typ wypełnienia \"%s\" elementu <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2362 ../src/ui/theme-parser.c:2445 | ||||
| #: ../src/ui/theme-parser.c:2508 | ||||
| #, c-format | ||||
| msgid "Did not understand state \"%s\" for <%s> element" | ||||
| msgstr "Niezrozumiały stan \"%s\" (atrybut \"state\") elementu <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2372 ../src/ui/theme-parser.c:2455 | ||||
| #, c-format | ||||
| msgid "Did not understand shadow \"%s\" for <%s> element" | ||||
| msgstr "Niezrozumiały cień \"%s\" (atrybut \"shadow\") elementu <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2382 | ||||
| #, c-format | ||||
| msgid "Did not understand arrow \"%s\" for <%s> element" | ||||
| msgstr "Niezrozumiała strzałka \"%s\" (atrybut \"arrow\") elementu <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2696 ../src/ui/theme-parser.c:2792 | ||||
| #, c-format | ||||
| msgid "No <draw_ops> called \"%s\" has been defined" | ||||
| msgstr "Nie określono elementu <draw_ops> o nazwie \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2708 ../src/ui/theme-parser.c:2804 | ||||
| #, c-format | ||||
| msgid "Including draw_ops \"%s\" here would create a circular reference" | ||||
| msgstr "" | ||||
| "Włączenie tutaj elementu \"draw_ops\" o nazwie \"%s\" spowodowałoby " | ||||
| "zapętlone odwołanie" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2919 | ||||
| #, c-format | ||||
| msgid "Unknown position \"%s\" for frame piece" | ||||
| msgstr "Nieznane położenie \"%s\" elementu ramki" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2927 | ||||
| #, c-format | ||||
| msgid "Frame style already has a piece at position %s" | ||||
| msgstr "Styl ramki zawiera już element o położeniu %s" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2944 ../src/ui/theme-parser.c:3021 | ||||
| #, c-format | ||||
| msgid "No <draw_ops> with the name \"%s\" has been defined" | ||||
| msgstr "Nie określono elementu <draw_ops> o nazwie \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2974 | ||||
| #, c-format | ||||
| msgid "Unknown function \"%s\" for button" | ||||
| msgstr "Nieznana funkcja \"%s\" powiązana z przyciskiem" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2984 | ||||
| #, c-format | ||||
| msgid "Button function \"%s\" does not exist in this version (%d, need %d)" | ||||
| msgstr "Funkcja \"%s\" przycisku nie istnieje w tej wersji (%d, wymaga %d)" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2996 | ||||
| #, c-format | ||||
| msgid "Unknown state \"%s\" for button" | ||||
| msgstr "Nieznany stan \"%s\" powiązany z przyciskiem" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3004 | ||||
| #, c-format | ||||
| msgid "Frame style already has a button for function %s state %s" | ||||
| msgstr "" | ||||
| "Dla stylu ramki określono już przycisk, związany z funkcją %s i stanem %s" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3075 | ||||
| #, c-format | ||||
| msgid "\"%s\" is not a valid value for focus attribute" | ||||
| msgstr "\"%s\" nie jest prawidłową wartością atrybutu \"focus\"" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3084 | ||||
| #, c-format | ||||
| msgid "\"%s\" is not a valid value for state attribute" | ||||
| msgstr "\"%s\" nie jest prawidłową wartością atrybutu \"state\"" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3094 | ||||
| #, c-format | ||||
| msgid "A style called \"%s\" has not been defined" | ||||
| msgstr "Nie określono stylu o nazwie \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3115 ../src/ui/theme-parser.c:3138 | ||||
| #, c-format | ||||
| msgid "\"%s\" is not a valid value for resize attribute" | ||||
| msgstr "\"%s\" nie jest prawidłową wartością atrybutu \"resize\"" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3149 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Should not have \"resize\" attribute on <%s> element for maximized/shaded " | ||||
| "states" | ||||
| msgstr "" | ||||
| "Element <%s> nie powinien zawierać atrybutu \"resize\" przy stanie " | ||||
| "zmaksymalizowanym lub zwiniętym" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3163 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Should not have \"resize\" attribute on <%s> element for maximized states" | ||||
| msgstr "" | ||||
| "Element <%s> nie powinien zawierać atrybutu \"resize\" przy stanie " | ||||
| "zmaksymalizowanym" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3177 ../src/ui/theme-parser.c:3221 | ||||
| #, c-format | ||||
| msgid "Style has already been specified for state %s resize %s focus %s" | ||||
| msgstr "Określono już styl dla stanu %s, rozmiaru %s i uaktywnienia %s" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3188 ../src/ui/theme-parser.c:3199 | ||||
| #: ../src/ui/theme-parser.c:3210 ../src/ui/theme-parser.c:3232 | ||||
| #: ../src/ui/theme-parser.c:3243 ../src/ui/theme-parser.c:3254 | ||||
| #, c-format | ||||
| msgid "Style has already been specified for state %s focus %s" | ||||
| msgstr "Określono już styl dla stanu %s i uaktywnienia %s" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3293 | ||||
| msgid "" | ||||
| "Can't have a two draw_ops for a <piece> element (theme specified a draw_ops " | ||||
| "attribute and also a <draw_ops> element, or specified two elements)" | ||||
| msgstr "" | ||||
| "Element <piece> nie może zawierać dwóch \"draw_ops\" (motyw zawiera atrybut " | ||||
| "\"draw_ops\" i element <draw_ops> lub dwa elementy)" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3331 | ||||
| msgid "" | ||||
| "Can't have a two draw_ops for a <button> element (theme specified a draw_ops " | ||||
| "attribute and also a <draw_ops> element, or specified two elements)" | ||||
| msgstr "" | ||||
| "Element <button> nie może zawierać dwóch \"draw_ops\" (motyw zawiera atrybut " | ||||
| "\"draw_ops\" i element <draw_ops> lub dwa elementy)" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3369 | ||||
| msgid "" | ||||
| "Can't have a two draw_ops for a <menu_icon> element (theme specified a " | ||||
| "draw_ops attribute and also a <draw_ops> element, or specified two elements)" | ||||
| msgstr "" | ||||
| "Element <menu_icon> nie może zawierać dwóch \"draw_ops\" (motyw zawiera " | ||||
| "atrybut \"draw_ops\" i element <draw_ops> lub dwa elementy)" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3433 | ||||
| #, c-format | ||||
| msgid "Bad version specification '%s'" | ||||
| msgstr "Błędne określenie wersji \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3506 | ||||
| msgid "" | ||||
| "\"version\" attribute cannot be used in metacity-theme-1.xml or metacity-" | ||||
| "theme-2.xml" | ||||
| msgstr "" | ||||
| "Atrybut \"version\" nie może być używany w plikach metacity-theme-1.xml lub " | ||||
| "metacity-theme-2.xml" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3529 | ||||
| #, c-format | ||||
| msgid "Theme requires version %s but latest supported theme version is %d.%d" | ||||
| msgstr "" | ||||
| "Motyw wymaga wersji %s, ale najnowsza obsługiwana wersja motywów to %d.%d" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3561 | ||||
| #, c-format | ||||
| msgid "Outermost element in theme must be <metacity_theme> not <%s>" | ||||
| msgstr "Głównym elementem motywu musi być <metacity_theme>, nie <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3581 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Element <%s> is not allowed inside a name/author/date/description element" | ||||
| msgstr "" | ||||
| "Element <%s> nie jest dopuszczalny wewnątrz elementu name/author/date/" | ||||
| "description" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3586 | ||||
| #, c-format | ||||
| msgid "Element <%s> is not allowed inside a <constant> element" | ||||
| msgstr "Element <%s> nie jest dopuszczalny wewnątrz elementu <constant>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3598 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Element <%s> is not allowed inside a distance/border/aspect_ratio element" | ||||
| msgstr "" | ||||
| "Element <%s> nie jest dopuszczalny wewnątrz elementu distance/border/" | ||||
| "aspect_ratio" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3620 | ||||
| #, c-format | ||||
| msgid "Element <%s> is not allowed inside a draw operation element" | ||||
| msgstr "" | ||||
| "Element <%s> nie jest dopuszczalny wewnątrz elementu działania rysowania" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3630 ../src/ui/theme-parser.c:3660 | ||||
| #: ../src/ui/theme-parser.c:3665 ../src/ui/theme-parser.c:3670 | ||||
| #, c-format | ||||
| msgid "Element <%s> is not allowed inside a <%s> element" | ||||
| msgstr "Element <%s> nie jest dopuszczalny wewnątrz elementu <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3898 | ||||
| msgid "No draw_ops provided for frame piece" | ||||
| msgstr "Brak elementu \"draw_ops\" powiązanego z elementem ramki" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3913 | ||||
| msgid "No draw_ops provided for button" | ||||
| msgstr "Brak elementu \"draw_ops\" powiązanego z przyciskiem" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3967 | ||||
| #, c-format | ||||
| msgid "No text is allowed inside element <%s>" | ||||
| msgstr "Wewnątrz elementu <%s> nie jest dopuszczalny tekst" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:4025 ../src/ui/theme-parser.c:4037 | ||||
| #: ../src/ui/theme-parser.c:4049 ../src/ui/theme-parser.c:4061 | ||||
| #: ../src/ui/theme-parser.c:4073 | ||||
| #, c-format | ||||
| msgid "<%s> specified twice for this theme" | ||||
| msgstr "<%s> określono dwukrotnie dla tego motywu" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:4335 | ||||
| #, c-format | ||||
| msgid "Failed to find a valid file for theme %s\n" | ||||
| msgstr "Odnalezienie prawidłowego pliku dla motywu %s się nie powiodło\n" | ||||
|  | ||||
| #: ../src/x11/session.c:1815 | ||||
| msgid "" | ||||
| "These windows do not support "save current setup" and will have to " | ||||
| "be restarted manually next time you log in." | ||||
| msgstr "" | ||||
| "Te okna nie obsługują opcji zapisu aktualnego stanu (\"save current setup" | ||||
| "\"), więc przy następnym zalogowaniu będą musiały zostać uruchomione ręcznie." | ||||
| "Te okna nie obsługują opcji zapisu obecnego stanu („save current setup”), " | ||||
| "więc przy następnym zalogowaniu będą musiały zostać uruchomione ręcznie." | ||||
|  | ||||
| #: ../src/x11/window-props.c:515 | ||||
| #: ../src/x11/window-props.c:549 | ||||
| #, c-format | ||||
| msgid "%s (on %s)" | ||||
| msgstr "%s (na %s)" | ||||
|   | ||||
							
								
								
									
										1284
									
								
								po/pt_BR.po
									
									
									
									
									
								
							
							
						
						
									
										1284
									
								
								po/pt_BR.po
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										782
									
								
								po/sl.po
									
									
									
									
									
								
							
							
						
						
									
										782
									
								
								po/sl.po
									
									
									
									
									
								
							| @@ -4,15 +4,15 @@ | ||||
| # | ||||
| # Andraž Tori <andraz.tori1@guest.arnes.si>, 2000. | ||||
| # Matjaž Horvat <m@owca.info>, 2006. | ||||
| # Matej Urbančič <mateju@svn.gnome.org>, 2007-2014. | ||||
| # Matej Urbančič <mateju@svn.gnome.org>, 2007-2015. | ||||
| # | ||||
| msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: mutter master\n" | ||||
| "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" | ||||
| "product=mutter&keywords=I18N+L10N&component=general\n" | ||||
| "POT-Creation-Date: 2014-12-26 10:55+0000\n" | ||||
| "PO-Revision-Date: 2014-12-26 19:24+0100\n" | ||||
| "POT-Creation-Date: 2015-03-15 11:07+0000\n" | ||||
| "PO-Revision-Date: 2015-03-15 14:36+0100\n" | ||||
| "Last-Translator: Matej Urbančič <mateju@svn.gnome.org>\n" | ||||
| "Language-Team: Slovenian GNOME Translation Team <gnome-si@googlegroups.com>\n" | ||||
| "Language: sl_SI\n" | ||||
| @@ -435,22 +435,42 @@ msgstr "Preklopi na VT 6" | ||||
| msgid "Switch to VT 7" | ||||
| msgstr "Preklopi na VT 7" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:375 | ||||
| #: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:8 | ||||
| msgid "Switch to VT 8" | ||||
| msgstr "Preklopi na VT 8" | ||||
|  | ||||
| #: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:9 | ||||
| msgid "Switch to VT 9" | ||||
| msgstr "Preklopi na VT 9" | ||||
|  | ||||
| #: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:10 | ||||
| msgid "Switch to VT 10" | ||||
| msgstr "Preklopi na VT 10" | ||||
|  | ||||
| #: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:11 | ||||
| msgid "Switch to VT 11" | ||||
| msgstr "Preklopi na VT 11" | ||||
|  | ||||
| #: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:12 | ||||
| msgid "Switch to VT 12" | ||||
| msgstr "Preklopi na VT 12" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:364 | ||||
| msgid "Built-in display" | ||||
| msgstr "Vgrajen zaslon" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:400 | ||||
| #: ../src/backends/meta-monitor-manager.c:391 | ||||
| msgid "Unknown" | ||||
| msgstr "Neznano" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:402 | ||||
| #: ../src/backends/meta-monitor-manager.c:393 | ||||
| msgid "Unknown Display" | ||||
| msgstr "Neznan zaslon" | ||||
|  | ||||
| #. TRANSLATORS: this is a monitor vendor name, followed by a | ||||
| #. * size in inches, like 'Dell 15"' | ||||
| #. | ||||
| #: ../src/backends/meta-monitor-manager.c:410 | ||||
| #: ../src/backends/meta-monitor-manager.c:401 | ||||
| #, c-format | ||||
| msgid "%s %s" | ||||
| msgstr "%s %s" | ||||
| @@ -494,7 +514,7 @@ msgstr "_Počakaj" | ||||
| msgid "_Force Quit" | ||||
| msgstr "_Vsili konec" | ||||
|  | ||||
| #: ../src/core/display.c:550 | ||||
| #: ../src/core/display.c:562 | ||||
| #, c-format | ||||
| msgid "Failed to open X Window System display '%s'\n" | ||||
| msgstr "Ni mogoče odpreti zaslona '%s' okenskega sistema X\n" | ||||
| @@ -531,19 +551,6 @@ msgstr "Zaženi izbirnik wayland" | ||||
| msgid "Run as a full display server, rather than nested" | ||||
| msgstr "Zaženi kot polni strežnik zaslona in ne vstavljeno" | ||||
|  | ||||
| #: ../src/core/main.c:451 | ||||
| #, c-format | ||||
| msgid "Failed to scan themes directory: %s\n" | ||||
| msgstr "Ni mogoče preiskati mape tem: %s\n" | ||||
|  | ||||
| #: ../src/core/main.c:467 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Could not find a theme! Be sure %s exists and contains the usual themes.\n" | ||||
| msgstr "" | ||||
| "Ni mogoče najti teme! Prepričajte se, da %s obstaja in vsebuje običajni " | ||||
| "zapis teme.\n" | ||||
|  | ||||
| #: ../src/core/mutter.c:39 | ||||
| #, c-format | ||||
| msgid "" | ||||
| @@ -568,717 +575,30 @@ msgid "Mutter plugin to use" | ||||
| msgstr "Vstavek Mutter za uporabo" | ||||
|  | ||||
| # G:1 K:0 O:0 | ||||
| #: ../src/core/prefs.c:2064 | ||||
| #: ../src/core/prefs.c:2004 | ||||
| #, c-format | ||||
| msgid "Workspace %d" | ||||
| msgstr "Delovna površina %d" | ||||
|  | ||||
| #: ../src/core/screen.c:534 | ||||
| #: ../src/core/screen.c:525 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Display \"%s\" already has a window manager; try using the --replace option " | ||||
| "to replace the current window manager." | ||||
| msgstr "" | ||||
| "Zaslon \"%s\" že ima določen upravljalnik oken; poskušajte uporabiti možnost " | ||||
| "--replace za zamenjavo trenutnega upravljalnika zaslona." | ||||
|  | ||||
| #: ../src/core/screen.c:607 | ||||
| #, c-format | ||||
| msgid "Screen %d on display '%s' is invalid\n" | ||||
| msgstr "Zaslon %d na prikazu '%s' ni veljaven\n" | ||||
|  | ||||
| #: ../src/core/screen.c:550 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Screen %d on display \"%s\" already has a window manager; try using the --" | ||||
| "replace option to replace the current window manager.\n" | ||||
| msgstr "" | ||||
| "Zaslon %d na prikazu \"%s\" je že upravljan z upravljalnikom oken; " | ||||
| "poskušajte uporabiti možnost --replace za zamenjavo trenutnega.\n" | ||||
|  | ||||
| #: ../src/core/screen.c:643 | ||||
| #, c-format | ||||
| msgid "Screen %d on display \"%s\" already has a window manager\n" | ||||
| msgstr "Zaslon %d na prikazu \"%s\"  je že upravljan z upravljalnikom oken\n" | ||||
|  | ||||
| #: ../src/core/util.c:118 | ||||
| msgid "Mutter was compiled without support for verbose mode\n" | ||||
| msgstr "" | ||||
| "Program Mutter je kodno preveden brez podpore za podrobni način izpisovanja\n" | ||||
|  | ||||
| #. Translators: This represents the size of a window.  The first number is | ||||
| #. * the width of the window and the second is the height. | ||||
| #. | ||||
| #: ../src/ui/resizepopup.c:134 | ||||
| #, c-format | ||||
| msgid "%d x %d" | ||||
| msgstr "%d x %d" | ||||
|  | ||||
| #: ../src/ui/theme.c:233 | ||||
| msgid "top" | ||||
| msgstr "zgoraj" | ||||
|  | ||||
| # G:12 K:5 O:0 | ||||
| #: ../src/ui/theme.c:235 | ||||
| msgid "bottom" | ||||
| msgstr "spodaj" | ||||
|  | ||||
| # G:10 K:4 O:0 | ||||
| #: ../src/ui/theme.c:237 | ||||
| msgid "left" | ||||
| msgstr "levo" | ||||
|  | ||||
| # G:1 K:0 O:0 | ||||
| #: ../src/ui/theme.c:239 | ||||
| msgid "right" | ||||
| msgstr "desno" | ||||
|  | ||||
| # G:1 K:0 O:0 | ||||
| #: ../src/ui/theme.c:267 | ||||
| #, c-format | ||||
| msgid "frame geometry does not specify \"%s\" dimension" | ||||
| msgstr "geometrija okvirja ne navaja dimenzije \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:286 | ||||
| #, c-format | ||||
| msgid "frame geometry does not specify dimension \"%s\" for border \"%s\"" | ||||
| msgstr "geometrija okvirja ne navaja dimenzije \"%s\" za rob \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:323 | ||||
| #, c-format | ||||
| msgid "Button aspect ratio %g is not reasonable" | ||||
| msgstr "Vrednost razmerja gumba %g ni smiselna" | ||||
|  | ||||
| #: ../src/ui/theme.c:335 | ||||
| #, c-format | ||||
| msgid "Frame geometry does not specify size of buttons" | ||||
| msgstr "Geometrija okvirja ne navaja velikosti gumbov" | ||||
|  | ||||
| #: ../src/ui/theme.c:1061 | ||||
| #, c-format | ||||
| msgid "Gradients should have at least two colors" | ||||
| msgstr "Prelivi bi morali imeti vsaj dve barvi" | ||||
|  | ||||
| #: ../src/ui/theme.c:1211 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "GTK custom color specification must have color name and fallback in " | ||||
| "parentheses, e.g. gtk:custom(foo,bar); could not parse \"%s\"" | ||||
| msgstr "" | ||||
| "Navedba barve GTK mora biti opredeljena z imenom barve in v navednicah " | ||||
| "povrnjeno barvo , npr. gtk:izbirno(ime_barve,povrnjena_barva); ni mogoče " | ||||
| "razčleniti \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:1227 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-" | ||||
| "_ are valid" | ||||
| msgstr "" | ||||
| "Neveljaven znak '%c' v imenu barve gtk:izbirno; dovoljeni znaki so le A-Za-" | ||||
| "z0-9-_." | ||||
|  | ||||
| #: ../src/ui/theme.c:1241 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not " | ||||
| "fit the format" | ||||
| msgstr "" | ||||
| "Gtk:zapis po meri \"gtk:izbirno(ime_barve,povrnjena_barva)\", \"%s\" ne " | ||||
| "ustreza pravilni obliki." | ||||
|  | ||||
| #: ../src/ui/theme.c:1286 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "GTK color specification must have the state in brackets, e.g. gtk:fg[NORMAL] " | ||||
| "where NORMAL is the state; could not parse \"%s\"" | ||||
| msgstr "" | ||||
| "Navedba barve GTK mora vsebovati stanje v oglatih oklepajih, npr. gtk:" | ||||
| "fg[NORMAL], kjer je NORMAL stanje; ni mogoče razčleniti \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:1300 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "GTK color specification must have a close bracket after the state, e.g. gtk:" | ||||
| "fg[NORMAL] where NORMAL is the state; could not parse \"%s\"" | ||||
| msgstr "" | ||||
| "Navedbi barve GTK manjka oglati zaklepaj za stanjem, npr. gtk:fg[NORMAL], " | ||||
| "kjer je NORMAL stanje; ni mogoče razčleniti \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:1311 | ||||
| #, c-format | ||||
| msgid "Did not understand state \"%s\" in color specification" | ||||
| msgstr "Ni mogoče razumeti stanja \"%s\" v navedbi barve " | ||||
|  | ||||
| #: ../src/ui/theme.c:1324 | ||||
| #, c-format | ||||
| msgid "Did not understand color component \"%s\" in color specification" | ||||
| msgstr "Ni mogoče razumeti barvne komponente \"%s\" v navedbi barve" | ||||
|  | ||||
| #: ../src/ui/theme.c:1352 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Blend format is \"blend/bg_color/fg_color/alpha\", \"%s\" does not fit the " | ||||
| "format" | ||||
| msgstr "" | ||||
| "Oblika zapisa preliva je \"blend/bg_color/fg_color/alpha\", \"%s\" ne " | ||||
| "ustreza pravilni obliki" | ||||
|  | ||||
| #: ../src/ui/theme.c:1363 | ||||
| #, c-format | ||||
| msgid "Could not parse alpha value \"%s\" in blended color" | ||||
| msgstr "V prelivni barvi ni mogoče razčleniti vrednosti alfa \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:1373 | ||||
| #, c-format | ||||
| msgid "Alpha value \"%s\" in blended color is not between 0.0 and 1.0" | ||||
| msgstr "V prelivni barvi alfa vrednost \"%s\" ni med 0.0 in 1.0" | ||||
|  | ||||
| #: ../src/ui/theme.c:1419 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Shade format is \"shade/base_color/factor\", \"%s\" does not fit the format" | ||||
| msgstr "" | ||||
| "Oblika zapisa barve senčenja je \"shade/base_color/factor\", \"%s\" ne " | ||||
| "ustreza pravilni obliki." | ||||
|  | ||||
| #: ../src/ui/theme.c:1430 | ||||
| #, c-format | ||||
| msgid "Could not parse shade factor \"%s\" in shaded color" | ||||
| msgstr "Ni mogoče razčleniti vrednosti senčenja \"%s\" v senčeni barvi" | ||||
|  | ||||
| #: ../src/ui/theme.c:1440 | ||||
| #, c-format | ||||
| msgid "Shade factor \"%s\" in shaded color is negative" | ||||
| msgstr "V senčeni barvi je vrednost senčenja \"%s\" negativna" | ||||
|  | ||||
| #: ../src/ui/theme.c:1469 | ||||
| #, c-format | ||||
| msgid "Could not parse color \"%s\"" | ||||
| msgstr "Ni mogoče razčleniti barve \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:1778 | ||||
| #, c-format | ||||
| msgid "Coordinate expression contains character '%s' which is not allowed" | ||||
| msgstr "Izraz koordinat vsebuje znak '%s', ki pa ni dovoljen" | ||||
|  | ||||
| #: ../src/ui/theme.c:1805 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Coordinate expression contains floating point number '%s' which could not be " | ||||
| "parsed" | ||||
| msgstr "" | ||||
| "Izraz koordinat vsebuje številko s plavajočo vejico '%s', ki je ni mogoče " | ||||
| "razčleniti" | ||||
|  | ||||
| #: ../src/ui/theme.c:1819 | ||||
| #, c-format | ||||
| msgid "Coordinate expression contains integer '%s' which could not be parsed" | ||||
| msgstr "Izraz koordinat vsebuje celo število '%s', ki ga ni mogoče razčleniti" | ||||
|  | ||||
| #: ../src/ui/theme.c:1940 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Coordinate expression contained unknown operator at the start of this text: " | ||||
| "\"%s\"" | ||||
| msgstr "Izraz koordinat vsebuje neznan operator na začetku besedila: \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:1997 | ||||
| #, c-format | ||||
| msgid "Coordinate expression was empty or not understood" | ||||
| msgstr "Izraz koordinat je prazen ali pa ni v razumljivem zapisu" | ||||
|  | ||||
| #: ../src/ui/theme.c:2110 ../src/ui/theme.c:2120 ../src/ui/theme.c:2154 | ||||
| #, c-format | ||||
| msgid "Coordinate expression results in division by zero" | ||||
| msgstr "Izraz koordinat povzroči deljenje z vrednostjo nič" | ||||
|  | ||||
| #: ../src/ui/theme.c:2162 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Coordinate expression tries to use mod operator on a floating-point number" | ||||
| msgstr "" | ||||
| "Izraz koordinat poskuša uporabiti operator mod ali številko s plavajočo " | ||||
| "vejico" | ||||
|  | ||||
| #: ../src/ui/theme.c:2218 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Coordinate expression has an operator \"%s\" where an operand was expected" | ||||
| msgstr "Izraz koordinat vsebuje operator \"%s\", kjer je pričakovan operand" | ||||
|  | ||||
| #: ../src/ui/theme.c:2227 | ||||
| #, c-format | ||||
| msgid "Coordinate expression had an operand where an operator was expected" | ||||
| msgstr "Izraz koordinat vsebuje operand kjer je pričakovan operator" | ||||
|  | ||||
| #: ../src/ui/theme.c:2235 | ||||
| #, c-format | ||||
| msgid "Coordinate expression ended with an operator instead of an operand" | ||||
| msgstr "Izraz koordinat se konča z operatorjem namesto z operandom" | ||||
|  | ||||
| #: ../src/ui/theme.c:2245 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Coordinate expression has operator \"%c\" following operator \"%c\" with no " | ||||
| "operand in between" | ||||
| msgstr "" | ||||
| "Izraz koordinat vsebuje operator \"%c\", ki sledi operatorju \"%c\", brez " | ||||
| "vmesnega operanda" | ||||
|  | ||||
| #: ../src/ui/theme.c:2396 ../src/ui/theme.c:2441 | ||||
| #, c-format | ||||
| msgid "Coordinate expression had unknown variable or constant \"%s\"" | ||||
| msgstr "Izraz koordinat vsebuje neznano spremenljivko ali konstanto \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:2495 | ||||
| #, c-format | ||||
| msgid "Coordinate expression parser overflowed its buffer." | ||||
| msgstr "Razčlenjevalnik izrazov koordinat je preplavil medpomnilnik." | ||||
|  | ||||
| #: ../src/ui/theme.c:2524 | ||||
| #, c-format | ||||
| msgid "Coordinate expression had a close parenthesis with no open parenthesis" | ||||
| msgstr "Izraz koordinat vsebuje zaklepaj, ne pa tudi uklepaja" | ||||
|  | ||||
| #: ../src/ui/theme.c:2588 | ||||
| #, c-format | ||||
| msgid "Coordinate expression had an open parenthesis with no close parenthesis" | ||||
| msgstr "Izraz koordinat vsebuje uklepaj, vendar je brez zaklepaja" | ||||
|  | ||||
| #: ../src/ui/theme.c:2599 | ||||
| #, c-format | ||||
| msgid "Coordinate expression doesn't seem to have any operators or operands" | ||||
| msgstr "Videti je, da izraz koordinat ne vsebuje operatorjev ali operandov" | ||||
|  | ||||
| #: ../src/ui/theme.c:2812 ../src/ui/theme.c:2832 ../src/ui/theme.c:2852 | ||||
| #, c-format | ||||
| msgid "Theme contained an expression that resulted in an error: %s\n" | ||||
| msgstr "Tema vsebuje izraz, ki povzroča napako: %s\n" | ||||
|  | ||||
| #: ../src/ui/theme.c:4455 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/> must be " | ||||
| "specified for this frame style" | ||||
| msgstr "" | ||||
| "Za ta slog okvirja mora biti naveden <button function=\"%s\" state=\"%s\" " | ||||
| "draw_ops=\"karkoli\"/>" | ||||
|  | ||||
| #: ../src/ui/theme.c:4970 ../src/ui/theme.c:4995 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>" | ||||
| msgstr "" | ||||
| "Manjka <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"karkoli\"/>" | ||||
|  | ||||
| #: ../src/ui/theme.c:5041 | ||||
| #, c-format | ||||
| msgid "Failed to load theme \"%s\": %s\n" | ||||
| msgstr "Napaka med nalaganjem teme \"%s\": %s\n" | ||||
|  | ||||
| #: ../src/ui/theme.c:5177 ../src/ui/theme.c:5184 ../src/ui/theme.c:5191 | ||||
| #: ../src/ui/theme.c:5198 ../src/ui/theme.c:5205 | ||||
| #, c-format | ||||
| msgid "No <%s> set for theme \"%s\"" | ||||
| msgstr "Ni nastavljena vrednost <%s> za temo \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:5213 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "No frame style set for window type \"%s\" in theme \"%s\", add a <window " | ||||
| "type=\"%s\" style_set=\"whatever\"/> element" | ||||
| msgstr "" | ||||
| "Ni določenega sloga okvirja okna vrste \"%s\" v temi \"%s\". Dodajte predmet " | ||||
| "<window type=\"%s\" style_set=\"whatever\"/>" | ||||
|  | ||||
| #: ../src/ui/theme.c:5620 ../src/ui/theme.c:5682 ../src/ui/theme.c:5745 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "User-defined constants must begin with a capital letter; \"%s\" does not" | ||||
| msgstr "" | ||||
| "Uporabniško določene konstante se morajo začeti z veliko črko; vrednost \"%s" | ||||
| "\" se ne" | ||||
|  | ||||
| #: ../src/ui/theme.c:5628 ../src/ui/theme.c:5690 ../src/ui/theme.c:5753 | ||||
| #, c-format | ||||
| msgid "Constant \"%s\" has already been defined" | ||||
| msgstr "Konstanta \"%s\" je že določena" | ||||
|  | ||||
| #. Translators: This means that an attribute which should have been found | ||||
| #. * on an XML element was not in fact found. | ||||
| #. | ||||
| #: ../src/ui/theme-parser.c:234 | ||||
| #, c-format | ||||
| msgid "No \"%s\" attribute on element <%s>" | ||||
| msgstr "Ni atributa \"%s\" za predmet <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:263 ../src/ui/theme-parser.c:281 | ||||
| #, c-format | ||||
| msgid "Line %d character %d: %s" | ||||
| msgstr "Vrstica %d, znak %d: %s" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:481 | ||||
| #, c-format | ||||
| msgid "Attribute \"%s\" repeated twice on the same <%s> element" | ||||
| msgstr "Atribut \"%s\" je bil v enakem predmetu <%s> ponovljen dvakrat" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:505 ../src/ui/theme-parser.c:554 | ||||
| #, c-format | ||||
| msgid "Attribute \"%s\" is invalid on <%s> element in this context" | ||||
| msgstr "Atribut \"%s\" je na ta način v predmetu <%s> neveljaven" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:596 | ||||
| #, c-format | ||||
| msgid "Could not parse \"%s\" as an integer" | ||||
| msgstr "Ni mogoče razčleniti \"%s\" kot celoštevilčne vrednosti" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:605 ../src/ui/theme-parser.c:660 | ||||
| #, c-format | ||||
| msgid "Did not understand trailing characters \"%s\" in string \"%s\"" | ||||
| msgstr "Ni mogoče razumeti končnih znakov \"%s\" v nizu \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:615 | ||||
| #, c-format | ||||
| msgid "Integer %ld must be positive" | ||||
| msgstr "Celoštevilska vrednost %ld mora biti pozitivna" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:623 | ||||
| #, c-format | ||||
| msgid "Integer %ld is too large, current max is %d" | ||||
| msgstr "Celoštevilska vrednost %ld je prevelika; trenutna omejitev je %d" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:651 ../src/ui/theme-parser.c:767 | ||||
| #, c-format | ||||
| msgid "Could not parse \"%s\" as a floating point number" | ||||
| msgstr "Ni mogoče razčleniti \"%s\" kot števila s plavajočo vejico" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:682 ../src/ui/theme-parser.c:710 | ||||
| #, c-format | ||||
| msgid "Boolean values must be \"true\" or \"false\" not \"%s\"" | ||||
| msgstr "Logične vrednosti morajo biti \"prav\" ali \"napak\" in ne \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:737 | ||||
| #, c-format | ||||
| msgid "Angle must be between 0.0 and 360.0, was %g\n" | ||||
| msgstr "Kot mora biti med 0.0 in 360.0, določen pa je z vrednostjo %g\n" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:800 | ||||
| #, c-format | ||||
| msgid "Alpha must be between 0.0 (invisible) and 1.0 (fully opaque), was %g\n" | ||||
| msgstr "" | ||||
| "Alfa mora biti med 0.0 (nevidno) in 1.0 (popolnoma vidno), vrednost pa je " | ||||
| "določena na %g\n" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:865 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Invalid title scale \"%s\" (must be one of xx-small,x-small,small,medium," | ||||
| "large,x-large,xx-large)\n" | ||||
| msgstr "" | ||||
| "Neveljavna velikost naziva \"%s\" (mora biti eno od xx-small,x-small,small," | ||||
| "medium,large,x-large,xx-large)\n" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1021 ../src/ui/theme-parser.c:1084 | ||||
| #: ../src/ui/theme-parser.c:1118 ../src/ui/theme-parser.c:1221 | ||||
| #, c-format | ||||
| msgid "<%s> name \"%s\" used a second time" | ||||
| msgstr "ime <%s> \"%s\" je uporabljeno drugič" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1033 ../src/ui/theme-parser.c:1130 | ||||
| #: ../src/ui/theme-parser.c:1233 | ||||
| #, c-format | ||||
| msgid "<%s> parent \"%s\" has not been defined" | ||||
| msgstr "nadrejeni predmet <%s> \"%s\" ni naveden" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1143 | ||||
| #, c-format | ||||
| msgid "<%s> geometry \"%s\" has not been defined" | ||||
| msgstr "geometrija <%s> \"%s\" ni navedena" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1156 | ||||
| #, c-format | ||||
| msgid "<%s> must specify either a geometry or a parent that has a geometry" | ||||
| msgstr "" | ||||
| "<%s> mora imeti navedeno ali geometrijo ali nadrejeni predmet z določeno " | ||||
| "geometrijo" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1198 | ||||
| msgid "You must specify a background for an alpha value to be meaningful" | ||||
| msgstr "Določiti je treba ozadje, v kolikor naj ima alfa vrednost pomen." | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1266 | ||||
| #, c-format | ||||
| msgid "Unknown type \"%s\" on <%s> element" | ||||
| msgstr "Neznana vrsta \"%s\" v predmetu <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1277 | ||||
| #, c-format | ||||
| msgid "Unknown style_set \"%s\" on <%s> element" | ||||
| msgstr "Neznan style_set \"%s\" v predmetu <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1285 | ||||
| #, c-format | ||||
| msgid "Window type \"%s\" has already been assigned a style set" | ||||
| msgstr "Vrsti okna \"%s\" je slog že določen" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1315 ../src/ui/theme-parser.c:1379 | ||||
| #: ../src/ui/theme-parser.c:1605 ../src/ui/theme-parser.c:2840 | ||||
| #: ../src/ui/theme-parser.c:2886 ../src/ui/theme-parser.c:3036 | ||||
| #: ../src/ui/theme-parser.c:3272 ../src/ui/theme-parser.c:3310 | ||||
| #: ../src/ui/theme-parser.c:3348 ../src/ui/theme-parser.c:3386 | ||||
| #, c-format | ||||
| msgid "Element <%s> is not allowed below <%s>" | ||||
| msgstr "Predmet <%s> ni dovoljen pod <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1429 ../src/ui/theme-parser.c:1443 | ||||
| #: ../src/ui/theme-parser.c:1488 | ||||
| msgid "" | ||||
| "Cannot specify both \"button_width\"/\"button_height\" and \"aspect_ratio\" " | ||||
| "for buttons" | ||||
| msgstr "" | ||||
| "Ni mogoče navesti tako vrednosti \"button_width\"/\"button_height\", kot " | ||||
| "vrednosti razmerja\"aspect_ratio\" gumba" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1452 | ||||
| #, c-format | ||||
| msgid "Distance \"%s\" is unknown" | ||||
| msgstr "Razdalja \"%s\" ni znana" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1497 | ||||
| #, c-format | ||||
| msgid "Aspect ratio \"%s\" is unknown" | ||||
| msgstr "Razmerje \"%s\" ni znano" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1559 | ||||
| #, c-format | ||||
| msgid "Border \"%s\" is unknown" | ||||
| msgstr "Rob \"%s\" ni znane vrste" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1870 | ||||
| #, c-format | ||||
| msgid "No \"start_angle\" or \"from\" attribute on element <%s>" | ||||
| msgstr "Predmet <%s> nima določenega atributa \"start_angle\" ali \"from\"" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1877 | ||||
| #, c-format | ||||
| msgid "No \"extent_angle\" or \"to\" attribute on element <%s>" | ||||
| msgstr "Predmet <%s> nima določenega atributa \"extent_angle\" ali \"to\"" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2117 | ||||
| #, c-format | ||||
| msgid "Did not understand value \"%s\" for type of gradient" | ||||
| msgstr "Ni mogoče razumeti vrednosti za vrsto preliva \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2195 ../src/ui/theme-parser.c:2570 | ||||
| #, c-format | ||||
| msgid "Did not understand fill type \"%s\" for <%s> element" | ||||
| msgstr "Neprepoznana vrsta polnjenja \"%s\" za predmet <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2362 ../src/ui/theme-parser.c:2445 | ||||
| #: ../src/ui/theme-parser.c:2508 | ||||
| #, c-format | ||||
| msgid "Did not understand state \"%s\" for <%s> element" | ||||
| msgstr "Ni mogoče razumeti stanja \"%s\" za predmet <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2372 ../src/ui/theme-parser.c:2455 | ||||
| #, c-format | ||||
| msgid "Did not understand shadow \"%s\" for <%s> element" | ||||
| msgstr "Ni mogoče razumeti senčenja \"%s\" za predmet <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2382 | ||||
| #, c-format | ||||
| msgid "Did not understand arrow \"%s\" for <%s> element" | ||||
| msgstr "Ni mogoče razumeti puščice \"%s\" za predmet <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2696 ../src/ui/theme-parser.c:2792 | ||||
| #, c-format | ||||
| msgid "No <draw_ops> called \"%s\" has been defined" | ||||
| msgstr "<draw_ops> imenovan \"%s\" ni naveden" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2708 ../src/ui/theme-parser.c:2804 | ||||
| #, c-format | ||||
| msgid "Including draw_ops \"%s\" here would create a circular reference" | ||||
| msgstr "Vključevanje draw_ops \"%s\" na tem mestu ustvari krožno sklicevanje" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2919 | ||||
| #, c-format | ||||
| msgid "Unknown position \"%s\" for frame piece" | ||||
| msgstr "Neznan položaj \"%s\" za del okvirja" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2927 | ||||
| #, c-format | ||||
| msgid "Frame style already has a piece at position %s" | ||||
| msgstr "Slog okvirja že ima del na položaju %s" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2944 ../src/ui/theme-parser.c:3021 | ||||
| #, c-format | ||||
| msgid "No <draw_ops> with the name \"%s\" has been defined" | ||||
| msgstr "Za ime \"%s\" ni navedenega <draw_ops>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2974 | ||||
| #, c-format | ||||
| msgid "Unknown function \"%s\" for button" | ||||
| msgstr "Neznana funkcija \"%s\" za gumb" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2984 | ||||
| #, c-format | ||||
| msgid "Button function \"%s\" does not exist in this version (%d, need %d)" | ||||
| msgstr "Funkcija gumba \"%s\" ne obstaja v tej različici (%d, zahtevana %d)" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2996 | ||||
| #, c-format | ||||
| msgid "Unknown state \"%s\" for button" | ||||
| msgstr "Neznano stanje \"%s\" za gumb" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3004 | ||||
| #, c-format | ||||
| msgid "Frame style already has a button for function %s state %s" | ||||
| msgstr "Slog okvirja že ima gumb za funkcijo %s stanje %s" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3075 | ||||
| #, c-format | ||||
| msgid "\"%s\" is not a valid value for focus attribute" | ||||
| msgstr "\"%s\" ni veljavna vrednost za atribut \"focus\"" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3084 | ||||
| #, c-format | ||||
| msgid "\"%s\" is not a valid value for state attribute" | ||||
| msgstr "\"%s\" ni veljavna vrednost za atribut \"state\"" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3094 | ||||
| #, c-format | ||||
| msgid "A style called \"%s\" has not been defined" | ||||
| msgstr "Slog imenovan \"%s\" ni določen" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3115 ../src/ui/theme-parser.c:3138 | ||||
| #, c-format | ||||
| msgid "\"%s\" is not a valid value for resize attribute" | ||||
| msgstr "\"%s\" ni veljavna vrednost za atribut \"resize\"" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3149 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Should not have \"resize\" attribute on <%s> element for maximized/shaded " | ||||
| "states" | ||||
| msgstr "" | ||||
| "Predmetu <%s> ni mogoče določiti atributa \"resize\" za razpeta/senčena " | ||||
| "stanja" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3163 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Should not have \"resize\" attribute on <%s> element for maximized states" | ||||
| msgstr "Predmetu <%s> ni mogoče določiti atributa \"resize\" za razpeta stanja" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3177 ../src/ui/theme-parser.c:3221 | ||||
| #, c-format | ||||
| msgid "Style has already been specified for state %s resize %s focus %s" | ||||
| msgstr "Slog za stanje %s, spremenjeno velikost %s in žarišče %s je že naveden" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3188 ../src/ui/theme-parser.c:3199 | ||||
| #: ../src/ui/theme-parser.c:3210 ../src/ui/theme-parser.c:3232 | ||||
| #: ../src/ui/theme-parser.c:3243 ../src/ui/theme-parser.c:3254 | ||||
| #, c-format | ||||
| msgid "Style has already been specified for state %s focus %s" | ||||
| msgstr "Slog za stanje %s in žarišče %s je že naveden" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3293 | ||||
| msgid "" | ||||
| "Can't have a two draw_ops for a <piece> element (theme specified a draw_ops " | ||||
| "attribute and also a <draw_ops> element, or specified two elements)" | ||||
| msgstr "" | ||||
| "Za predmet <piece> ni mogoče imeti določenih dveh vrednosti draw_ops (tema " | ||||
| "je navedla atribut draw_ops in hkrati predmet <draw_ops> ali navedena dva " | ||||
| "predmeta)" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3331 | ||||
| msgid "" | ||||
| "Can't have a two draw_ops for a <button> element (theme specified a draw_ops " | ||||
| "attribute and also a <draw_ops> element, or specified two elements)" | ||||
| msgstr "" | ||||
| "Za predmet <button> ni mogoče imeti določenih dveh vrednosti draw_ops (tema " | ||||
| "ima naveden atribut draw_ops in hkrati element <draw_ops> ali pa ima " | ||||
| "navedena dva elementa)" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3369 | ||||
| msgid "" | ||||
| "Can't have a two draw_ops for a <menu_icon> element (theme specified a " | ||||
| "draw_ops attribute and also a <draw_ops> element, or specified two elements)" | ||||
| msgstr "" | ||||
| "Za element <menu_icon> ni mogoče imeti dveh draw_ops (tema ima naveden " | ||||
| "atribut draw_ops in hkrati predmet <draw_ops> ali pa ima navedena dva " | ||||
| "predmeta)" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3433 | ||||
| #, c-format | ||||
| msgid "Bad version specification '%s'" | ||||
| msgstr "Slabo določilo različice '%s'" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3506 | ||||
| msgid "" | ||||
| "\"version\" attribute cannot be used in metacity-theme-1.xml or metacity-" | ||||
| "theme-2.xml" | ||||
| msgstr "" | ||||
| "atributa \"version\" ni mogoče uporabiti v temi metacity-theme-1.xml oziroma " | ||||
| "metacity-theme-2.xml" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3529 | ||||
| #, c-format | ||||
| msgid "Theme requires version %s but latest supported theme version is %d.%d" | ||||
| msgstr "Tema zahteva različico %s, zadnja podprta različica teme pa je %d.%d" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3561 | ||||
| #, c-format | ||||
| msgid "Outermost element in theme must be <metacity_theme> not <%s>" | ||||
| msgstr "Najbolj zunanji predmet teme mora biti <metacity_theme> in ne <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3581 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Element <%s> is not allowed inside a name/author/date/description element" | ||||
| msgstr "" | ||||
| "Predmet <%s> ni dovoljen znotraj predmetov imena, avtorja, datuma ali opisa" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3586 | ||||
| #, c-format | ||||
| msgid "Element <%s> is not allowed inside a <constant> element" | ||||
| msgstr "Predmet <%s> ni dovoljen znotraj predmeta <constant>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3598 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Element <%s> is not allowed inside a distance/border/aspect_ratio element" | ||||
| msgstr "" | ||||
| "Predmet <%s> ni dovoljen znotraj predmetov razdalje/robov/razmerja velikosti" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3620 | ||||
| #, c-format | ||||
| msgid "Element <%s> is not allowed inside a draw operation element" | ||||
| msgstr "Predmet <%s> ni dovoljen znotraj predmeta izrisevanja" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3630 ../src/ui/theme-parser.c:3660 | ||||
| #: ../src/ui/theme-parser.c:3665 ../src/ui/theme-parser.c:3670 | ||||
| #, c-format | ||||
| msgid "Element <%s> is not allowed inside a <%s> element" | ||||
| msgstr "Predmet <%s> ni dovoljen znotraj predmeta <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3898 | ||||
| msgid "No draw_ops provided for frame piece" | ||||
| msgstr "Za del okvirja ni navedena vrednost draw_ops" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3913 | ||||
| msgid "No draw_ops provided for button" | ||||
| msgstr "Za gumb ni navedena vrednost draw_ops" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3967 | ||||
| #, c-format | ||||
| msgid "No text is allowed inside element <%s>" | ||||
| msgstr "Znotraj predmeta <%s> besedilo ni dovoljeno" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:4025 ../src/ui/theme-parser.c:4037 | ||||
| #: ../src/ui/theme-parser.c:4049 ../src/ui/theme-parser.c:4061 | ||||
| #: ../src/ui/theme-parser.c:4073 | ||||
| #, c-format | ||||
| msgid "<%s> specified twice for this theme" | ||||
| msgstr "Vrednost <%s> je za to temo navedena dvakrat" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:4335 | ||||
| #, c-format | ||||
| msgid "Failed to find a valid file for theme %s\n" | ||||
| msgstr "Ni mogoče najti veljavne datoteke za temo %s\n" | ||||
|  | ||||
| # G:2 K:6 O:0 | ||||
| #: ../src/x11/session.c:1815 | ||||
| msgid "" | ||||
| @@ -1288,16 +608,26 @@ msgstr "" | ||||
| "Ta okna ne podpirajo možnosti "shranjevanja trenutnih nastavitev", " | ||||
| "zato jih bo treba ob naslednji prijavi zagnati ročno." | ||||
|  | ||||
| #: ../src/x11/window-props.c:558 | ||||
| #: ../src/x11/window-props.c:549 | ||||
| #, c-format | ||||
| msgid "%s (on %s)" | ||||
| msgstr "%s (na %s)" | ||||
|  | ||||
| #~ msgid "background texture could not be created from file" | ||||
| #~ msgstr "teksture ozadja iz datoteke ni mogoče ustvariti" | ||||
| #~ msgid "Failed to scan themes directory: %s\n" | ||||
| #~ msgstr "Ni mogoče preiskati mape tem: %s\n" | ||||
|  | ||||
| #~ msgid "Unknown window information request: %d" | ||||
| #~ msgstr "Zahteva izpisa podrobnosti neznanega okna: %d" | ||||
| #~ msgid "" | ||||
| #~ "Could not find a theme! Be sure %s exists and contains the usual themes.\n" | ||||
| #~ msgstr "" | ||||
| #~ "Ni mogoče najti teme! Prepričajte se, da %s obstaja in vsebuje običajni " | ||||
| #~ "zapis teme.\n" | ||||
|  | ||||
| #~ msgid "Missing %s extension required for compositing" | ||||
| #~ msgstr "Manjka razširitev %s, ki je ključna za sestavljanje" | ||||
| #~ msgid "Screen %d on display \"%s\" already has a window manager\n" | ||||
| #~ msgstr "" | ||||
| #~ "Zaslon %d na prikazu \"%s\"  je že upravljan z upravljalnikom oken\n" | ||||
|  | ||||
| #~ msgid "%d x %d" | ||||
| #~ msgstr "%d x %d" | ||||
|  | ||||
| #~ msgid "top" | ||||
| #~ msgstr "zgoraj" | ||||
|   | ||||
							
								
								
									
										1252
									
								
								po/sr@latin.po
									
									
									
									
									
								
							
							
						
						
									
										1252
									
								
								po/sr@latin.po
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1190
									
								
								po/zh_TW.po
									
									
									
									
									
								
							
							
						
						
									
										1190
									
								
								po/zh_TW.po
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -9,6 +9,7 @@ dist_stacking_DATA =				\ | ||||
| 	tests/stacking/basic-wayland.metatest	\ | ||||
| 	tests/stacking/minimized.metatest   	\ | ||||
| 	tests/stacking/mixed-windows.metatest   \ | ||||
| 	tests/stacking/set-parent.metatest	\ | ||||
| 	tests/stacking/override-redirect.metatest | ||||
|  | ||||
| mutter-all.test: tests/mutter-all.test.in | ||||
| @@ -41,11 +42,6 @@ endif | ||||
| # Some random test programs for bits of the code | ||||
|  | ||||
| testboxes_SOURCES = core/testboxes.c | ||||
| testgradient_SOURCES = ui/testgradient.c | ||||
| testasyncgetprop_SOURCES = x11/testasyncgetprop.c | ||||
|  | ||||
| noinst_PROGRAMS+=testboxes testgradient testasyncgetprop | ||||
|  | ||||
| testboxes_LDADD = $(MUTTER_LIBS) libmutter.la | ||||
| testgradient_LDADD = $(MUTTER_LIBS) libmutter.la | ||||
| testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter.la | ||||
|  | ||||
| noinst_PROGRAMS += testboxes | ||||
|   | ||||
							
								
								
									
										164
									
								
								src/Makefile.am
									
									
									
									
									
								
							
							
						
						
									
										164
									
								
								src/Makefile.am
									
									
									
									
									
								
							| @@ -6,6 +6,7 @@ lib_LTLIBRARIES = libmutter.la | ||||
| SUBDIRS=compositor/plugins | ||||
|  | ||||
| EXTRA_DIST = | ||||
| NULL = | ||||
|  | ||||
| AM_CPPFLAGS = \ | ||||
| 	-DCLUTTER_ENABLE_COMPOSITOR_API					\ | ||||
| @@ -31,34 +32,44 @@ AM_CPPFLAGS = \ | ||||
| 	-DMUTTER_PKGLIBDIR=\"$(pkglibdir)\"				\ | ||||
| 	-DMUTTER_PLUGIN_DIR=\"$(MUTTER_PLUGIN_DIR)\"			\ | ||||
| 	-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\"			\ | ||||
| 	-DXWAYLAND_PATH=\"$(XWAYLAND_PATH)\" | ||||
| 	-DXWAYLAND_PATH=\"$(XWAYLAND_PATH)\"				\ | ||||
| 	$(NULL) | ||||
|  | ||||
| mutter_built_sources = \ | ||||
| 	$(dbus_idle_built_sources)		\ | ||||
| 	$(dbus_display_config_built_sources)	\ | ||||
| 	$(dbus_login1_built_sources)		\ | ||||
| 	mutter-enum-types.h 			\ | ||||
| 	mutter-enum-types.c | ||||
| 	meta/meta-enum-types.h			\ | ||||
| 	meta-enum-types.c			\ | ||||
| 	$(NULL) | ||||
|  | ||||
| if HAVE_WAYLAND | ||||
| mutter_built_sources += \ | ||||
| 	pointer-gestures-unstable-v1-protocol.c				\ | ||||
| 	pointer-gestures-unstable-v1-server-protocol.h			\ | ||||
| 	gtk-shell-protocol.c			\ | ||||
| 	gtk-shell-server-protocol.h		\ | ||||
| 	xdg-shell-protocol.c			\ | ||||
| 	xdg-shell-server-protocol.h | ||||
| 	xdg-shell-unstable-v5-protocol.c				\ | ||||
| 	xdg-shell-unstable-v5-server-protocol.h				\ | ||||
| 	relative-pointer-unstable-v1-protocol.c				\ | ||||
| 	relative-pointer-unstable-v1-server-protocol.h			\ | ||||
| 	pointer-constraints-unstable-v1-protocol.c			\ | ||||
| 	pointer-constraints-unstable-v1-server-protocol.h		\ | ||||
| 	$(NULL) | ||||
| endif | ||||
|  | ||||
| wayland_protocols = \ | ||||
| wayland_protocols =				\ | ||||
| 	wayland/protocol/gtk-shell.xml		\ | ||||
| 	wayland/protocol/xdg-shell.xml | ||||
| 	$(NULL) | ||||
|  | ||||
| libmutter_la_SOURCES =				\ | ||||
| 	backends/meta-backend.c			\ | ||||
| 	meta/meta-backend.h			\ | ||||
| 	backends/meta-backend-private.h		\ | ||||
| 	backends/meta-barrier.c			\ | ||||
| 	backends/meta-barrier-private.h		\ | ||||
| 	backends/meta-cursor.c			\ | ||||
| 	backends/meta-cursor.h			\ | ||||
| 	backends/meta-cursor-private.h		\ | ||||
| 	backends/meta-cursor-tracker.c		\ | ||||
| 	backends/meta-cursor-tracker-private.h	\ | ||||
| 	backends/meta-cursor-renderer.c		\ | ||||
| @@ -68,33 +79,45 @@ libmutter_la_SOURCES =				\ | ||||
| 	backends/meta-idle-monitor-private.h	\ | ||||
| 	backends/meta-idle-monitor-dbus.c	\ | ||||
| 	backends/meta-idle-monitor-dbus.h	\ | ||||
| 	backends/meta-input-settings.c		\ | ||||
| 	backends/meta-input-settings-private.h	\ | ||||
| 	backends/meta-monitor-config.c		\ | ||||
| 	backends/meta-monitor-config.h		\ | ||||
| 	backends/meta-monitor-manager.c		\ | ||||
| 	backends/meta-monitor-manager.h		\ | ||||
| 	meta/meta-monitor-manager.h		\ | ||||
| 	backends/meta-monitor-manager-private.h	\ | ||||
| 	backends/meta-monitor-manager-dummy.c	\ | ||||
| 	backends/meta-monitor-manager-dummy.h	\ | ||||
| 	backends/meta-pointer-constraint.c	\ | ||||
| 	backends/meta-pointer-constraint.h	\ | ||||
| 	backends/meta-stage.h			\ | ||||
| 	backends/meta-stage.c			\ | ||||
| 	backends/edid-parse.c			\ | ||||
| 	backends/edid.h				\ | ||||
| 	backends/x11/meta-backend-x11.c			\ | ||||
| 	backends/x11/meta-backend-x11.h			\ | ||||
| 	backends/x11/meta-barrier-x11.c			\ | ||||
| 	backends/x11/meta-barrier-x11.h			\ | ||||
| 	backends/x11/meta-cursor-renderer-x11.c		\ | ||||
| 	backends/x11/meta-cursor-renderer-x11.h		\ | ||||
| 	backends/x11/nested/meta-cursor-renderer-x11-nested.c		\ | ||||
| 	backends/x11/nested/meta-cursor-renderer-x11-nested.h		\ | ||||
| 	backends/x11/meta-idle-monitor-xsync.c		\ | ||||
| 	backends/x11/meta-idle-monitor-xsync.h		\ | ||||
| 	backends/x11/meta-input-settings-x11.c		\ | ||||
| 	backends/x11/meta-input-settings-x11.h		\ | ||||
| 	backends/x11/meta-monitor-manager-xrandr.c	\ | ||||
| 	backends/x11/meta-monitor-manager-xrandr.h	\ | ||||
| 	core/meta-accel-parse.c			\ | ||||
| 	core/meta-accel-parse.h			\ | ||||
| 	core/barrier.c				\ | ||||
| 	meta/barrier.h				\ | ||||
| 	core/bell.c				\ | ||||
| 	core/bell.h				\ | ||||
| 	core/boxes.c				\ | ||||
| 	core/boxes-private.h			\ | ||||
| 	meta/boxes.h				\ | ||||
| 	core/meta-border.c			\ | ||||
| 	core/meta-border.h			\ | ||||
| 	compositor/clutter-utils.c		\ | ||||
| 	compositor/clutter-utils.h		\ | ||||
| 	compositor/cogl-utils.c			\ | ||||
| @@ -119,13 +142,14 @@ libmutter_la_SOURCES =				\ | ||||
| 	compositor/meta-plugin-manager.c	\ | ||||
| 	compositor/meta-plugin-manager.h	\ | ||||
| 	compositor/meta-shadow-factory.c	\ | ||||
| 	compositor/meta-shadow-factory-private.h	\ | ||||
| 	compositor/meta-shaped-texture.c	\ | ||||
| 	compositor/meta-shaped-texture-private.h 	\ | ||||
| 	compositor/meta-surface-actor.c		\ | ||||
| 	compositor/meta-surface-actor.h		\ | ||||
| 	compositor/meta-surface-actor-x11.c	\ | ||||
| 	compositor/meta-surface-actor-x11.h	\ | ||||
| 	compositor/meta-sync-ring.c		\ | ||||
| 	compositor/meta-sync-ring.h		\ | ||||
| 	compositor/meta-texture-rectangle.c	\ | ||||
| 	compositor/meta-texture-rectangle.h	\ | ||||
| 	compositor/meta-texture-tower.c		\ | ||||
| @@ -135,7 +159,6 @@ libmutter_la_SOURCES =				\ | ||||
| 	compositor/meta-window-group.c		\ | ||||
| 	compositor/meta-window-group.h		\ | ||||
| 	compositor/meta-window-shape.c		\ | ||||
| 	compositor/meta-window-shape.h		\ | ||||
| 	compositor/region-utils.c		\ | ||||
| 	compositor/region-utils.h		\ | ||||
| 	meta/compositor.h			\ | ||||
| @@ -146,6 +169,7 @@ libmutter_la_SOURCES =				\ | ||||
| 	meta/meta-plugin.h			\ | ||||
| 	meta/meta-shadow-factory.h		\ | ||||
| 	meta/meta-window-actor.h		\ | ||||
| 	meta/meta-window-shape.h		\ | ||||
| 	meta/compositor-mutter.h 		\ | ||||
| 	core/constraints.c			\ | ||||
| 	core/constraints.h			\ | ||||
| @@ -162,8 +186,6 @@ libmutter_la_SOURCES =				\ | ||||
| 	meta/errors.h				\ | ||||
| 	core/frame.c				\ | ||||
| 	core/frame.h				\ | ||||
| 	ui/gradient.c				\ | ||||
| 	meta/gradient.h				\ | ||||
| 	core/meta-gesture-tracker.c		\ | ||||
| 	core/meta-gesture-tracker-private.h	\ | ||||
| 	core/keybindings.c			\ | ||||
| @@ -176,6 +198,8 @@ libmutter_la_SOURCES =				\ | ||||
| 	core/screen.c				\ | ||||
| 	core/screen-private.h			\ | ||||
| 	meta/screen.h				\ | ||||
| 	core/startup-notification.c		\ | ||||
| 	core/startup-notification-private.h	\ | ||||
| 	meta/types.h				\ | ||||
| 	core/restart.c				\ | ||||
| 	core/stack.c				\ | ||||
| @@ -195,17 +219,11 @@ libmutter_la_SOURCES =				\ | ||||
| 	ui/ui.h					\ | ||||
| 	ui/frames.c				\ | ||||
| 	ui/frames.h				\ | ||||
| 	ui/resizepopup.c			\ | ||||
| 	ui/resizepopup.h			\ | ||||
| 	ui/theme-parser.c			\ | ||||
| 	ui/theme.c				\ | ||||
| 	meta/theme.h				\ | ||||
| 	ui/theme-private.h			\ | ||||
| 	ui/ui.c					\ | ||||
| 	x11/iconcache.c				\ | ||||
| 	x11/iconcache.h				\ | ||||
| 	x11/async-getprop.c			\ | ||||
| 	x11/async-getprop.h			\ | ||||
| 	x11/atomnames.h				\ | ||||
| 	x11/events.c				\ | ||||
| 	x11/events.h				\ | ||||
| 	x11/group-private.h			\ | ||||
| @@ -213,6 +231,8 @@ libmutter_la_SOURCES =				\ | ||||
| 	x11/group-props.h			\ | ||||
| 	x11/group.c				\ | ||||
| 	meta/group.h				\ | ||||
| 	x11/iconcache.c				\ | ||||
| 	x11/iconcache.h				\ | ||||
| 	x11/session.c				\ | ||||
| 	x11/session.h				\ | ||||
| 	x11/window-props.c			\ | ||||
| @@ -222,7 +242,8 @@ libmutter_la_SOURCES =				\ | ||||
| 	x11/window-x11-private.h		\ | ||||
| 	x11/xprops.c				\ | ||||
| 	x11/xprops.h				\ | ||||
| 	x11/mutter-Xatomtype.h | ||||
| 	x11/mutter-Xatomtype.h			\ | ||||
| 	$(NULL) | ||||
|  | ||||
| if HAVE_WAYLAND | ||||
| libmutter_la_SOURCES +=				\ | ||||
| @@ -233,6 +254,8 @@ libmutter_la_SOURCES +=				\ | ||||
| 	wayland/meta-wayland-private.h		\ | ||||
| 	wayland/meta-xwayland.c			\ | ||||
| 	wayland/meta-xwayland.h			\ | ||||
| 	wayland/meta-xwayland-selection.c	\ | ||||
| 	wayland/meta-xwayland-selection-private.h	\ | ||||
| 	wayland/meta-xwayland-private.h		\ | ||||
| 	wayland/meta-wayland-buffer.c      	\ | ||||
| 	wayland/meta-wayland-buffer.h      	\ | ||||
| @@ -240,10 +263,25 @@ libmutter_la_SOURCES +=				\ | ||||
| 	wayland/meta-wayland-region.h      	\ | ||||
| 	wayland/meta-wayland-data-device.c      \ | ||||
| 	wayland/meta-wayland-data-device.h      \ | ||||
| 	wayland/meta-wayland-data-device-private.h	\ | ||||
| 	wayland/meta-wayland-pointer-gestures.c	\ | ||||
| 	wayland/meta-wayland-pointer-gestures.h	\ | ||||
| 	wayland/meta-wayland-pointer-gesture-swipe.c	\ | ||||
| 	wayland/meta-wayland-pointer-gesture-swipe.h	\ | ||||
| 	wayland/meta-wayland-pointer-gesture-pinch.c	\ | ||||
| 	wayland/meta-wayland-pointer-gesture-pinch.h	\ | ||||
| 	wayland/meta-wayland-keyboard.c		\ | ||||
| 	wayland/meta-wayland-keyboard.h		\ | ||||
| 	wayland/meta-wayland-pointer.c		\ | ||||
| 	wayland/meta-wayland-pointer.h		\ | ||||
| 	wayland/meta-wayland-pointer-constraints.c	\ | ||||
| 	wayland/meta-wayland-pointer-constraints.h	\ | ||||
| 	wayland/meta-pointer-lock-wayland.c		\ | ||||
| 	wayland/meta-pointer-lock-wayland.h		\ | ||||
| 	wayland/meta-pointer-confinement-wayland.c	\ | ||||
| 	wayland/meta-pointer-confinement-wayland.h	\ | ||||
| 	wayland/meta-wayland-popup.c		\ | ||||
| 	wayland/meta-wayland-popup.h		\ | ||||
| 	wayland/meta-wayland-seat.c		\ | ||||
| 	wayland/meta-wayland-seat.h		\ | ||||
| 	wayland/meta-wayland-touch.c		\ | ||||
| @@ -254,30 +292,36 @@ libmutter_la_SOURCES +=				\ | ||||
| 	wayland/meta-wayland-versions.h		\ | ||||
| 	wayland/meta-wayland-outputs.c		\ | ||||
| 	wayland/meta-wayland-outputs.h		\ | ||||
| 	wayland/window-wayland.c		\ | ||||
| 	wayland/window-wayland.h | ||||
| 	wayland/meta-window-wayland.c		\ | ||||
| 	wayland/meta-window-wayland.h		\ | ||||
| 	$(NULL) | ||||
| endif | ||||
|  | ||||
| if HAVE_NATIVE_BACKEND | ||||
| libmutter_la_SOURCES +=					\ | ||||
| 	backends/native/meta-backend-native.c		\ | ||||
| 	backends/native/meta-backend-native.h		\ | ||||
| 	backends/native/meta-backend-native-private.h	\ | ||||
| 	backends/native/meta-barrier-native.c		\ | ||||
| 	backends/native/meta-barrier-native.h		\ | ||||
| 	backends/native/meta-cursor-renderer-native.c	\ | ||||
| 	backends/native/meta-cursor-renderer-native.h	\ | ||||
| 	backends/native/meta-idle-monitor-native.c	\ | ||||
| 	backends/native/meta-idle-monitor-native.h	\ | ||||
| 	backends/native/meta-input-settings-native.c	\ | ||||
| 	backends/native/meta-input-settings-native.h	\ | ||||
| 	backends/native/meta-monitor-manager-kms.c	\ | ||||
| 	backends/native/meta-monitor-manager-kms.h	\ | ||||
| 	backends/native/meta-launcher.c			\ | ||||
| 	backends/native/meta-launcher.h			\ | ||||
| 	backends/native/dbus-utils.c			\ | ||||
| 	backends/native/dbus-utils.h | ||||
| 	backends/native/dbus-utils.h			\ | ||||
| 	$(NULL) | ||||
| endif | ||||
|  | ||||
| nodist_libmutter_la_SOURCES =			\ | ||||
| 	$(mutter_built_sources) | ||||
| nodist_libmutter_la_SOURCES = $(mutter_built_sources) | ||||
|  | ||||
| libmutter_la_LDFLAGS = -no-undefined | ||||
| libmutter_la_LDFLAGS = -no-undefined -export-symbols-regex "^(meta|ag)_.*" | ||||
| libmutter_la_LIBADD  = $(MUTTER_LIBS) $(MUTTER_NATIVE_BACKEND_LIBS) | ||||
|  | ||||
| # Headers installed for plugins; introspected information will | ||||
| @@ -290,7 +334,6 @@ libmutterinclude_headers =			\ | ||||
| 	meta/compositor.h			\ | ||||
| 	meta/display.h				\ | ||||
| 	meta/errors.h				\ | ||||
| 	meta/gradient.h				\ | ||||
| 	meta/group.h				\ | ||||
| 	meta/keybindings.h			\ | ||||
| 	meta/main.h				\ | ||||
| @@ -302,34 +345,33 @@ libmutterinclude_headers =			\ | ||||
| 	meta/meta-cursor-tracker.h		\ | ||||
| 	meta/meta-idle-monitor.h		\ | ||||
| 	meta/meta-plugin.h			\ | ||||
| 	meta/meta-monitor-manager.h		\ | ||||
| 	meta/meta-shaped-texture.h		\ | ||||
| 	meta/meta-shadow-factory.h		\ | ||||
| 	meta/meta-window-actor.h		\ | ||||
| 	meta/meta-window-shape.h		\ | ||||
| 	meta/prefs.h				\ | ||||
| 	meta/screen.h				\ | ||||
| 	meta/theme.h				\ | ||||
| 	meta/types.h				\ | ||||
| 	meta/util.h				\ | ||||
| 	meta/window.h				\ | ||||
| 	meta/workspace.h | ||||
| 	meta/workspace.h			\ | ||||
| 	$(NULL) | ||||
|  | ||||
| libmutterinclude_built_headers =		\ | ||||
| 	meta/meta-version.h | ||||
| 	meta/meta-version.h			\ | ||||
| 	meta/meta-enum-types.h			\ | ||||
| 	$(NULL) | ||||
|  | ||||
| libmutterinclude_base_headers =			\ | ||||
| 	$(libmutterinclude_headers)		\ | ||||
| 	$(libmutterinclude_built_headers) | ||||
|  | ||||
| # Excluded from scanning for introspection but installed | ||||
| # atomnames.h: macros cause problems for scanning process | ||||
| libmutterinclude_extra_headers =		\ | ||||
| 	meta/atomnames.h | ||||
|  | ||||
| libmutterincludedir = $(includedir)/mutter/meta | ||||
|  | ||||
| libmutterinclude_HEADERS =			\ | ||||
| 	$(libmutterinclude_headers)		\ | ||||
| 	$(libmutterinclude_extra_headers) | ||||
| 	$(libmutterinclude_headers) | ||||
|  | ||||
| nodist_libmutterinclude_HEADERS =		\ | ||||
| 	$(libmutterinclude_built_headers) | ||||
| @@ -372,7 +414,6 @@ Meta-$(api_version).gir: libmutter.la | ||||
| @META_GIR@_CFLAGS = $(AM_CPPFLAGS) | ||||
| @META_GIR@_LIBS = libmutter.la | ||||
| @META_GIR@_FILES =				\ | ||||
| 	mutter-enum-types.h			\ | ||||
| 	$(libmutterinclude_base_headers)	\ | ||||
| 	$(filter %.c,$(libmutter_la_SOURCES) $(nodist_libmutter_la_SOURCES)) | ||||
| @META_GIR@_SCANNERFLAGS = --warn-all --warn-error | ||||
| @@ -392,39 +433,40 @@ DISTCLEANFILES = 				\ | ||||
| pkgconfigdir = $(libdir)/pkgconfig | ||||
| pkgconfig_DATA = libmutter.pc | ||||
|  | ||||
| EXTRA_DIST +=				\ | ||||
| 	$(wayland_protocols)		\ | ||||
| 	libmutter.pc.in \ | ||||
| 	mutter-enum-types.h.in \ | ||||
| 	mutter-enum-types.c.in \ | ||||
| 	org.freedesktop.login1.xml	\ | ||||
| EXTRA_DIST +=					\ | ||||
| 	$(wayland_protocols)			\ | ||||
| 	libmutter.pc.in				\ | ||||
| 	meta-enum-types.h.in			\ | ||||
| 	meta-enum-types.c.in			\ | ||||
| 	org.freedesktop.login1.xml		\ | ||||
| 	org.gnome.Mutter.DisplayConfig.xml	\ | ||||
| 	org.gnome.Mutter.IdleMonitor.xml | ||||
| 	org.gnome.Mutter.IdleMonitor.xml	\ | ||||
| 	$(NULL) | ||||
|  | ||||
| BUILT_SOURCES =					\ | ||||
| 	$(mutter_built_sources)			\ | ||||
| 	$(libmutterinclude_built_headers) | ||||
|  | ||||
| MUTTER_STAMP_FILES = stamp-mutter-enum-types.h | ||||
| MUTTER_STAMP_FILES = stamp-meta-enum-types.h | ||||
| CLEANFILES += $(MUTTER_STAMP_FILES) | ||||
|  | ||||
| mutter-enum-types.h: stamp-mutter-enum-types.h Makefile | ||||
| meta/meta-enum-types.h: stamp-meta-enum-types.h Makefile | ||||
| 	@true | ||||
| stamp-mutter-enum-types.h: $(libmutterinclude_base_headers) mutter-enum-types.h.in | ||||
| stamp-meta-enum-types.h: $(libmutterinclude_headers) meta-enum-types.h.in | ||||
| 	$(AM_V_GEN) ( cd $(srcdir) && \ | ||||
| 	  $(GLIB_MKENUMS) \ | ||||
| 	    --template mutter-enum-types.h.in \ | ||||
| 	    --template meta-enum-types.h.in \ | ||||
| 	  $(libmutterinclude_base_headers) ) >> xgen-teth && \ | ||||
| 	(cmp -s xgen-teth mutter-enum-types.h || cp xgen-teth mutter-enum-types.h) && \ | ||||
| 	(cmp -s xgen-teth meta/meta-enum-types.h || cp xgen-teth meta/meta-enum-types.h) && \ | ||||
| 	rm -f xgen-teth && \ | ||||
| 	echo timestamp > $(@F) | ||||
|  | ||||
| mutter-enum-types.c: stamp-mutter-enum-types.h mutter-enum-types.c.in | ||||
| meta-enum-types.c: stamp-meta-enum-types.h meta-enum-types.c.in | ||||
| 	  $(AM_V_GEN) ( cd $(srcdir) && \ | ||||
| 	  $(GLIB_MKENUMS) \ | ||||
| 	    --template mutter-enum-types.c.in \ | ||||
| 	    --template meta-enum-types.c.in \ | ||||
| 	  $(libmutterinclude_base_headers) ) >> xgen-tetc && \ | ||||
| 	cp xgen-tetc mutter-enum-types.c && \ | ||||
| 	cp xgen-tetc meta-enum-types.c && \ | ||||
| 	rm -f xgen-tetc | ||||
|  | ||||
| dbus_display_config_built_sources = meta-dbus-display-config.c meta-dbus-display-config.h | ||||
| @@ -453,6 +495,20 @@ $(dbus_login1_built_sources) : Makefile.am org.freedesktop.login1.xml | ||||
| 		--generate-c-code meta-dbus-login1					\ | ||||
| 		$(srcdir)/org.freedesktop.login1.xml | ||||
|  | ||||
| .SECONDEXPANSION: | ||||
|  | ||||
| define protostability | ||||
| $(shell echo $1 | sed 's/.*\(\<unstable\>\|\<stable\>\).*/\1/') | ||||
| endef | ||||
|  | ||||
| define protoname | ||||
| $(shell echo $1 | sed 's/\([a-z\-]\+\)-[a-z]\+-v[0-9]\+/\1/') | ||||
| endef | ||||
|  | ||||
| %-protocol.c : $(WAYLAND_PROTOCOLS_DATADIR)/$$(call protostability,$$*)/$$(call protoname,$$*)/$$*.xml | ||||
| 	$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@ | ||||
| %-server-protocol.h : $(WAYLAND_PROTOCOLS_DATADIR)/$$(call protostability,$$*)/$$(call protoname,$$*)/$$*.xml | ||||
| 	$(AM_V_GEN)$(WAYLAND_SCANNER) server-header < $< > $@ | ||||
| %-protocol.c : $(srcdir)/wayland/protocol/%.xml | ||||
| 	$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@ | ||||
| %-server-protocol.h : $(srcdir)/wayland/protocol/%.xml | ||||
|   | ||||
| @@ -33,7 +33,8 @@ | ||||
| #include <meta/meta-backend.h> | ||||
| #include <meta/meta-idle-monitor.h> | ||||
| #include "meta-cursor-renderer.h" | ||||
| #include "meta-monitor-manager.h" | ||||
| #include "meta-monitor-manager-private.h" | ||||
| #include "backends/meta-pointer-constraint.h" | ||||
|  | ||||
| #define DEFAULT_XKB_RULES_FILE "evdev" | ||||
| #define DEFAULT_XKB_MODEL "pc105+inet" | ||||
| @@ -49,8 +50,10 @@ struct _MetaBackend | ||||
| { | ||||
|   GObject parent; | ||||
|  | ||||
|   MetaIdleMonitor *device_monitors[256]; | ||||
|   int device_id_max; | ||||
|   GHashTable *device_monitors; | ||||
|   gint current_device_id; | ||||
|  | ||||
|   MetaPointerConstraint *client_pointer_constraint; | ||||
| }; | ||||
|  | ||||
| struct _MetaBackendClass | ||||
| @@ -87,6 +90,13 @@ struct _MetaBackendClass | ||||
|  | ||||
|   void (* update_screen_size) (MetaBackend *backend, int width, int height); | ||||
|   void (* select_stage_events) (MetaBackend *backend); | ||||
|  | ||||
|   gboolean (* get_relative_motion_deltas) (MetaBackend *backend, | ||||
|                                            const        ClutterEvent *event, | ||||
|                                            double       *dx, | ||||
|                                            double       *dy, | ||||
|                                            double       *dx_unaccel, | ||||
|                                            double       *dy_unaccel); | ||||
| }; | ||||
|  | ||||
| MetaIdleMonitor * meta_backend_get_idle_monitor (MetaBackend *backend, | ||||
| @@ -107,4 +117,17 @@ void meta_backend_warp_pointer (MetaBackend *backend, | ||||
|  | ||||
| struct xkb_keymap * meta_backend_get_keymap (MetaBackend *backend); | ||||
|  | ||||
| void meta_backend_update_last_device (MetaBackend *backend, | ||||
|                                       int          device_id); | ||||
|  | ||||
| gboolean meta_backend_get_relative_motion_deltas (MetaBackend *backend, | ||||
|                                                   const        ClutterEvent *event, | ||||
|                                                   double       *dx, | ||||
|                                                   double       *dy, | ||||
|                                                   double       *dx_unaccel, | ||||
|                                                   double       *dy_unaccel); | ||||
|  | ||||
| void meta_backend_set_client_pointer_constraint (MetaBackend *backend, | ||||
|                                                  MetaPointerConstraint *constraint); | ||||
|  | ||||
| #endif /* META_BACKEND_PRIVATE_H */ | ||||
|   | ||||
| @@ -24,16 +24,24 @@ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include <stdlib.h> | ||||
|  | ||||
| #include <meta/meta-backend.h> | ||||
| #include "meta-backend-private.h" | ||||
| #include "meta-input-settings-private.h" | ||||
|  | ||||
| #include "backends/x11/meta-backend-x11.h" | ||||
| #include "meta-cursor-tracker-private.h" | ||||
| #include "meta-stage.h" | ||||
|  | ||||
| #ifdef HAVE_NATIVE_BACKEND | ||||
| #include "backends/native/meta-backend-native.h" | ||||
| #endif | ||||
|  | ||||
| #include "backends/meta-idle-monitor-private.h" | ||||
|  | ||||
| #include "backends/meta-monitor-manager-dummy.h" | ||||
|  | ||||
| static MetaBackend *_backend; | ||||
|  | ||||
| /** | ||||
| @@ -53,6 +61,7 @@ struct _MetaBackendPrivate | ||||
| { | ||||
|   MetaMonitorManager *monitor_manager; | ||||
|   MetaCursorRenderer *cursor_renderer; | ||||
|   MetaInputSettings *input_settings; | ||||
|  | ||||
|   ClutterActor *stage; | ||||
| }; | ||||
| @@ -65,15 +74,11 @@ meta_backend_finalize (GObject *object) | ||||
| { | ||||
|   MetaBackend *backend = META_BACKEND (object); | ||||
|   MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); | ||||
|   int i; | ||||
|  | ||||
|   g_clear_object (&priv->monitor_manager); | ||||
|   g_clear_object (&priv->input_settings); | ||||
|  | ||||
|   for (i = 0; i <= backend->device_id_max; i++) | ||||
|     { | ||||
|       if (backend->device_monitors[i]) | ||||
|         g_object_unref (backend->device_monitors[i]); | ||||
|     } | ||||
|   g_hash_table_destroy (backend->device_monitors); | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_backend_parent_class)->finalize (object); | ||||
| } | ||||
| @@ -89,12 +94,37 @@ meta_backend_sync_screen_size (MetaBackend *backend) | ||||
|   META_BACKEND_GET_CLASS (backend)->update_screen_size (backend, width, height); | ||||
| } | ||||
|  | ||||
| static void | ||||
| center_pointer (MetaBackend *backend) | ||||
| { | ||||
|   MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); | ||||
|   MetaMonitorInfo *monitors, *primary; | ||||
|   guint n_monitors; | ||||
|  | ||||
|   monitors = meta_monitor_manager_get_monitor_infos (priv->monitor_manager, &n_monitors); | ||||
|   primary = &monitors[meta_monitor_manager_get_primary_index (priv->monitor_manager)]; | ||||
|   meta_backend_warp_pointer (backend, | ||||
|                              primary->rect.x + primary->rect.width / 2, | ||||
|                              primary->rect.y + primary->rect.height / 2); | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_monitors_changed (MetaMonitorManager *monitors, | ||||
|                      gpointer user_data) | ||||
| { | ||||
|   MetaBackend *backend = META_BACKEND (user_data); | ||||
|   ClutterDeviceManager *manager = clutter_device_manager_get_default (); | ||||
|   ClutterInputDevice *device = clutter_device_manager_get_core_device (manager, CLUTTER_POINTER_DEVICE); | ||||
|   ClutterPoint point; | ||||
|  | ||||
|   meta_backend_sync_screen_size (backend); | ||||
|  | ||||
|   if (clutter_input_device_get_coords (device, NULL, &point)) | ||||
|     { | ||||
|       /* If we're outside all monitors, warp the pointer back inside */ | ||||
|       if (meta_monitor_manager_get_monitor_at_point (monitors, point.x, point.y) < 0) | ||||
|         center_pointer (backend); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static MetaIdleMonitor * | ||||
| @@ -108,27 +138,19 @@ static void | ||||
| create_device_monitor (MetaBackend *backend, | ||||
|                        int          device_id) | ||||
| { | ||||
|   g_assert (backend->device_monitors[device_id] == NULL); | ||||
|   MetaIdleMonitor *idle_monitor; | ||||
|  | ||||
|   backend->device_monitors[device_id] = meta_backend_create_idle_monitor (backend, device_id); | ||||
|   backend->device_id_max = MAX (backend->device_id_max, device_id); | ||||
|   g_assert (g_hash_table_lookup (backend->device_monitors, &device_id) == NULL); | ||||
|  | ||||
|   idle_monitor = meta_backend_create_idle_monitor (backend, device_id); | ||||
|   g_hash_table_insert (backend->device_monitors, &idle_monitor->device_id, idle_monitor); | ||||
| } | ||||
|  | ||||
| static void | ||||
| destroy_device_monitor (MetaBackend *backend, | ||||
|                         int          device_id) | ||||
| { | ||||
|   g_clear_object (&backend->device_monitors[device_id]); | ||||
|  | ||||
|   if (device_id == backend->device_id_max) | ||||
|     { | ||||
|       /* Reset the max device ID */ | ||||
|       int i, new_max = 0; | ||||
|       for (i = 0; i < backend->device_id_max; i++) | ||||
|         if (backend->device_monitors[i] != NULL) | ||||
|           new_max = i; | ||||
|       backend->device_id_max = new_max; | ||||
|     } | ||||
|   g_hash_table_remove (backend->device_monitors, &device_id); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -142,6 +164,55 @@ on_device_added (ClutterDeviceManager *device_manager, | ||||
|   create_device_monitor (backend, device_id); | ||||
| } | ||||
|  | ||||
| static inline gboolean | ||||
| device_is_slave_touchscreen (ClutterInputDevice *device) | ||||
| { | ||||
|   return (clutter_input_device_get_device_mode (device) != CLUTTER_INPUT_MODE_MASTER && | ||||
|           clutter_input_device_get_device_type (device) == CLUTTER_TOUCHSCREEN_DEVICE); | ||||
| } | ||||
|  | ||||
| static inline gboolean | ||||
| check_has_pointing_device (ClutterDeviceManager *manager) | ||||
| { | ||||
|   const GSList *devices; | ||||
|  | ||||
|   devices = clutter_device_manager_peek_devices (manager); | ||||
|  | ||||
|   for (; devices; devices = devices->next) | ||||
|     { | ||||
|       ClutterInputDevice *device = devices->data; | ||||
|  | ||||
|       if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_MASTER) | ||||
|         continue; | ||||
|       if (clutter_input_device_get_device_type (device) == CLUTTER_TOUCHSCREEN_DEVICE || | ||||
|           clutter_input_device_get_device_type (device) == CLUTTER_KEYBOARD_DEVICE) | ||||
|         continue; | ||||
|  | ||||
|       return TRUE; | ||||
|     } | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static inline gboolean | ||||
| check_has_slave_touchscreen (ClutterDeviceManager *manager) | ||||
| { | ||||
|   const GSList *devices; | ||||
|  | ||||
|   devices = clutter_device_manager_peek_devices (manager); | ||||
|  | ||||
|   for (; devices; devices = devices->next) | ||||
|     { | ||||
|       ClutterInputDevice *device = devices->data; | ||||
|  | ||||
|       if (clutter_input_device_get_device_mode (device) != CLUTTER_INPUT_MODE_MASTER && | ||||
|           clutter_input_device_get_device_type (device) == CLUTTER_TOUCHSCREEN_DEVICE) | ||||
|         return TRUE; | ||||
|     } | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_device_removed (ClutterDeviceManager *device_manager, | ||||
|                    ClutterInputDevice   *device, | ||||
| @@ -151,6 +222,41 @@ on_device_removed (ClutterDeviceManager *device_manager, | ||||
|   int device_id = clutter_input_device_get_device_id (device); | ||||
|  | ||||
|   destroy_device_monitor (backend, device_id); | ||||
|  | ||||
|   /* If the device the user last interacted goes away, check again pointer | ||||
|    * visibility. | ||||
|    */ | ||||
|   if (backend->current_device_id == device_id) | ||||
|     { | ||||
|       MetaCursorTracker *cursor_tracker = meta_cursor_tracker_get_for_screen (NULL); | ||||
|       gboolean has_touchscreen, has_pointing_device; | ||||
|       ClutterInputDeviceType device_type; | ||||
|  | ||||
|       device_type = clutter_input_device_get_device_type (device); | ||||
|       has_touchscreen = check_has_slave_touchscreen (device_manager); | ||||
|  | ||||
|       if (device_type == CLUTTER_TOUCHSCREEN_DEVICE && has_touchscreen) | ||||
|         { | ||||
|           /* There's more touchscreens left, keep the pointer hidden */ | ||||
|           meta_cursor_tracker_set_pointer_visible (cursor_tracker, FALSE); | ||||
|         } | ||||
|       else if (device_type != CLUTTER_KEYBOARD_DEVICE) | ||||
|         { | ||||
|           has_pointing_device = check_has_pointing_device (device_manager); | ||||
|           meta_cursor_tracker_set_pointer_visible (cursor_tracker, | ||||
|                                                    has_pointing_device && | ||||
|                                                    !has_touchscreen); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static MetaMonitorManager * | ||||
| create_monitor_manager (MetaBackend *backend) | ||||
| { | ||||
|   if (g_getenv ("META_DUMMY_MONITORS")) | ||||
|     return g_object_new (META_TYPE_MONITOR_MANAGER_DUMMY, NULL); | ||||
|  | ||||
|   return META_BACKEND_GET_CLASS (backend)->create_monitor_manager (backend); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -162,7 +268,7 @@ meta_backend_real_post_init (MetaBackend *backend) | ||||
|   clutter_actor_realize (priv->stage); | ||||
|   META_BACKEND_GET_CLASS (backend)->select_stage_events (backend); | ||||
|  | ||||
|   priv->monitor_manager = META_BACKEND_GET_CLASS (backend)->create_monitor_manager (backend); | ||||
|   priv->monitor_manager = create_monitor_manager (backend); | ||||
|  | ||||
|   g_signal_connect (priv->monitor_manager, "monitors-changed", | ||||
|                     G_CALLBACK (on_monitors_changed), backend); | ||||
| @@ -170,8 +276,13 @@ meta_backend_real_post_init (MetaBackend *backend) | ||||
|  | ||||
|   priv->cursor_renderer = META_BACKEND_GET_CLASS (backend)->create_cursor_renderer (backend); | ||||
|  | ||||
|   backend->device_monitors = g_hash_table_new_full (g_int_hash, g_int_equal, | ||||
|                                                     NULL, (GDestroyNotify) g_object_unref); | ||||
|  | ||||
|   { | ||||
|     MetaCursorTracker *cursor_tracker; | ||||
|     ClutterDeviceManager *manager; | ||||
|     gboolean has_touchscreen = FALSE; | ||||
|     GSList *devices, *l; | ||||
|  | ||||
|     /* Create the core device monitor. */ | ||||
| @@ -189,10 +300,18 @@ meta_backend_real_post_init (MetaBackend *backend) | ||||
|       { | ||||
|         ClutterInputDevice *device = l->data; | ||||
|         on_device_added (manager, device, backend); | ||||
|         has_touchscreen |= device_is_slave_touchscreen (device); | ||||
|       } | ||||
|  | ||||
|     cursor_tracker = meta_cursor_tracker_get_for_screen (NULL); | ||||
|     meta_cursor_tracker_set_pointer_visible (cursor_tracker, !has_touchscreen); | ||||
|  | ||||
|     g_slist_free (devices); | ||||
|   } | ||||
|  | ||||
|   priv->input_settings = meta_input_settings_create (); | ||||
|  | ||||
|   center_pointer (backend); | ||||
| } | ||||
|  | ||||
| static MetaCursorRenderer * | ||||
| @@ -234,6 +353,17 @@ meta_backend_real_select_stage_events (MetaBackend *backend) | ||||
|   /* Do nothing */ | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_backend_real_get_relative_motion_deltas (MetaBackend *backend, | ||||
|                                              const         ClutterEvent *event, | ||||
|                                              double        *dx, | ||||
|                                              double        *dy, | ||||
|                                              double        *dx_unaccel, | ||||
|                                              double        *dy_unaccel) | ||||
| { | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_backend_class_init (MetaBackendClass *klass) | ||||
| { | ||||
| @@ -247,6 +377,7 @@ meta_backend_class_init (MetaBackendClass *klass) | ||||
|   klass->ungrab_device = meta_backend_real_ungrab_device; | ||||
|   klass->update_screen_size = meta_backend_real_update_screen_size; | ||||
|   klass->select_stage_events = meta_backend_real_select_stage_events; | ||||
|   klass->get_relative_motion_deltas = meta_backend_real_get_relative_motion_deltas; | ||||
|  | ||||
|   g_signal_new ("keymap-changed", | ||||
|                 G_TYPE_FROM_CLASS (object_class), | ||||
| @@ -260,6 +391,12 @@ meta_backend_class_init (MetaBackendClass *klass) | ||||
|                 0, | ||||
|                 NULL, NULL, NULL, | ||||
|                 G_TYPE_NONE, 1, G_TYPE_UINT); | ||||
|   g_signal_new ("last-device-changed", | ||||
|                 G_TYPE_FROM_CLASS (object_class), | ||||
|                 G_SIGNAL_RUN_LAST, | ||||
|                 0, | ||||
|                 NULL, NULL, NULL, | ||||
|                 G_TYPE_NONE, 1, G_TYPE_INT); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -281,9 +418,7 @@ MetaIdleMonitor * | ||||
| meta_backend_get_idle_monitor (MetaBackend *backend, | ||||
|                                int          device_id) | ||||
| { | ||||
|   g_return_val_if_fail (device_id >= 0 && device_id < 256, NULL); | ||||
|  | ||||
|   return backend->device_monitors[device_id]; | ||||
|   return g_hash_table_lookup (backend->device_monitors, &device_id); | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -382,6 +517,71 @@ meta_backend_get_stage (MetaBackend *backend) | ||||
|   return priv->stage; | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_backend_update_last_device (MetaBackend *backend, | ||||
|                                  int          device_id) | ||||
| { | ||||
|   ClutterInputDeviceType device_type; | ||||
|   MetaCursorTracker *cursor_tracker; | ||||
|   ClutterDeviceManager *manager; | ||||
|   ClutterInputDevice *device; | ||||
|  | ||||
|   if (backend->current_device_id == device_id) | ||||
|     return; | ||||
|  | ||||
|   manager = clutter_device_manager_get_default (); | ||||
|   device = clutter_device_manager_get_device (manager, device_id); | ||||
|  | ||||
|   if (!device || | ||||
|       clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_MASTER) | ||||
|     return; | ||||
|  | ||||
|   device_type = clutter_input_device_get_device_type (device); | ||||
|  | ||||
|   cursor_tracker = meta_cursor_tracker_get_for_screen (NULL); | ||||
|   backend->current_device_id = device_id; | ||||
|   g_signal_emit_by_name (backend, "last-device-changed", device_id); | ||||
|  | ||||
|   if (device_type == CLUTTER_KEYBOARD_DEVICE) | ||||
|     return; | ||||
|  | ||||
|   switch (device_type) | ||||
|     { | ||||
|     case CLUTTER_TOUCHSCREEN_DEVICE: | ||||
|       meta_cursor_tracker_set_pointer_visible (cursor_tracker, FALSE); | ||||
|       break; | ||||
|     default: | ||||
|       meta_cursor_tracker_set_pointer_visible (cursor_tracker, TRUE); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_backend_get_relative_motion_deltas (MetaBackend *backend, | ||||
|                                          const        ClutterEvent *event, | ||||
|                                          double       *dx, | ||||
|                                          double       *dy, | ||||
|                                          double       *dx_unaccel, | ||||
|                                          double       *dy_unaccel) | ||||
| { | ||||
|   MetaBackendClass *klass = META_BACKEND_GET_CLASS (backend); | ||||
|   return klass->get_relative_motion_deltas (backend, | ||||
|                                             event, | ||||
|                                             dx, dy, | ||||
|                                             dx_unaccel, dy_unaccel); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_backend_set_client_pointer_constraint (MetaBackend           *backend, | ||||
|                                             MetaPointerConstraint *constraint) | ||||
| { | ||||
|   g_assert (!constraint || (constraint && !backend->client_pointer_constraint)); | ||||
|  | ||||
|   g_clear_object (&backend->client_pointer_constraint); | ||||
|   if (constraint) | ||||
|     backend->client_pointer_constraint = g_object_ref (constraint); | ||||
| } | ||||
|  | ||||
| static GType | ||||
| get_backend_type (void) | ||||
| { | ||||
| @@ -466,7 +666,10 @@ meta_clutter_init (void) | ||||
|   meta_create_backend (); | ||||
|  | ||||
|   if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS) | ||||
|     g_error ("Unable to initialize Clutter.\n"); | ||||
|     { | ||||
|       g_warning ("Unable to initialize Clutter.\n"); | ||||
|       exit (1); | ||||
|     } | ||||
|  | ||||
|   /* | ||||
|    * XXX: We cannot handle high dpi scaling yet, so fix the scale to 1 | ||||
|   | ||||
							
								
								
									
										76
									
								
								src/backends/meta-barrier-private.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								src/backends/meta-barrier-private.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,76 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2014-2015 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Jasper St. Pierre <jstpierre@mecheye.net> | ||||
|  *     Jonas Ådahl <jadahl@gmail.com> | ||||
|  */ | ||||
|  | ||||
| #ifndef META_BARRIER_PRIVATE_H | ||||
| #define META_BARRIER_PRIVATE_H | ||||
|  | ||||
| #include "core/meta-border.h" | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define META_TYPE_BARRIER_IMPL            (meta_barrier_impl_get_type ()) | ||||
| #define META_BARRIER_IMPL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BARRIER_IMPL, MetaBarrierImpl)) | ||||
| #define META_BARRIER_IMPL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_BARRIER_IMPL, MetaBarrierImplClass)) | ||||
| #define META_IS_BARRIER_IMPL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_BARRIER_IMPL)) | ||||
| #define META_IS_BARRIER_IMPL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_BARRIER_IMPL)) | ||||
| #define META_BARRIER_IMPL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_BARRIER_IMPL, MetaBarrierImplClass)) | ||||
|  | ||||
| typedef struct _MetaBarrierImpl        MetaBarrierImpl; | ||||
| typedef struct _MetaBarrierImplClass   MetaBarrierImplClass; | ||||
|  | ||||
| struct _MetaBarrierImpl | ||||
| { | ||||
|   GObject parent; | ||||
| }; | ||||
|  | ||||
| struct _MetaBarrierImplClass | ||||
| { | ||||
|   GObjectClass parent_class; | ||||
|  | ||||
|   gboolean (*is_active) (MetaBarrierImpl *barrier); | ||||
|   void (*release) (MetaBarrierImpl  *barrier, | ||||
|                    MetaBarrierEvent *event); | ||||
|   void (*destroy) (MetaBarrierImpl *barrier); | ||||
| }; | ||||
|  | ||||
| GType meta_barrier_impl_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| void _meta_barrier_emit_hit_signal (MetaBarrier      *barrier, | ||||
|                                     MetaBarrierEvent *event); | ||||
| void _meta_barrier_emit_left_signal (MetaBarrier      *barrier, | ||||
|                                      MetaBarrierEvent *event); | ||||
|  | ||||
| void meta_barrier_event_unref (MetaBarrierEvent *event); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| struct _MetaBarrierPrivate | ||||
| { | ||||
|   MetaDisplay *display; | ||||
|   MetaBorder border; | ||||
|   MetaBarrierImpl *impl; | ||||
| }; | ||||
|  | ||||
| #endif /* META_BARRIER_PRIVATE_H */ | ||||
| @@ -10,15 +10,16 @@ | ||||
| 
 | ||||
| #include <glib-object.h> | ||||
| 
 | ||||
| #include <X11/extensions/XInput2.h> | ||||
| #include <X11/extensions/Xfixes.h> | ||||
| #include <meta/util.h> | ||||
| #include <meta/barrier.h> | ||||
| #include "display-private.h" | ||||
| #include "mutter-enum-types.h" | ||||
| #include "core.h" | ||||
| #include "backends/native/meta-backend-native.h" | ||||
| #include "backends/native/meta-barrier-native.h" | ||||
| #include "backends/x11/meta-backend-x11.h" | ||||
| #include "backends/x11/meta-barrier-x11.h" | ||||
| #include <meta/meta-enum-types.h> | ||||
| 
 | ||||
| G_DEFINE_TYPE (MetaBarrier, meta_barrier, G_TYPE_OBJECT) | ||||
| G_DEFINE_TYPE (MetaBarrierImpl, meta_barrier_impl, G_TYPE_OBJECT) | ||||
| 
 | ||||
| enum { | ||||
|   PROP_0, | ||||
| @@ -45,21 +46,6 @@ enum { | ||||
| 
 | ||||
| static guint obj_signals[LAST_SIGNAL]; | ||||
| 
 | ||||
| struct _MetaBarrierPrivate | ||||
| { | ||||
|   MetaDisplay *display; | ||||
| 
 | ||||
|   int x1; | ||||
|   int y1; | ||||
|   int x2; | ||||
|   int y2; | ||||
| 
 | ||||
|   MetaBarrierDirection directions; | ||||
| 
 | ||||
|   PointerBarrier xbarrier; | ||||
| }; | ||||
| 
 | ||||
| static void meta_barrier_event_unref (MetaBarrierEvent *event); | ||||
| 
 | ||||
| static void | ||||
| meta_barrier_get_property (GObject    *object, | ||||
| @@ -75,19 +61,20 @@ meta_barrier_get_property (GObject    *object, | ||||
|       g_value_set_object (value, priv->display); | ||||
|       break; | ||||
|     case PROP_X1: | ||||
|       g_value_set_int (value, priv->x1); | ||||
|       g_value_set_int (value, priv->border.line.a.x); | ||||
|       break; | ||||
|     case PROP_Y1: | ||||
|       g_value_set_int (value, priv->y1); | ||||
|       g_value_set_int (value, priv->border.line.a.y); | ||||
|       break; | ||||
|     case PROP_X2: | ||||
|       g_value_set_int (value, priv->x2); | ||||
|       g_value_set_int (value, priv->border.line.b.x); | ||||
|       break; | ||||
|     case PROP_Y2: | ||||
|       g_value_set_int (value, priv->y2); | ||||
|       g_value_set_int (value, priv->border.line.b.y); | ||||
|       break; | ||||
|     case PROP_DIRECTIONS: | ||||
|       g_value_set_flags (value, priv->directions); | ||||
|       g_value_set_flags (value, | ||||
|                          meta_border_get_allows_directions (&priv->border)); | ||||
|       break; | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
| @@ -109,19 +96,20 @@ meta_barrier_set_property (GObject      *object, | ||||
|       priv->display = g_value_get_object (value); | ||||
|       break; | ||||
|     case PROP_X1: | ||||
|       priv->x1 = g_value_get_int (value); | ||||
|       priv->border.line.a.x = g_value_get_int (value); | ||||
|       break; | ||||
|     case PROP_Y1: | ||||
|       priv->y1 = g_value_get_int (value); | ||||
|       priv->border.line.a.y = g_value_get_int (value); | ||||
|       break; | ||||
|     case PROP_X2: | ||||
|       priv->x2 = g_value_get_int (value); | ||||
|       priv->border.line.b.x = g_value_get_int (value); | ||||
|       break; | ||||
|     case PROP_Y2: | ||||
|       priv->y2 = g_value_get_int (value); | ||||
|       priv->border.line.b.y = g_value_get_int (value); | ||||
|       break; | ||||
|     case PROP_DIRECTIONS: | ||||
|       priv->directions = g_value_get_flags (value); | ||||
|       meta_border_set_allows_directions (&priv->border, | ||||
|                                          g_value_get_flags (value)); | ||||
|       break; | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
| @@ -133,13 +121,11 @@ static void | ||||
| meta_barrier_dispose (GObject *object) | ||||
| { | ||||
|   MetaBarrier *barrier = META_BARRIER (object); | ||||
|   MetaBarrierPrivate *priv = barrier->priv; | ||||
| 
 | ||||
|   if (meta_barrier_is_active (barrier)) | ||||
|     { | ||||
|       meta_bug ("MetaBarrier wrapper %p for X barrier %ld was destroyed" | ||||
|                 " while the X barrier is still active.", | ||||
|                 barrier, priv->xbarrier); | ||||
|       meta_bug ("MetaBarrier %p was destroyed while it was still active.", | ||||
|                 barrier); | ||||
|     } | ||||
| 
 | ||||
|   G_OBJECT_CLASS (meta_barrier_parent_class)->dispose (object); | ||||
| @@ -148,7 +134,12 @@ meta_barrier_dispose (GObject *object) | ||||
| gboolean | ||||
| meta_barrier_is_active (MetaBarrier *barrier) | ||||
| { | ||||
|   return barrier->priv->xbarrier != 0; | ||||
|   MetaBarrierImpl *impl = barrier->priv->impl; | ||||
| 
 | ||||
|   if (impl) | ||||
|     return META_BARRIER_IMPL_GET_CLASS (impl)->is_active (impl); | ||||
|   else | ||||
|     return FALSE; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
| @@ -165,15 +156,10 @@ void | ||||
| meta_barrier_release (MetaBarrier      *barrier, | ||||
|                       MetaBarrierEvent *event) | ||||
| { | ||||
| #ifdef HAVE_XI23 | ||||
|   MetaBarrierPrivate *priv = barrier->priv; | ||||
|   if (META_DISPLAY_HAS_XINPUT_23 (priv->display)) | ||||
|     { | ||||
|       XIBarrierReleasePointer (priv->display->xdisplay, | ||||
|                                META_VIRTUAL_CORE_POINTER_ID, | ||||
|                                priv->xbarrier, event->event_id); | ||||
|     } | ||||
| #endif /* HAVE_XI23 */ | ||||
|   MetaBarrierImpl *impl = barrier->priv->impl; | ||||
| 
 | ||||
|   if (impl) | ||||
|     META_BARRIER_IMPL_GET_CLASS (impl)->release (impl, event); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| @@ -181,31 +167,27 @@ meta_barrier_constructed (GObject *object) | ||||
| { | ||||
|   MetaBarrier *barrier = META_BARRIER (object); | ||||
|   MetaBarrierPrivate *priv = barrier->priv; | ||||
|   Display *dpy; | ||||
|   Window root; | ||||
| 
 | ||||
|   g_return_if_fail (priv->x1 == priv->x2 || priv->y1 == priv->y2); | ||||
|   g_return_if_fail (priv->border.line.a.x == priv->border.line.b.x || | ||||
|                     priv->border.line.a.y == priv->border.line.b.y); | ||||
| 
 | ||||
|   if (priv->display == NULL) | ||||
|     { | ||||
|       g_warning ("A display must be provided when constructing a barrier."); | ||||
|       return; | ||||
|     } | ||||
| #if defined(HAVE_NATIVE_BACKEND) | ||||
|   if (META_IS_BACKEND_NATIVE (meta_get_backend ())) | ||||
|     priv->impl = meta_barrier_impl_native_new (barrier); | ||||
| #endif | ||||
| #if defined(HAVE_XI23) | ||||
|   if (META_IS_BACKEND_X11 (meta_get_backend ()) && | ||||
|       !meta_is_wayland_compositor ()) | ||||
|     priv->impl = meta_barrier_impl_x11_new (barrier); | ||||
| #endif | ||||
| 
 | ||||
|   dpy = priv->display->xdisplay; | ||||
|   root = DefaultRootWindow (dpy); | ||||
|   if (priv->impl == NULL) | ||||
|     g_warning ("Created a non-working barrier"); | ||||
| 
 | ||||
|   priv->xbarrier = XFixesCreatePointerBarrier (dpy, root, | ||||
|                                                priv->x1, priv->y1, | ||||
|                                                priv->x2, priv->y2, | ||||
|                                                priv->directions, 0, NULL); | ||||
| 
 | ||||
|   /* Take a ref that we'll release when the XID dies inside destroy(),
 | ||||
|    * so that the object stays alive and doesn't get GC'd. */ | ||||
|   /* Take a ref that we'll release in destroy() so that the object stays
 | ||||
|    * alive while active. */ | ||||
|   g_object_ref (barrier); | ||||
| 
 | ||||
|   g_hash_table_insert (priv->display->xids, &priv->xbarrier, barrier); | ||||
| 
 | ||||
|   G_OBJECT_CLASS (meta_barrier_parent_class)->constructed (object); | ||||
| } | ||||
| 
 | ||||
| @@ -306,20 +288,10 @@ meta_barrier_class_init (MetaBarrierClass *klass) | ||||
| void | ||||
| meta_barrier_destroy (MetaBarrier *barrier) | ||||
| { | ||||
|   MetaBarrierPrivate *priv = barrier->priv; | ||||
|   Display *dpy; | ||||
|   MetaBarrierImpl *impl = barrier->priv->impl; | ||||
| 
 | ||||
|   if (priv->display == NULL) | ||||
|     return; | ||||
| 
 | ||||
|   dpy = priv->display->xdisplay; | ||||
| 
 | ||||
|   if (!meta_barrier_is_active (barrier)) | ||||
|     return; | ||||
| 
 | ||||
|   XFixesDestroyPointerBarrier (dpy, priv->xbarrier); | ||||
|   g_hash_table_remove (priv->display->xids, &priv->xbarrier); | ||||
|   priv->xbarrier = 0; | ||||
|   if (impl) | ||||
|     return META_BARRIER_IMPL_GET_CLASS (impl)->destroy (impl); | ||||
| 
 | ||||
|   g_object_unref (barrier); | ||||
| } | ||||
| @@ -330,71 +302,32 @@ meta_barrier_init (MetaBarrier *barrier) | ||||
|   barrier->priv = G_TYPE_INSTANCE_GET_PRIVATE (barrier, META_TYPE_BARRIER, MetaBarrierPrivate); | ||||
| } | ||||
| 
 | ||||
| #ifdef HAVE_XI23 | ||||
| void | ||||
| _meta_barrier_emit_hit_signal (MetaBarrier      *barrier, | ||||
|                                MetaBarrierEvent *event) | ||||
| { | ||||
|   g_signal_emit (barrier, obj_signals[HIT], 0, event); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| _meta_barrier_emit_left_signal (MetaBarrier      *barrier, | ||||
|                                 MetaBarrierEvent *event) | ||||
| { | ||||
|   g_signal_emit (barrier, obj_signals[LEFT], 0, event); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| meta_barrier_fire_event (MetaBarrier    *barrier, | ||||
|                          XIBarrierEvent *xevent) | ||||
| meta_barrier_impl_class_init (MetaBarrierImplClass *klass) | ||||
| { | ||||
|   MetaBarrierEvent *event = g_slice_new0 (MetaBarrierEvent); | ||||
| 
 | ||||
|   event->ref_count = 1; | ||||
|   event->event_id = xevent->eventid; | ||||
|   event->time = xevent->time; | ||||
|   event->dt = xevent->dtime; | ||||
| 
 | ||||
|   event->x = xevent->root_x; | ||||
|   event->y = xevent->root_y; | ||||
|   event->dx = xevent->dx; | ||||
|   event->dy = xevent->dy; | ||||
| 
 | ||||
|   event->released = (xevent->flags & XIBarrierPointerReleased) != 0; | ||||
|   event->grabbed = (xevent->flags & XIBarrierDeviceIsGrabbed) != 0; | ||||
| 
 | ||||
|   switch (xevent->evtype) | ||||
|     { | ||||
|     case XI_BarrierHit: | ||||
|       g_signal_emit (barrier, obj_signals[HIT], 0, event); | ||||
|       break; | ||||
|     case XI_BarrierLeave: | ||||
|       g_signal_emit (barrier, obj_signals[LEFT], 0, event); | ||||
|       break; | ||||
|     default: | ||||
|       g_assert_not_reached (); | ||||
|     } | ||||
| 
 | ||||
|   meta_barrier_event_unref (event); | ||||
|   klass->is_active = NULL; | ||||
|   klass->release = NULL; | ||||
|   klass->destroy = NULL; | ||||
| } | ||||
| 
 | ||||
| gboolean | ||||
| meta_display_process_barrier_event (MetaDisplay *display, | ||||
|                                     XIEvent     *event) | ||||
| static void | ||||
| meta_barrier_impl_init (MetaBarrierImpl *impl) | ||||
| { | ||||
|   MetaBarrier *barrier; | ||||
|   XIBarrierEvent *xev; | ||||
| 
 | ||||
|   if (event == NULL) | ||||
|     return FALSE; | ||||
| 
 | ||||
|   switch (event->evtype) | ||||
|     { | ||||
|     case XI_BarrierHit: | ||||
|     case XI_BarrierLeave: | ||||
|       break; | ||||
|     default: | ||||
|       return FALSE; | ||||
|     } | ||||
| 
 | ||||
|   xev = (XIBarrierEvent *) event; | ||||
|   barrier = g_hash_table_lookup (display->xids, &xev->barrier); | ||||
|   if (barrier != NULL) | ||||
|     { | ||||
|       meta_barrier_fire_event (barrier, xev); | ||||
|       return TRUE; | ||||
|     } | ||||
| 
 | ||||
|   return FALSE; | ||||
| } | ||||
| #endif /* HAVE_XI23 */ | ||||
| 
 | ||||
| static MetaBarrierEvent * | ||||
| meta_barrier_event_ref (MetaBarrierEvent *event) | ||||
| @@ -406,7 +339,7 @@ meta_barrier_event_ref (MetaBarrierEvent *event) | ||||
|   return event; | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| void | ||||
| meta_barrier_event_unref (MetaBarrierEvent *event) | ||||
| { | ||||
|   g_return_if_fail (event != NULL); | ||||
| @@ -1,56 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright 2013 Red Hat, Inc. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * Author: Giovanni Campagna <gcampagn@redhat.com> | ||||
|  */ | ||||
|  | ||||
| #ifndef META_CURSOR_PRIVATE_H | ||||
| #define META_CURSOR_PRIVATE_H | ||||
|  | ||||
| #include "meta-cursor.h" | ||||
|  | ||||
| #include <cogl/cogl.h> | ||||
| #include <gbm.h> | ||||
|  | ||||
| typedef struct { | ||||
|   CoglTexture2D *texture; | ||||
|   int hot_x, hot_y; | ||||
|  | ||||
| #ifdef HAVE_NATIVE_BACKEND | ||||
|   struct gbm_bo *bo; | ||||
| #endif | ||||
| } MetaCursorImage; | ||||
|  | ||||
| struct _MetaCursorReference { | ||||
|   int ref_count; | ||||
|  | ||||
|   MetaCursor cursor; | ||||
|   MetaCursorImage image; | ||||
| }; | ||||
|  | ||||
| CoglTexture *meta_cursor_reference_get_cogl_texture (MetaCursorReference *cursor, | ||||
|                                                      int                 *hot_x, | ||||
|                                                      int                 *hot_y); | ||||
|  | ||||
| #ifdef HAVE_NATIVE_BACKEND | ||||
| struct gbm_bo *meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor, | ||||
|                                                  int                 *hot_x, | ||||
|                                                  int                 *hot_y); | ||||
| #endif | ||||
|  | ||||
| #endif /* META_CURSOR_PRIVATE_H */ | ||||
| @@ -25,9 +25,10 @@ | ||||
| #include "config.h" | ||||
|  | ||||
| #include "meta-cursor-renderer.h" | ||||
| #include "meta-cursor-private.h" | ||||
|  | ||||
| #include <meta/meta-backend.h> | ||||
| #include <backends/meta-backend-private.h> | ||||
| #include <backends/meta-monitor-manager-private.h> | ||||
| #include <meta/util.h> | ||||
|  | ||||
| #include <cogl/cogl.h> | ||||
| @@ -38,9 +39,8 @@ | ||||
| struct _MetaCursorRendererPrivate | ||||
| { | ||||
|   int current_x, current_y; | ||||
|   MetaRectangle current_rect; | ||||
|  | ||||
|   MetaCursorReference *displayed_cursor; | ||||
|   MetaCursorSprite *displayed_cursor; | ||||
|   gboolean handled_by_backend; | ||||
| }; | ||||
| typedef struct _MetaCursorRendererPrivate MetaCursorRendererPrivate; | ||||
| @@ -48,27 +48,33 @@ typedef struct _MetaCursorRendererPrivate MetaCursorRendererPrivate; | ||||
| G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRenderer, meta_cursor_renderer, G_TYPE_OBJECT); | ||||
|  | ||||
| static void | ||||
| queue_redraw (MetaCursorRenderer *renderer) | ||||
| queue_redraw (MetaCursorRenderer *renderer, | ||||
|               MetaCursorSprite   *cursor_sprite) | ||||
| { | ||||
|   MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); | ||||
|   MetaBackend *backend = meta_get_backend (); | ||||
|   ClutterActor *stage = meta_backend_get_stage (backend); | ||||
|   CoglTexture *texture; | ||||
|   MetaRectangle rect = { 0 }; | ||||
|  | ||||
|   if (cursor_sprite) | ||||
|     rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite); | ||||
|  | ||||
|   /* During early initialization, we can have no stage */ | ||||
|   if (!stage) | ||||
|     return; | ||||
|  | ||||
|   if (priv->displayed_cursor && !priv->handled_by_backend) | ||||
|     texture = meta_cursor_reference_get_cogl_texture (priv->displayed_cursor, NULL, NULL); | ||||
|   if (cursor_sprite && !priv->handled_by_backend) | ||||
|     texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite); | ||||
|   else | ||||
|     texture = NULL; | ||||
|  | ||||
|   meta_stage_set_cursor (META_STAGE (stage), texture, &priv->current_rect); | ||||
|   meta_stage_set_cursor (META_STAGE (stage), texture, &rect); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_cursor_renderer_real_update_cursor (MetaCursorRenderer *renderer) | ||||
| meta_cursor_renderer_real_update_cursor (MetaCursorRenderer *renderer, | ||||
|                                          MetaCursorSprite   *cursor_sprite) | ||||
| { | ||||
|   return FALSE; | ||||
| } | ||||
| @@ -84,34 +90,63 @@ meta_cursor_renderer_init (MetaCursorRenderer *renderer) | ||||
| { | ||||
| } | ||||
|  | ||||
| MetaRectangle | ||||
| meta_cursor_renderer_calculate_rect (MetaCursorRenderer *renderer, | ||||
|                                      MetaCursorSprite   *cursor_sprite) | ||||
| { | ||||
|   MetaCursorRendererPrivate *priv = | ||||
|     meta_cursor_renderer_get_instance_private (renderer); | ||||
|   CoglTexture *texture; | ||||
|   int hot_x, hot_y; | ||||
|   int width, height; | ||||
|   float texture_scale; | ||||
|  | ||||
|   texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite); | ||||
|   if (!texture) | ||||
|     return (MetaRectangle) { 0 }; | ||||
|  | ||||
|   meta_cursor_sprite_get_hotspot (cursor_sprite, &hot_x, &hot_y); | ||||
|   texture_scale = meta_cursor_sprite_get_texture_scale (cursor_sprite); | ||||
|   width = cogl_texture_get_width (texture); | ||||
|   height = cogl_texture_get_height (texture); | ||||
|  | ||||
|   return (MetaRectangle) { | ||||
|     .x = (int)roundf (priv->current_x - (hot_x * texture_scale)), | ||||
|     .y = (int)roundf (priv->current_y - (hot_y * texture_scale)), | ||||
|     .width = (int)roundf (width * texture_scale), | ||||
|     .height = (int)roundf (height * texture_scale), | ||||
|   }; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| is_cursor_in_monitors_area (int x, int y) | ||||
| { | ||||
|   MetaMonitorManager *monitor_manager = meta_backend_get_monitor_manager (meta_get_backend ()); | ||||
|   return meta_monitor_manager_get_monitor_at_point (monitor_manager, | ||||
|                                                     (gfloat) x, (gfloat) y) >= 0; | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_cursor (MetaCursorRenderer *renderer) | ||||
| update_cursor (MetaCursorRenderer *renderer, | ||||
|                MetaCursorSprite   *cursor_sprite) | ||||
| { | ||||
|   MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); | ||||
|   gboolean handled_by_backend; | ||||
|   gboolean should_redraw = FALSE; | ||||
|  | ||||
|   if (priv->displayed_cursor) | ||||
|     { | ||||
|       CoglTexture *texture; | ||||
|       int hot_x, hot_y; | ||||
|   /* do not render cursor if it is not on any monitor. Such situation | ||||
|    * can occur e. g. after monitor hot-plug */ | ||||
|   if (!is_cursor_in_monitors_area (priv->current_x, priv->current_y)) | ||||
|     return; | ||||
|  | ||||
|       texture = meta_cursor_reference_get_cogl_texture (priv->displayed_cursor, &hot_x, &hot_y); | ||||
|   if (cursor_sprite) | ||||
|     meta_cursor_sprite_prepare_at (cursor_sprite, | ||||
|                                    priv->current_x, | ||||
|                                    priv->current_y); | ||||
|  | ||||
|       priv->current_rect.x = priv->current_x - hot_x; | ||||
|       priv->current_rect.y = priv->current_y - hot_y; | ||||
|       priv->current_rect.width = cogl_texture_get_width (COGL_TEXTURE (texture)); | ||||
|       priv->current_rect.height = cogl_texture_get_height (COGL_TEXTURE (texture)); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       priv->current_rect.x = 0; | ||||
|       priv->current_rect.y = 0; | ||||
|       priv->current_rect.width = 0; | ||||
|       priv->current_rect.height = 0; | ||||
|     } | ||||
|  | ||||
|   handled_by_backend = META_CURSOR_RENDERER_GET_CLASS (renderer)->update_cursor (renderer); | ||||
|   handled_by_backend = | ||||
|     META_CURSOR_RENDERER_GET_CLASS (renderer)->update_cursor (renderer, | ||||
|                                                               cursor_sprite); | ||||
|   if (handled_by_backend != priv->handled_by_backend) | ||||
|     { | ||||
|       priv->handled_by_backend = handled_by_backend; | ||||
| @@ -122,7 +157,7 @@ update_cursor (MetaCursorRenderer *renderer) | ||||
|     should_redraw = TRUE; | ||||
|  | ||||
|   if (should_redraw) | ||||
|     queue_redraw (renderer); | ||||
|     queue_redraw (renderer, cursor_sprite); | ||||
| } | ||||
|  | ||||
| MetaCursorRenderer * | ||||
| @@ -132,16 +167,25 @@ meta_cursor_renderer_new (void) | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_renderer_set_cursor (MetaCursorRenderer  *renderer, | ||||
|                                  MetaCursorReference *cursor) | ||||
| meta_cursor_renderer_set_cursor (MetaCursorRenderer *renderer, | ||||
|                                  MetaCursorSprite   *cursor_sprite) | ||||
| { | ||||
|   MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); | ||||
|  | ||||
|   if (priv->displayed_cursor == cursor) | ||||
|   if (priv->displayed_cursor == cursor_sprite) | ||||
|     return; | ||||
|   priv->displayed_cursor = cursor_sprite; | ||||
|  | ||||
|   priv->displayed_cursor = cursor; | ||||
|   update_cursor (renderer); | ||||
|   update_cursor (renderer, cursor_sprite); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_renderer_force_update (MetaCursorRenderer *renderer) | ||||
| { | ||||
|   MetaCursorRendererPrivate *priv = | ||||
|     meta_cursor_renderer_get_instance_private (renderer); | ||||
|  | ||||
|   update_cursor (renderer, priv->displayed_cursor); | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -155,10 +199,10 @@ meta_cursor_renderer_set_position (MetaCursorRenderer *renderer, | ||||
|   priv->current_x = x; | ||||
|   priv->current_y = y; | ||||
|  | ||||
|   update_cursor (renderer); | ||||
|   update_cursor (renderer, priv->displayed_cursor); | ||||
| } | ||||
|  | ||||
| MetaCursorReference * | ||||
| MetaCursorSprite * | ||||
| meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer) | ||||
| { | ||||
|   MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); | ||||
| @@ -166,10 +210,27 @@ meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer) | ||||
|   return priv->displayed_cursor; | ||||
| } | ||||
|  | ||||
| const MetaRectangle * | ||||
| meta_cursor_renderer_get_rect (MetaCursorRenderer *renderer) | ||||
| #ifdef HAVE_WAYLAND | ||||
| void | ||||
| meta_cursor_renderer_realize_cursor_from_wl_buffer (MetaCursorRenderer *renderer, | ||||
|                                                     MetaCursorSprite   *cursor_sprite, | ||||
|                                                     struct wl_resource *buffer) | ||||
| { | ||||
|   MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); | ||||
|  | ||||
|   return &priv->current_rect; | ||||
|   MetaCursorRendererClass *renderer_class = META_CURSOR_RENDERER_GET_CLASS (renderer); | ||||
|  | ||||
|   if (renderer_class->realize_cursor_from_wl_buffer) | ||||
|     renderer_class->realize_cursor_from_wl_buffer (renderer, cursor_sprite, buffer); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| void | ||||
| meta_cursor_renderer_realize_cursor_from_xcursor (MetaCursorRenderer *renderer, | ||||
|                                                   MetaCursorSprite   *cursor_sprite, | ||||
|                                                   XcursorImage       *xc_image) | ||||
| { | ||||
|   MetaCursorRendererClass *renderer_class = META_CURSOR_RENDERER_GET_CLASS (renderer); | ||||
|  | ||||
|   if (renderer_class->realize_cursor_from_xcursor) | ||||
|     renderer_class->realize_cursor_from_xcursor (renderer, cursor_sprite, xc_image); | ||||
| } | ||||
|   | ||||
| @@ -26,45 +26,56 @@ | ||||
| #define META_CURSOR_RENDERER_H | ||||
|  | ||||
| #include <glib-object.h> | ||||
| #include <X11/Xcursor/Xcursor.h> | ||||
| #ifdef HAVE_WAYLAND | ||||
| #include <wayland-server.h> | ||||
| #endif | ||||
|  | ||||
| #include <meta/screen.h> | ||||
| #include "meta-cursor.h" | ||||
|  | ||||
| #include <gbm.h> | ||||
|  | ||||
| #define META_TYPE_CURSOR_RENDERER            (meta_cursor_renderer_get_type ()) | ||||
| #define META_CURSOR_RENDERER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CURSOR_RENDERER, MetaCursorRenderer)) | ||||
| #define META_CURSOR_RENDERER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_CURSOR_RENDERER, MetaCursorRendererClass)) | ||||
| #define META_IS_CURSOR_RENDERER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_CURSOR_RENDERER)) | ||||
| #define META_IS_CURSOR_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_CURSOR_RENDERER)) | ||||
| #define META_CURSOR_RENDERER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_CURSOR_RENDERER, MetaCursorRendererClass)) | ||||
|  | ||||
| typedef struct _MetaCursorRenderer        MetaCursorRenderer; | ||||
| typedef struct _MetaCursorRendererClass   MetaCursorRendererClass; | ||||
|  | ||||
| struct _MetaCursorRenderer | ||||
| { | ||||
|   GObject parent; | ||||
| }; | ||||
| #define META_TYPE_CURSOR_RENDERER (meta_cursor_renderer_get_type ()) | ||||
| G_DECLARE_DERIVABLE_TYPE (MetaCursorRenderer, meta_cursor_renderer, | ||||
|                           META, CURSOR_RENDERER, GObject); | ||||
|  | ||||
| struct _MetaCursorRendererClass | ||||
| { | ||||
|   GObjectClass parent_class; | ||||
|  | ||||
|   gboolean (* update_cursor) (MetaCursorRenderer *renderer); | ||||
|   gboolean (* update_cursor) (MetaCursorRenderer *renderer, | ||||
|                               MetaCursorSprite   *cursor_sprite); | ||||
| #ifdef HAVE_WAYLAND | ||||
|   void (* realize_cursor_from_wl_buffer) (MetaCursorRenderer *renderer, | ||||
|                                           MetaCursorSprite *cursor_sprite, | ||||
|                                           struct wl_resource *buffer); | ||||
| #endif | ||||
|   void (* realize_cursor_from_xcursor) (MetaCursorRenderer *renderer, | ||||
|                                         MetaCursorSprite *cursor_sprite, | ||||
|                                         XcursorImage *xc_image); | ||||
| }; | ||||
|  | ||||
| GType meta_cursor_renderer_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| MetaCursorRenderer * meta_cursor_renderer_new (void); | ||||
|  | ||||
| void meta_cursor_renderer_set_cursor (MetaCursorRenderer  *renderer, | ||||
|                                       MetaCursorReference *cursor); | ||||
| void meta_cursor_renderer_set_cursor (MetaCursorRenderer *renderer, | ||||
|                                       MetaCursorSprite   *cursor_sprite); | ||||
|  | ||||
| void meta_cursor_renderer_set_position (MetaCursorRenderer *renderer, | ||||
|                                         int x, int y); | ||||
| void meta_cursor_renderer_force_update (MetaCursorRenderer *renderer); | ||||
|  | ||||
| MetaCursorReference * meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer); | ||||
| const MetaRectangle * meta_cursor_renderer_get_rect (MetaCursorRenderer *renderer); | ||||
| MetaCursorSprite * meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer); | ||||
|  | ||||
| MetaRectangle meta_cursor_renderer_calculate_rect (MetaCursorRenderer *renderer, | ||||
|                                                    MetaCursorSprite   *cursor_sprite); | ||||
|  | ||||
| #ifdef HAVE_WAYLAND | ||||
| void meta_cursor_renderer_realize_cursor_from_wl_buffer (MetaCursorRenderer *renderer, | ||||
|                                                          MetaCursorSprite   *cursor_sprite, | ||||
|                                                          struct wl_resource *buffer); | ||||
| #endif | ||||
|  | ||||
| void meta_cursor_renderer_realize_cursor_from_xcursor (MetaCursorRenderer *renderer, | ||||
|                                                        MetaCursorSprite   *cursor_sprite, | ||||
|                                                        XcursorImage       *xc_image); | ||||
|  | ||||
| #endif /* META_CURSOR_RENDERER_H */ | ||||
|   | ||||
| @@ -34,7 +34,7 @@ struct _MetaCursorTracker { | ||||
|  | ||||
|   gboolean is_showing; | ||||
|  | ||||
|   MetaCursorReference *displayed_cursor; | ||||
|   MetaCursorSprite *displayed_cursor; | ||||
|  | ||||
|   /* Wayland clients can set a NULL buffer as their cursor | ||||
|    * explicitly, which means that we shouldn't display anything. | ||||
| @@ -42,12 +42,12 @@ struct _MetaCursorTracker { | ||||
|    * determine an unset window cursor; we need an extra boolean. | ||||
|    */ | ||||
|   gboolean has_window_cursor; | ||||
|   MetaCursorReference *window_cursor; | ||||
|   MetaCursorSprite *window_cursor; | ||||
|  | ||||
|   MetaCursorReference *root_cursor; | ||||
|   MetaCursorSprite *root_cursor; | ||||
|  | ||||
|   /* The cursor from the X11 server. */ | ||||
|   MetaCursorReference *xfixes_cursor; | ||||
|   MetaCursorSprite *xfixes_cursor; | ||||
| }; | ||||
|  | ||||
| struct _MetaCursorTrackerClass { | ||||
| @@ -57,16 +57,16 @@ struct _MetaCursorTrackerClass { | ||||
| gboolean meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker, | ||||
| 					    XEvent            *xevent); | ||||
|  | ||||
| void     meta_cursor_tracker_set_window_cursor   (MetaCursorTracker   *tracker, | ||||
|                                                   MetaCursorReference *cursor); | ||||
| void     meta_cursor_tracker_unset_window_cursor (MetaCursorTracker   *tracker); | ||||
| void     meta_cursor_tracker_set_root_cursor     (MetaCursorTracker   *tracker, | ||||
|                                                   MetaCursorReference *cursor); | ||||
| void     meta_cursor_tracker_set_window_cursor   (MetaCursorTracker *tracker, | ||||
|                                                   MetaCursorSprite  *cursor_sprite); | ||||
| void     meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker); | ||||
| void     meta_cursor_tracker_set_root_cursor     (MetaCursorTracker *tracker, | ||||
|                                                   MetaCursorSprite  *cursor_sprite); | ||||
|  | ||||
| void     meta_cursor_tracker_update_position (MetaCursorTracker *tracker, | ||||
| 					      int                new_x, | ||||
| 					      int                new_y); | ||||
|  | ||||
| MetaCursorReference * meta_cursor_tracker_get_displayed_cursor (MetaCursorTracker *tracker); | ||||
| MetaCursorSprite * meta_cursor_tracker_get_displayed_cursor (MetaCursorTracker *tracker); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -27,7 +27,9 @@ | ||||
|  *                     pointer abstraction" | ||||
|  */ | ||||
|  | ||||
| #include <config.h> | ||||
| #include "config.h" | ||||
| #include "meta-cursor-tracker-private.h" | ||||
|  | ||||
| #include <string.h> | ||||
| #include <meta/main.h> | ||||
| #include <meta/util.h> | ||||
| @@ -38,12 +40,10 @@ | ||||
|  | ||||
| #include <gdk/gdk.h> | ||||
| #include <gdk/gdkx.h> | ||||
| #include <X11/extensions/Xfixes.h> | ||||
|  | ||||
| #include "meta-backend-private.h" | ||||
|  | ||||
| #include "meta-cursor-private.h" | ||||
| #include "meta-cursor-tracker-private.h" | ||||
|  | ||||
| G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT); | ||||
|  | ||||
| enum { | ||||
| @@ -53,7 +53,7 @@ enum { | ||||
|  | ||||
| static guint signals[LAST_SIGNAL]; | ||||
|  | ||||
| static MetaCursorReference * | ||||
| static MetaCursorSprite * | ||||
| get_displayed_cursor (MetaCursorTracker *tracker) | ||||
| { | ||||
|   MetaDisplay *display = meta_get_display (); | ||||
| @@ -79,14 +79,14 @@ update_displayed_cursor (MetaCursorTracker *tracker) | ||||
| static void | ||||
| sync_cursor (MetaCursorTracker *tracker) | ||||
| { | ||||
|   MetaCursorReference *displayed_cursor = get_displayed_cursor (tracker); | ||||
|   MetaCursorSprite *displayed_cursor = get_displayed_cursor (tracker); | ||||
|  | ||||
|   if (tracker->displayed_cursor == displayed_cursor) | ||||
|     return; | ||||
|  | ||||
|   g_clear_pointer (&tracker->displayed_cursor, meta_cursor_reference_unref); | ||||
|   g_clear_object (&tracker->displayed_cursor); | ||||
|   if (displayed_cursor) | ||||
|     tracker->displayed_cursor = meta_cursor_reference_ref (displayed_cursor); | ||||
|     tracker->displayed_cursor = g_object_ref (displayed_cursor); | ||||
|  | ||||
|   update_displayed_cursor (tracker); | ||||
|   g_signal_emit (tracker, signals[CURSOR_CHANGED], 0); | ||||
| @@ -107,9 +107,9 @@ meta_cursor_tracker_finalize (GObject *object) | ||||
|   MetaCursorTracker *self = META_CURSOR_TRACKER (object); | ||||
|  | ||||
|   if (self->displayed_cursor) | ||||
|     meta_cursor_reference_unref (self->displayed_cursor); | ||||
|     g_object_unref (self->displayed_cursor); | ||||
|   if (self->root_cursor) | ||||
|     meta_cursor_reference_unref (self->root_cursor); | ||||
|     g_object_unref (self->root_cursor); | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_cursor_tracker_parent_class)->finalize (object); | ||||
| } | ||||
| @@ -155,13 +155,13 @@ meta_cursor_tracker_get_for_screen (MetaScreen *screen) | ||||
| } | ||||
|  | ||||
| static void | ||||
| set_window_cursor (MetaCursorTracker   *tracker, | ||||
|                    gboolean             has_cursor, | ||||
|                    MetaCursorReference *cursor) | ||||
| set_window_cursor (MetaCursorTracker *tracker, | ||||
|                    gboolean           has_cursor, | ||||
|                    MetaCursorSprite  *cursor_sprite) | ||||
| { | ||||
|   g_clear_pointer (&tracker->window_cursor, meta_cursor_reference_unref); | ||||
|   if (cursor) | ||||
|     tracker->window_cursor = meta_cursor_reference_ref (cursor); | ||||
|   g_clear_object (&tracker->window_cursor); | ||||
|   if (cursor_sprite) | ||||
|     tracker->window_cursor = g_object_ref (cursor_sprite); | ||||
|   tracker->has_window_cursor = has_cursor; | ||||
|   sync_cursor (tracker); | ||||
| } | ||||
| @@ -183,27 +183,12 @@ meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker, | ||||
|   if (notify_event->subtype != XFixesDisplayCursorNotify) | ||||
|     return FALSE; | ||||
|  | ||||
|   g_clear_pointer (&tracker->xfixes_cursor, meta_cursor_reference_unref); | ||||
|   g_clear_object (&tracker->xfixes_cursor); | ||||
|   g_signal_emit (tracker, signals[CURSOR_CHANGED], 0); | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static MetaCursorReference * | ||||
| meta_cursor_reference_take_texture (CoglTexture2D *texture, | ||||
|                                     int            hot_x, | ||||
|                                     int            hot_y) | ||||
| { | ||||
|   MetaCursorReference *self; | ||||
|  | ||||
|   self = g_slice_new0 (MetaCursorReference); | ||||
|   self->ref_count = 1; | ||||
|   self->image.texture = texture; | ||||
|   self->image.hot_x = hot_x; | ||||
|   self->image.hot_y = hot_y; | ||||
|  | ||||
|   return self; | ||||
| } | ||||
|  | ||||
| static void | ||||
| ensure_xfixes_cursor (MetaCursorTracker *tracker) | ||||
| { | ||||
| @@ -261,10 +246,13 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker) | ||||
|  | ||||
|   if (sprite != NULL) | ||||
|     { | ||||
|       MetaCursorReference *cursor = meta_cursor_reference_take_texture (sprite, | ||||
|                                                                         cursor_image->xhot, | ||||
|                                                                         cursor_image->yhot); | ||||
|       tracker->xfixes_cursor = cursor; | ||||
|       MetaCursorSprite *cursor_sprite = meta_cursor_sprite_new (); | ||||
|       meta_cursor_sprite_set_texture (cursor_sprite, | ||||
|                                       sprite, | ||||
|                                       cursor_image->xhot, | ||||
|                                       cursor_image->yhot); | ||||
|       cogl_object_unref (sprite); | ||||
|       tracker->xfixes_cursor = cursor_sprite; | ||||
|     } | ||||
|   XFree (cursor_image); | ||||
| } | ||||
| @@ -277,22 +265,22 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker) | ||||
| CoglTexture * | ||||
| meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker) | ||||
| { | ||||
|   MetaCursorReference *cursor; | ||||
|   MetaCursorSprite *cursor_sprite; | ||||
|  | ||||
|   g_return_val_if_fail (META_IS_CURSOR_TRACKER (tracker), NULL); | ||||
|  | ||||
|   if (meta_is_wayland_compositor ()) | ||||
|     { | ||||
|       cursor = tracker->displayed_cursor; | ||||
|       cursor_sprite = tracker->displayed_cursor; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       ensure_xfixes_cursor (tracker); | ||||
|       cursor = tracker->xfixes_cursor; | ||||
|       cursor_sprite = tracker->xfixes_cursor; | ||||
|     } | ||||
|  | ||||
|   if (cursor) | ||||
|     return meta_cursor_reference_get_cogl_texture (cursor, NULL, NULL); | ||||
|   if (cursor_sprite) | ||||
|     return meta_cursor_sprite_get_cogl_texture (cursor_sprite); | ||||
|   else | ||||
|     return NULL; | ||||
| } | ||||
| @@ -309,22 +297,22 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker, | ||||
|                              int               *x, | ||||
|                              int               *y) | ||||
| { | ||||
|   MetaCursorReference *cursor; | ||||
|   MetaCursorSprite *cursor_sprite; | ||||
|  | ||||
|   g_return_if_fail (META_IS_CURSOR_TRACKER (tracker)); | ||||
|  | ||||
|   if (meta_is_wayland_compositor ()) | ||||
|     { | ||||
|       cursor = tracker->displayed_cursor; | ||||
|       cursor_sprite = tracker->displayed_cursor; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       ensure_xfixes_cursor (tracker); | ||||
|       cursor = tracker->xfixes_cursor; | ||||
|       cursor_sprite = tracker->xfixes_cursor; | ||||
|     } | ||||
|  | ||||
|   if (cursor) | ||||
|     meta_cursor_reference_get_cogl_texture (cursor, x, y); | ||||
|   if (cursor_sprite) | ||||
|     meta_cursor_sprite_get_hotspot (cursor_sprite, x, y); | ||||
|   else | ||||
|     { | ||||
|       if (x) | ||||
| @@ -335,10 +323,10 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker, | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_tracker_set_window_cursor (MetaCursorTracker   *tracker, | ||||
|                                        MetaCursorReference *cursor) | ||||
| meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker, | ||||
|                                        MetaCursorSprite  *cursor_sprite) | ||||
| { | ||||
|   set_window_cursor (tracker, TRUE, cursor); | ||||
|   set_window_cursor (tracker, TRUE, cursor_sprite); | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -348,12 +336,12 @@ meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker) | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_tracker_set_root_cursor (MetaCursorTracker   *tracker, | ||||
|                                      MetaCursorReference *cursor) | ||||
| meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker, | ||||
|                                      MetaCursorSprite  *cursor_sprite) | ||||
| { | ||||
|   g_clear_pointer (&tracker->root_cursor, meta_cursor_reference_unref); | ||||
|   if (cursor) | ||||
|     tracker->root_cursor = meta_cursor_reference_ref (cursor); | ||||
|   g_clear_object (&tracker->root_cursor); | ||||
|   if (cursor_sprite) | ||||
|     tracker->root_cursor = g_object_ref (cursor_sprite); | ||||
|  | ||||
|   sync_cursor (tracker); | ||||
| } | ||||
| @@ -373,12 +361,12 @@ get_pointer_position_gdk (int         *x, | ||||
|                           int         *y, | ||||
|                           int         *mods) | ||||
| { | ||||
|   GdkDeviceManager *gmanager; | ||||
|   GdkSeat *gseat; | ||||
|   GdkDevice *gdevice; | ||||
|   GdkScreen *gscreen; | ||||
|  | ||||
|   gmanager = gdk_display_get_device_manager (gdk_display_get_default ()); | ||||
|   gdevice = gdk_x11_device_manager_lookup (gmanager, META_VIRTUAL_CORE_POINTER_ID); | ||||
|   gseat = gdk_display_get_default_seat (gdk_display_get_default ()); | ||||
|   gdevice = gdk_seat_get_pointer (gseat); | ||||
|  | ||||
|   gdk_device_get_position (gdevice, &gscreen, x, y); | ||||
|   if (mods) | ||||
| @@ -436,7 +424,7 @@ meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker, | ||||
|   sync_cursor (tracker); | ||||
| } | ||||
|  | ||||
| MetaCursorReference * | ||||
| MetaCursorSprite * | ||||
| meta_cursor_tracker_get_displayed_cursor (MetaCursorTracker *tracker) | ||||
| { | ||||
|   return tracker->displayed_cursor; | ||||
|   | ||||
| @@ -21,7 +21,7 @@ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include "meta-cursor-private.h" | ||||
| #include "meta-cursor.h" | ||||
|  | ||||
| #include <meta/errors.h> | ||||
|  | ||||
| @@ -29,55 +29,38 @@ | ||||
| #include "screen-private.h" | ||||
| #include "meta-backend-private.h" | ||||
|  | ||||
| #ifdef HAVE_NATIVE_BACKEND | ||||
| #include "backends/native/meta-cursor-renderer-native.h" | ||||
| #endif | ||||
|  | ||||
| #include <string.h> | ||||
|  | ||||
| #include <X11/cursorfont.h> | ||||
| #include <X11/extensions/Xfixes.h> | ||||
| #include <X11/Xcursor/Xcursor.h> | ||||
|  | ||||
| #ifdef HAVE_WAYLAND | ||||
| #include <cogl/cogl-wayland-server.h> | ||||
| #endif | ||||
| enum { | ||||
|   PREPARE_AT, | ||||
|  | ||||
| MetaCursorReference * | ||||
| meta_cursor_reference_ref (MetaCursorReference *self) | ||||
|   LAST_SIGNAL | ||||
| }; | ||||
|  | ||||
| static guint signals[LAST_SIGNAL]; | ||||
|  | ||||
| struct _MetaCursorSprite | ||||
| { | ||||
|   g_assert (self->ref_count > 0); | ||||
|   self->ref_count++; | ||||
|   GObject parent; | ||||
|  | ||||
|   return self; | ||||
| } | ||||
|   MetaCursor cursor; | ||||
|  | ||||
| static void | ||||
| meta_cursor_image_free (MetaCursorImage *image) | ||||
| { | ||||
|   cogl_object_unref (image->texture); | ||||
|   CoglTexture2D *texture; | ||||
|   float texture_scale; | ||||
|   int hot_x, hot_y; | ||||
|  | ||||
| #ifdef HAVE_NATIVE_BACKEND | ||||
|   if (image->bo) | ||||
|     gbm_bo_destroy (image->bo); | ||||
| #endif | ||||
| } | ||||
|   int current_frame; | ||||
|   XcursorImages *xcursor_images; | ||||
|  | ||||
| static void | ||||
| meta_cursor_reference_free (MetaCursorReference *self) | ||||
| { | ||||
|   meta_cursor_image_free (&self->image); | ||||
|   g_slice_free (MetaCursorReference, self); | ||||
| } | ||||
|   int theme_scale; | ||||
|   gboolean theme_dirty; | ||||
| }; | ||||
|  | ||||
| void | ||||
| meta_cursor_reference_unref (MetaCursorReference *self) | ||||
| { | ||||
|   self->ref_count--; | ||||
|  | ||||
|   if (self->ref_count == 0) | ||||
|     meta_cursor_reference_free (self); | ||||
| } | ||||
| G_DEFINE_TYPE (MetaCursorSprite, meta_cursor_sprite, G_TYPE_OBJECT) | ||||
|  | ||||
| static const char * | ||||
| translate_meta_cursor (MetaCursor cursor) | ||||
| @@ -134,93 +117,27 @@ meta_cursor_create_x_cursor (Display    *xdisplay, | ||||
|   return XcursorLibraryLoadCursor (xdisplay, translate_meta_cursor (cursor)); | ||||
| } | ||||
|  | ||||
| static XcursorImage * | ||||
| load_cursor_on_client (MetaCursor cursor) | ||||
| static XcursorImages * | ||||
| load_cursor_on_client (MetaCursor cursor, int scale) | ||||
| { | ||||
|   return XcursorLibraryLoadImage (translate_meta_cursor (cursor), | ||||
|                                   meta_prefs_get_cursor_theme (), | ||||
|                                   meta_prefs_get_cursor_size ()); | ||||
|   return XcursorLibraryLoadImages (translate_meta_cursor (cursor), | ||||
|                                    meta_prefs_get_cursor_theme (), | ||||
|                                    meta_prefs_get_cursor_size () * scale); | ||||
| } | ||||
|  | ||||
| #ifdef HAVE_NATIVE_BACKEND | ||||
| static void | ||||
| get_hardware_cursor_size (uint64_t *cursor_width, uint64_t *cursor_height) | ||||
| meta_cursor_sprite_load_from_xcursor_image (MetaCursorSprite *self, | ||||
|                                             XcursorImage     *xc_image) | ||||
| { | ||||
|   MetaBackend *meta_backend = meta_get_backend (); | ||||
|   MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend); | ||||
|  | ||||
|   if (META_IS_CURSOR_RENDERER_NATIVE (renderer)) | ||||
|     { | ||||
|       meta_cursor_renderer_native_get_cursor_size (META_CURSOR_RENDERER_NATIVE (renderer), cursor_width, cursor_height); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   g_assert_not_reached (); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #ifdef HAVE_NATIVE_BACKEND | ||||
| static void | ||||
| meta_cursor_image_load_gbm_buffer (struct gbm_device *gbm, | ||||
|                                    MetaCursorImage   *image, | ||||
|                                    uint8_t           *pixels, | ||||
|                                    uint               width, | ||||
|                                    uint               height, | ||||
|                                    int                rowstride, | ||||
|                                    uint32_t           gbm_format) | ||||
| { | ||||
|   uint64_t cursor_width, cursor_height; | ||||
|   get_hardware_cursor_size (&cursor_width, &cursor_height); | ||||
|  | ||||
|   if (width > cursor_width || height > cursor_height) | ||||
|     { | ||||
|       meta_warning ("Invalid theme cursor size (must be at most %ux%u)\n", | ||||
|                     (unsigned int)cursor_width, (unsigned int)cursor_height); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   if (gbm_device_is_format_supported (gbm, gbm_format, | ||||
|                                       GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE)) | ||||
|     { | ||||
|       uint8_t buf[4 * cursor_width * cursor_height]; | ||||
|       uint i; | ||||
|  | ||||
|       image->bo = gbm_bo_create (gbm, cursor_width, cursor_height, | ||||
|                                  gbm_format, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE); | ||||
|  | ||||
|       memset (buf, 0, sizeof(buf)); | ||||
|       for (i = 0; i < height; i++) | ||||
|         memcpy (buf + i * 4 * cursor_width, pixels + i * rowstride, width * 4); | ||||
|  | ||||
|       gbm_bo_write (image->bo, buf, cursor_width * cursor_height * 4); | ||||
|     } | ||||
|   else | ||||
|     meta_warning ("HW cursor for format %d not supported\n", gbm_format); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #ifdef HAVE_NATIVE_BACKEND | ||||
| static struct gbm_device * | ||||
| get_gbm_device (void) | ||||
| { | ||||
|   MetaBackend *meta_backend = meta_get_backend (); | ||||
|   MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend); | ||||
|  | ||||
|   if (META_IS_CURSOR_RENDERER_NATIVE (renderer)) | ||||
|     return meta_cursor_renderer_native_get_gbm_device (META_CURSOR_RENDERER_NATIVE (renderer)); | ||||
|   else | ||||
|     return NULL; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static void | ||||
| meta_cursor_image_load_from_xcursor_image (MetaCursorImage   *image, | ||||
|                                            XcursorImage      *xc_image) | ||||
| { | ||||
|   uint width, height, rowstride; | ||||
|   CoglPixelFormat cogl_format; | ||||
|   ClutterBackend *clutter_backend; | ||||
|   CoglContext *cogl_context; | ||||
|   CoglTexture *texture; | ||||
|  | ||||
|   g_assert (self->texture == NULL); | ||||
|  | ||||
|   width           = xc_image->width; | ||||
|   height          = xc_image->height; | ||||
| @@ -232,177 +149,210 @@ meta_cursor_image_load_from_xcursor_image (MetaCursorImage   *image, | ||||
|   cogl_format = COGL_PIXEL_FORMAT_ARGB_8888; | ||||
| #endif | ||||
|  | ||||
|   image->hot_x = xc_image->xhot; | ||||
|   image->hot_y = xc_image->yhot; | ||||
|  | ||||
|   clutter_backend = clutter_get_default_backend (); | ||||
|   cogl_context = clutter_backend_get_cogl_context (clutter_backend); | ||||
|   image->texture = cogl_texture_2d_new_from_data (cogl_context, | ||||
|                                                   width, height, | ||||
|                                                   cogl_format, | ||||
|                                                   rowstride, | ||||
|                                                   (uint8_t *) xc_image->pixels, | ||||
|                                                   NULL); | ||||
|   texture = cogl_texture_2d_new_from_data (cogl_context, | ||||
|                                            width, height, | ||||
|                                            cogl_format, | ||||
|                                            rowstride, | ||||
|                                            (uint8_t *) xc_image->pixels, | ||||
|                                            NULL); | ||||
|   meta_cursor_sprite_set_texture (self, texture, | ||||
|                                   xc_image->xhot, xc_image->yhot); | ||||
|   cogl_object_unref (texture); | ||||
|  | ||||
| #ifdef HAVE_NATIVE_BACKEND | ||||
|   struct gbm_device *gbm = get_gbm_device (); | ||||
|   if (gbm) | ||||
|     meta_cursor_image_load_gbm_buffer (gbm, | ||||
|                                        image, | ||||
|                                        (uint8_t *) xc_image->pixels, | ||||
|                                        width, height, rowstride, | ||||
|                                        GBM_FORMAT_ARGB8888); | ||||
| #endif | ||||
|   meta_cursor_renderer_realize_cursor_from_xcursor (renderer, self, xc_image); | ||||
| } | ||||
|  | ||||
| MetaCursorReference * | ||||
| meta_cursor_reference_from_theme (MetaCursor cursor) | ||||
| static XcursorImage * | ||||
| meta_cursor_sprite_get_current_frame_image (MetaCursorSprite *self) | ||||
| { | ||||
|   return self->xcursor_images->images[self->current_frame]; | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_sprite_tick_frame (MetaCursorSprite *self) | ||||
| { | ||||
|   MetaCursorReference *self; | ||||
|   XcursorImage *image; | ||||
|  | ||||
|   image = load_cursor_on_client (cursor); | ||||
|   if (!image) | ||||
|     return NULL; | ||||
|   if (!meta_cursor_sprite_is_animated (self)) | ||||
|     return; | ||||
|  | ||||
|   self = g_slice_new0 (MetaCursorReference); | ||||
|   self->ref_count = 1; | ||||
|   self->cursor = cursor; | ||||
|   meta_cursor_image_load_from_xcursor_image (&self->image, image); | ||||
|   self->current_frame++; | ||||
|  | ||||
|   XcursorImageDestroy (image); | ||||
|   return self; | ||||
|   if (self->current_frame >= self->xcursor_images->nimage) | ||||
|     self->current_frame = 0; | ||||
|  | ||||
|   image = meta_cursor_sprite_get_current_frame_image (self); | ||||
|  | ||||
|   g_clear_pointer (&self->texture, cogl_object_unref); | ||||
|   meta_cursor_sprite_load_from_xcursor_image (self, image); | ||||
| } | ||||
|  | ||||
| guint | ||||
| meta_cursor_sprite_get_current_frame_time (MetaCursorSprite *self) | ||||
| { | ||||
|   if (!meta_cursor_sprite_is_animated (self)) | ||||
|     return 0; | ||||
|  | ||||
|   return self->xcursor_images->images[self->current_frame]->delay; | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_cursor_sprite_is_animated (MetaCursorSprite *self) | ||||
| { | ||||
|   return (self->xcursor_images && | ||||
|           self->xcursor_images->nimage > 1); | ||||
| } | ||||
|  | ||||
| MetaCursorSprite * | ||||
| meta_cursor_sprite_new (void) | ||||
| { | ||||
|   return g_object_new (META_TYPE_CURSOR_SPRITE, NULL); | ||||
| } | ||||
|  | ||||
| #ifdef HAVE_WAYLAND | ||||
| static void | ||||
| meta_cursor_image_load_from_buffer (MetaCursorImage    *image, | ||||
|                                     struct wl_resource *buffer, | ||||
|                                     int                 hot_x, | ||||
|                                     int                 hot_y) | ||||
| meta_cursor_sprite_load_from_theme (MetaCursorSprite *self) | ||||
| { | ||||
|   ClutterBackend *backend; | ||||
|   CoglContext *cogl_context; | ||||
|   XcursorImage *image; | ||||
|  | ||||
|   image->hot_x = hot_x; | ||||
|   image->hot_y = hot_y; | ||||
|   g_assert (self->cursor != META_CURSOR_NONE); | ||||
|  | ||||
|   backend = clutter_get_default_backend (); | ||||
|   cogl_context = clutter_backend_get_cogl_context (backend); | ||||
|  | ||||
|   image->texture = cogl_wayland_texture_2d_new_from_buffer (cogl_context, buffer, NULL); | ||||
|  | ||||
| #ifdef HAVE_NATIVE_BACKEND | ||||
|   struct gbm_device *gbm = get_gbm_device (); | ||||
|   if (gbm) | ||||
|   /* We might be reloading with a different scale. If so clear the old data. */ | ||||
|   if (self->xcursor_images) | ||||
|     { | ||||
|       uint32_t gbm_format; | ||||
|       uint64_t cursor_width, cursor_height; | ||||
|       uint width, height; | ||||
|  | ||||
|       width = cogl_texture_get_width (COGL_TEXTURE (image->texture)); | ||||
|       height = cogl_texture_get_height (COGL_TEXTURE (image->texture)); | ||||
|  | ||||
|       struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (buffer); | ||||
|       if (shm_buffer) | ||||
|         { | ||||
|           int rowstride = wl_shm_buffer_get_stride (shm_buffer); | ||||
|  | ||||
|           switch (wl_shm_buffer_get_format (shm_buffer)) | ||||
|             { | ||||
| #if G_BYTE_ORDER == G_BIG_ENDIAN | ||||
|             case WL_SHM_FORMAT_ARGB8888: | ||||
|               gbm_format = GBM_FORMAT_ARGB8888; | ||||
|               break; | ||||
|             case WL_SHM_FORMAT_XRGB8888: | ||||
|               gbm_format = GBM_FORMAT_XRGB8888; | ||||
|               break; | ||||
| #else | ||||
|             case WL_SHM_FORMAT_ARGB8888: | ||||
|               gbm_format = GBM_FORMAT_ARGB8888; | ||||
|               break; | ||||
|             case WL_SHM_FORMAT_XRGB8888: | ||||
|               gbm_format = GBM_FORMAT_XRGB8888; | ||||
|               break; | ||||
| #endif | ||||
|             default: | ||||
|               g_warn_if_reached (); | ||||
|               gbm_format = GBM_FORMAT_ARGB8888; | ||||
|             } | ||||
|  | ||||
|           meta_cursor_image_load_gbm_buffer (gbm, | ||||
|                                              image, | ||||
|                                              (uint8_t *) wl_shm_buffer_get_data (shm_buffer), | ||||
|                                              width, height, rowstride, | ||||
|                                              gbm_format); | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           /* HW cursors have a predefined size (at least 64x64), which usually is bigger than cursor theme | ||||
|              size, so themed cursors must be padded with transparent pixels to fill the | ||||
|              overlay. This is trivial if we have CPU access to the data, but it's not | ||||
|              possible if the buffer is in GPU memory (and possibly tiled too), so if we | ||||
|              don't get the right size, we fallback to GL. | ||||
|           */ | ||||
|           get_hardware_cursor_size (&cursor_width, &cursor_height); | ||||
|  | ||||
|           if (width != cursor_width || height != cursor_height) | ||||
|             { | ||||
|               meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n"); | ||||
|               return; | ||||
|             } | ||||
|  | ||||
|           image->bo = gbm_bo_import (gbm, GBM_BO_IMPORT_WL_BUFFER, buffer, GBM_BO_USE_CURSOR); | ||||
|           if (!image->bo) | ||||
|             meta_warning ("Importing HW cursor from wl_buffer failed\n"); | ||||
|         } | ||||
|       g_clear_pointer (&self->texture, cogl_object_unref); | ||||
|       XcursorImagesDestroy (self->xcursor_images); | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|   self->current_frame = 0; | ||||
|   self->xcursor_images = load_cursor_on_client (self->cursor, | ||||
|                                                 self->theme_scale); | ||||
|   if (!self->xcursor_images) | ||||
|     meta_fatal ("Could not find cursor. Perhaps set XCURSOR_PATH?"); | ||||
|  | ||||
|   image = meta_cursor_sprite_get_current_frame_image (self); | ||||
|   meta_cursor_sprite_load_from_xcursor_image (self, image); | ||||
|  | ||||
|   self->theme_dirty = FALSE; | ||||
| } | ||||
|  | ||||
| MetaCursorReference * | ||||
| meta_cursor_reference_from_buffer (struct wl_resource *buffer, | ||||
|                                    int                 hot_x, | ||||
|                                    int                 hot_y) | ||||
| MetaCursorSprite * | ||||
| meta_cursor_sprite_from_theme (MetaCursor cursor) | ||||
| { | ||||
|   MetaCursorReference *self; | ||||
|   MetaCursorSprite *self; | ||||
|  | ||||
|   self = g_slice_new0 (MetaCursorReference); | ||||
|   self->ref_count = 1; | ||||
|   meta_cursor_image_load_from_buffer (&self->image, buffer, hot_x, hot_y); | ||||
|   self = meta_cursor_sprite_new (); | ||||
|  | ||||
|   self->cursor = cursor; | ||||
|   self->theme_dirty = TRUE; | ||||
|  | ||||
|   return self; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| void | ||||
| meta_cursor_sprite_set_texture (MetaCursorSprite *self, | ||||
|                                 CoglTexture      *texture, | ||||
|                                 int               hot_x, | ||||
|                                 int               hot_y) | ||||
| { | ||||
|   g_clear_pointer (&self->texture, cogl_object_unref); | ||||
|   if (texture) | ||||
|     self->texture = cogl_object_ref (texture); | ||||
|   self->hot_x = hot_x; | ||||
|   self->hot_y = hot_y; | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_sprite_set_texture_scale (MetaCursorSprite *self, | ||||
|                                       float             scale) | ||||
| { | ||||
|   self->texture_scale = scale; | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_sprite_set_theme_scale (MetaCursorSprite *self, | ||||
|                                     int               theme_scale) | ||||
| { | ||||
|   if (self->theme_scale != theme_scale) | ||||
|     self->theme_dirty = TRUE; | ||||
|   self->theme_scale = theme_scale; | ||||
| } | ||||
|  | ||||
| CoglTexture * | ||||
| meta_cursor_reference_get_cogl_texture (MetaCursorReference *cursor, | ||||
|                                         int                 *hot_x, | ||||
|                                         int                 *hot_y) | ||||
| meta_cursor_sprite_get_cogl_texture (MetaCursorSprite *self) | ||||
| { | ||||
|   if (hot_x) | ||||
|     *hot_x = cursor->image.hot_x; | ||||
|   if (hot_y) | ||||
|     *hot_y = cursor->image.hot_y; | ||||
|   return COGL_TEXTURE (cursor->image.texture); | ||||
|   return COGL_TEXTURE (self->texture); | ||||
| } | ||||
|  | ||||
| #ifdef HAVE_NATIVE_BACKEND | ||||
| struct gbm_bo * | ||||
| meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor, | ||||
|                                   int                 *hot_x, | ||||
|                                   int                 *hot_y) | ||||
| { | ||||
|   if (hot_x) | ||||
|     *hot_x = cursor->image.hot_x; | ||||
|   if (hot_y) | ||||
|     *hot_y = cursor->image.hot_y; | ||||
|   return cursor->image.bo; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| MetaCursor | ||||
| meta_cursor_reference_get_meta_cursor (MetaCursorReference *cursor) | ||||
| meta_cursor_sprite_get_meta_cursor (MetaCursorSprite *self) | ||||
| { | ||||
|   return cursor->cursor; | ||||
|   return self->cursor; | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_sprite_get_hotspot (MetaCursorSprite *self, | ||||
|                                 int              *hot_x, | ||||
|                                 int              *hot_y) | ||||
| { | ||||
|   *hot_x = self->hot_x; | ||||
|   *hot_y = self->hot_y; | ||||
| } | ||||
|  | ||||
| float | ||||
| meta_cursor_sprite_get_texture_scale (MetaCursorSprite *self) | ||||
| { | ||||
|   return self->texture_scale; | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_sprite_prepare_at (MetaCursorSprite *self, | ||||
|                                int               x, | ||||
|                                int               y) | ||||
| { | ||||
|   g_signal_emit (self, signals[PREPARE_AT], 0, x, y); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_sprite_realize_texture (MetaCursorSprite *self) | ||||
| { | ||||
|   if (self->theme_dirty) | ||||
|     meta_cursor_sprite_load_from_theme (self); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_cursor_sprite_init (MetaCursorSprite *self) | ||||
| { | ||||
|   self->texture_scale = 1.0f; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_cursor_sprite_finalize (GObject *object) | ||||
| { | ||||
|   MetaCursorSprite *self = META_CURSOR_SPRITE (object); | ||||
|  | ||||
|   if (self->xcursor_images) | ||||
|     XcursorImagesDestroy (self->xcursor_images); | ||||
|  | ||||
|   g_clear_pointer (&self->texture, cogl_object_unref); | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_cursor_sprite_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_cursor_sprite_class_init (MetaCursorSpriteClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|  | ||||
|   object_class->finalize = meta_cursor_sprite_finalize; | ||||
|  | ||||
|   signals[PREPARE_AT] = g_signal_new ("prepare-at", | ||||
|                                       G_TYPE_FROM_CLASS (object_class), | ||||
|                                       G_SIGNAL_RUN_LAST, | ||||
|                                       0, | ||||
|                                       NULL, NULL, NULL, | ||||
|                                       G_TYPE_NONE, 2, | ||||
|                                       G_TYPE_INT, | ||||
|                                       G_TYPE_INT); | ||||
| } | ||||
|   | ||||
| @@ -22,25 +22,54 @@ | ||||
| #ifndef META_CURSOR_H | ||||
| #define META_CURSOR_H | ||||
|  | ||||
| typedef struct _MetaCursorReference MetaCursorReference; | ||||
|  | ||||
| MetaCursorReference * meta_cursor_reference_ref (MetaCursorReference *cursor); | ||||
| void meta_cursor_reference_unref (MetaCursorReference *cursor); | ||||
|  | ||||
| #include <meta/common.h> | ||||
| #include <meta/boxes.h> | ||||
|  | ||||
| MetaCursorReference * meta_cursor_reference_from_theme  (MetaCursor          cursor); | ||||
| typedef struct _MetaCursorSprite MetaCursorSprite; | ||||
|  | ||||
| #ifdef HAVE_WAYLAND | ||||
| #include <wayland-server.h> | ||||
| MetaCursorReference * meta_cursor_reference_from_buffer (struct wl_resource *buffer, | ||||
|                                                          int                 hot_x, | ||||
|                                                          int                 hot_y); | ||||
| #endif | ||||
| #define META_TYPE_CURSOR_SPRITE (meta_cursor_sprite_get_type ()) | ||||
| G_DECLARE_FINAL_TYPE (MetaCursorSprite, | ||||
|                       meta_cursor_sprite, | ||||
|                       META, CURSOR_SPRITE, | ||||
|                       GObject); | ||||
|  | ||||
| MetaCursor meta_cursor_reference_get_meta_cursor (MetaCursorReference *cursor); | ||||
| MetaCursorSprite * meta_cursor_sprite_new (void); | ||||
|  | ||||
| MetaCursorSprite * meta_cursor_sprite_from_theme  (MetaCursor cursor); | ||||
|  | ||||
|  | ||||
| void meta_cursor_sprite_set_theme_scale (MetaCursorSprite *self, | ||||
|                                          int               scale); | ||||
|  | ||||
| MetaCursor meta_cursor_sprite_get_meta_cursor (MetaCursorSprite *self); | ||||
|  | ||||
| Cursor meta_cursor_create_x_cursor (Display    *xdisplay, | ||||
|                                     MetaCursor  cursor); | ||||
|  | ||||
| void meta_cursor_sprite_prepare_at (MetaCursorSprite *self, | ||||
|                                     int               x, | ||||
|                                     int               y); | ||||
|  | ||||
| void meta_cursor_sprite_realize_texture (MetaCursorSprite *self); | ||||
|  | ||||
| void meta_cursor_sprite_set_texture (MetaCursorSprite *self, | ||||
|                                      CoglTexture      *texture, | ||||
|                                      int               hot_x, | ||||
|                                      int               hot_y); | ||||
|  | ||||
| void meta_cursor_sprite_set_texture_scale (MetaCursorSprite *self, | ||||
|                                            float             scale); | ||||
|  | ||||
| CoglTexture *meta_cursor_sprite_get_cogl_texture (MetaCursorSprite *self); | ||||
|  | ||||
| void meta_cursor_sprite_get_hotspot (MetaCursorSprite *self, | ||||
|                                      int              *hot_x, | ||||
|                                      int              *hot_y); | ||||
|  | ||||
| float meta_cursor_sprite_get_texture_scale (MetaCursorSprite *self); | ||||
|  | ||||
| gboolean meta_cursor_sprite_is_animated            (MetaCursorSprite *self); | ||||
| void     meta_cursor_sprite_tick_frame             (MetaCursorSprite *self); | ||||
| guint    meta_cursor_sprite_get_current_frame_time (MetaCursorSprite *self); | ||||
|  | ||||
| #endif /* META_CURSOR_H */ | ||||
|   | ||||
							
								
								
									
										87
									
								
								src/backends/meta-input-settings-private.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								src/backends/meta-input-settings-private.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,87 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright 2014 Red Hat, Inc. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * Author: Carlos Garnacho <carlosg@gnome.org> | ||||
|  */ | ||||
|  | ||||
| #ifndef META_INPUT_SETTINGS_PRIVATE_H | ||||
| #define META_INPUT_SETTINGS_PRIVATE_H | ||||
|  | ||||
| #include "display-private.h" | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| #define META_TYPE_INPUT_SETTINGS             (meta_input_settings_get_type ()) | ||||
| #define META_INPUT_SETTINGS(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_INPUT_SETTINGS, MetaInputSettings)) | ||||
| #define META_INPUT_SETTINGS_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_INPUT_SETTINGS, MetaInputSettingsClass)) | ||||
| #define META_IS_INPUT_SETTINGS(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_INPUT_SETTINGS)) | ||||
| #define META_IS_INPUT_SETTINGS_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_INPUT_SETTINGS)) | ||||
| #define META_INPUT_SETTINGS_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_INPUT_SETTINGS, MetaInputSettingsClass)) | ||||
|  | ||||
| typedef struct _MetaInputSettings MetaInputSettings; | ||||
| typedef struct _MetaInputSettingsClass MetaInputSettingsClass; | ||||
|  | ||||
| struct _MetaInputSettings | ||||
| { | ||||
|   GObject parent_instance; | ||||
| }; | ||||
|  | ||||
| struct _MetaInputSettingsClass | ||||
| { | ||||
|   GObjectClass parent_class; | ||||
|  | ||||
|   void (* set_send_events)   (MetaInputSettings        *settings, | ||||
|                               ClutterInputDevice       *device, | ||||
|                               GDesktopDeviceSendEvents  mode); | ||||
|   void (* set_matrix)        (MetaInputSettings  *settings, | ||||
|                               ClutterInputDevice *device, | ||||
|                               gfloat              matrix[6]); | ||||
|   void (* set_speed)         (MetaInputSettings  *settings, | ||||
|                               ClutterInputDevice *device, | ||||
|                               gdouble             speed); | ||||
|   void (* set_left_handed)   (MetaInputSettings  *settings, | ||||
|                               ClutterInputDevice *device, | ||||
|                               gboolean            enabled); | ||||
|   void (* set_tap_enabled)   (MetaInputSettings  *settings, | ||||
|                               ClutterInputDevice *device, | ||||
|                               gboolean            enabled); | ||||
|   void (* set_invert_scroll) (MetaInputSettings  *settings, | ||||
|                               ClutterInputDevice *device, | ||||
|                               gboolean            inverted); | ||||
|   void (* set_edge_scroll)   (MetaInputSettings  *settings, | ||||
|                               ClutterInputDevice *device, | ||||
|                               gboolean            enabled); | ||||
|   void (* set_scroll_button) (MetaInputSettings  *settings, | ||||
|                               ClutterInputDevice *device, | ||||
|                               guint               button); | ||||
|  | ||||
|   void (* set_click_method)  (MetaInputSettings            *settings, | ||||
|                               ClutterInputDevice           *device, | ||||
|                               GDesktopTouchpadClickMethod   mode); | ||||
|  | ||||
|   void (* set_keyboard_repeat) (MetaInputSettings *settings, | ||||
|                                 gboolean           repeat, | ||||
|                                 guint              delay, | ||||
|                                 guint              interval); | ||||
| }; | ||||
|  | ||||
| GType meta_input_settings_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| MetaInputSettings * meta_input_settings_create (void); | ||||
|  | ||||
| #endif /* META_INPUT_SETTINGS_PRIVATE_H */ | ||||
							
								
								
									
										893
									
								
								src/backends/meta-input-settings.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										893
									
								
								src/backends/meta-input-settings.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,893 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright 2014 Red Hat, Inc. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * Author: Carlos Garnacho <carlosg@gnome.org> | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * SECTION:input-settings | ||||
|  * @title: MetaInputSettings | ||||
|  * @short_description: Mutter input device configuration | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include <string.h> | ||||
|  | ||||
| #include "meta-backend-private.h" | ||||
| #include "meta-input-settings-private.h" | ||||
| #include "x11/meta-input-settings-x11.h" | ||||
|  | ||||
| #ifdef HAVE_NATIVE_BACKEND | ||||
| #include "native/meta-backend-native.h" | ||||
| #include "native/meta-input-settings-native.h" | ||||
| #endif | ||||
|  | ||||
| #include <meta/util.h> | ||||
|  | ||||
| typedef struct _MetaInputSettingsPrivate MetaInputSettingsPrivate; | ||||
| typedef struct _DeviceMappingInfo DeviceMappingInfo; | ||||
|  | ||||
| struct _DeviceMappingInfo | ||||
| { | ||||
|   MetaInputSettings *input_settings; | ||||
|   ClutterInputDevice *device; | ||||
|   GSettings *settings; | ||||
| }; | ||||
|  | ||||
| struct _MetaInputSettingsPrivate | ||||
| { | ||||
|   ClutterDeviceManager *device_manager; | ||||
|   MetaMonitorManager *monitor_manager; | ||||
|   guint monitors_changed_id; | ||||
|  | ||||
|   GSettings *mouse_settings; | ||||
|   GSettings *touchpad_settings; | ||||
|   GSettings *trackball_settings; | ||||
|   GSettings *keyboard_settings; | ||||
|  | ||||
|   GHashTable *mappable_devices; | ||||
| }; | ||||
|  | ||||
| typedef void (*ConfigBoolFunc)   (MetaInputSettings  *input_settings, | ||||
|                                   ClutterInputDevice *device, | ||||
|                                   gboolean            setting); | ||||
| typedef void (*ConfigDoubleFunc) (MetaInputSettings  *input_settings, | ||||
|                                   ClutterInputDevice *device, | ||||
|                                   gdouble             value); | ||||
| typedef void (*ConfigUintFunc)   (MetaInputSettings  *input_settings, | ||||
|                                   ClutterInputDevice *device, | ||||
|                                   guint               value); | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_PRIVATE (MetaInputSettings, meta_input_settings, G_TYPE_OBJECT) | ||||
|  | ||||
| static GSList * | ||||
| meta_input_settings_get_devices (MetaInputSettings      *settings, | ||||
|                                  ClutterInputDeviceType  type) | ||||
| { | ||||
|   MetaInputSettingsPrivate *priv; | ||||
|   const GSList *devices; | ||||
|   GSList *list = NULL; | ||||
|  | ||||
|   priv = meta_input_settings_get_instance_private (settings); | ||||
|   devices = clutter_device_manager_peek_devices (priv->device_manager); | ||||
|  | ||||
|   while (devices) | ||||
|     { | ||||
|       ClutterInputDevice *device = devices->data; | ||||
|  | ||||
|       if (clutter_input_device_get_device_type (device) == type && | ||||
|           clutter_input_device_get_device_mode (device) != CLUTTER_INPUT_MODE_MASTER) | ||||
|         list = g_slist_prepend (list, device); | ||||
|  | ||||
|       devices = devices->next; | ||||
|     } | ||||
|  | ||||
|   return list; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_settings_dispose (GObject *object) | ||||
| { | ||||
|   MetaInputSettings *settings = META_INPUT_SETTINGS (object); | ||||
|   MetaInputSettingsPrivate *priv = meta_input_settings_get_instance_private (settings); | ||||
|  | ||||
|   g_clear_object (&priv->mouse_settings); | ||||
|   g_clear_object (&priv->touchpad_settings); | ||||
|   g_clear_object (&priv->trackball_settings); | ||||
|   g_clear_object (&priv->keyboard_settings); | ||||
|   g_clear_pointer (&priv->mappable_devices, g_hash_table_unref); | ||||
|  | ||||
|   if (priv->monitors_changed_id && priv->monitor_manager) | ||||
|     { | ||||
|       g_signal_handler_disconnect (priv->monitor_manager, | ||||
|                                    priv->monitors_changed_id); | ||||
|       priv->monitors_changed_id = 0; | ||||
|     } | ||||
|  | ||||
|   g_clear_object (&priv->monitor_manager); | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_input_settings_parent_class)->dispose (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| settings_device_set_bool_setting (MetaInputSettings  *input_settings, | ||||
|                                   ClutterInputDevice *device, | ||||
|                                   ConfigBoolFunc      func, | ||||
|                                   gboolean            enabled) | ||||
| { | ||||
|   func (input_settings, device, enabled); | ||||
| } | ||||
|  | ||||
| static void | ||||
| settings_set_bool_setting (MetaInputSettings      *input_settings, | ||||
|                            ClutterInputDeviceType  type, | ||||
|                            ConfigBoolFunc          func, | ||||
|                            gboolean                enabled) | ||||
| { | ||||
|   GSList *devices, *d; | ||||
|  | ||||
|   devices = meta_input_settings_get_devices (input_settings, type); | ||||
|  | ||||
|   for (d = devices; d; d = d->next) | ||||
|     settings_device_set_bool_setting (input_settings, d->data, func, enabled); | ||||
|  | ||||
|   g_slist_free (devices); | ||||
| } | ||||
|  | ||||
| static void | ||||
| settings_device_set_double_setting (MetaInputSettings  *input_settings, | ||||
|                                     ClutterInputDevice *device, | ||||
|                                     ConfigDoubleFunc    func, | ||||
|                                     gdouble             value) | ||||
| { | ||||
|   func (input_settings, device, value); | ||||
| } | ||||
|  | ||||
| static void | ||||
| settings_set_double_setting (MetaInputSettings      *input_settings, | ||||
|                              ClutterInputDeviceType  type, | ||||
|                              ConfigDoubleFunc        func, | ||||
|                              gdouble                 value) | ||||
| { | ||||
|   GSList *devices, *d; | ||||
|  | ||||
|   devices = meta_input_settings_get_devices (input_settings, type); | ||||
|  | ||||
|   for (d = devices; d; d = d->next) | ||||
|     settings_device_set_double_setting (input_settings, d->data, func, value); | ||||
|  | ||||
|   g_slist_free (devices); | ||||
| } | ||||
|  | ||||
| static void | ||||
| settings_device_set_uint_setting (MetaInputSettings  *input_settings, | ||||
|                                   ClutterInputDevice *device, | ||||
|                                   ConfigUintFunc      func, | ||||
|                                   guint               value) | ||||
| { | ||||
|   (func) (input_settings, device, value); | ||||
| } | ||||
|  | ||||
| static void | ||||
| settings_set_uint_setting (MetaInputSettings      *input_settings, | ||||
|                            ClutterInputDeviceType  type, | ||||
|                            ConfigUintFunc          func, | ||||
|                            guint                   value) | ||||
| { | ||||
|   GSList *devices, *d; | ||||
|  | ||||
|   devices = meta_input_settings_get_devices (input_settings, type); | ||||
|  | ||||
|   for (d = devices; d; d = d->next) | ||||
|     settings_device_set_uint_setting (input_settings, d->data, func, value); | ||||
|  | ||||
|   g_slist_free (devices); | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_touchpad_left_handed (MetaInputSettings  *input_settings, | ||||
|                              ClutterInputDevice *device) | ||||
| { | ||||
|   MetaInputSettingsClass *input_settings_class; | ||||
|   GDesktopTouchpadHandedness handedness; | ||||
|   MetaInputSettingsPrivate *priv; | ||||
|   gboolean enabled = FALSE; | ||||
|  | ||||
|   if (device && | ||||
|       clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE) | ||||
|     return; | ||||
|  | ||||
|   priv = meta_input_settings_get_instance_private (input_settings); | ||||
|   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); | ||||
|   handedness = g_settings_get_enum (priv->touchpad_settings, "left-handed"); | ||||
|  | ||||
|   switch (handedness) | ||||
|     { | ||||
|     case G_DESKTOP_TOUCHPAD_HANDEDNESS_RIGHT: | ||||
|       enabled = FALSE; | ||||
|       break; | ||||
|     case G_DESKTOP_TOUCHPAD_HANDEDNESS_LEFT: | ||||
|       enabled = TRUE; | ||||
|       break; | ||||
|     case G_DESKTOP_TOUCHPAD_HANDEDNESS_MOUSE: | ||||
|       enabled = g_settings_get_boolean (priv->mouse_settings, "left-handed"); | ||||
|       break; | ||||
|     default: | ||||
|       g_assert_not_reached (); | ||||
|     } | ||||
|  | ||||
|   if (device) | ||||
|     { | ||||
|       settings_device_set_bool_setting (input_settings, device, | ||||
|                                         input_settings_class->set_left_handed, | ||||
|                                         enabled); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, | ||||
|                                  input_settings_class->set_left_handed, | ||||
|                                  enabled); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_mouse_left_handed (MetaInputSettings  *input_settings, | ||||
|                           ClutterInputDevice *device) | ||||
| { | ||||
|   MetaInputSettingsClass *input_settings_class; | ||||
|   MetaInputSettingsPrivate *priv; | ||||
|   gboolean enabled; | ||||
|  | ||||
|   if (device && | ||||
|       clutter_input_device_get_device_type (device) != CLUTTER_POINTER_DEVICE) | ||||
|     return; | ||||
|  | ||||
|   priv = meta_input_settings_get_instance_private (input_settings); | ||||
|   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); | ||||
|   enabled = g_settings_get_boolean (priv->mouse_settings, "left-handed"); | ||||
|  | ||||
|   if (device) | ||||
|     { | ||||
|       settings_device_set_bool_setting (input_settings, device, | ||||
|                                         input_settings_class->set_left_handed, | ||||
|                                         enabled); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       GDesktopTouchpadHandedness touchpad_handedness; | ||||
|  | ||||
|       settings_set_bool_setting (input_settings, CLUTTER_POINTER_DEVICE, | ||||
|                                  input_settings_class->set_left_handed, | ||||
|                                  enabled); | ||||
|  | ||||
|       touchpad_handedness = g_settings_get_enum (priv->touchpad_settings, | ||||
|                                                  "left-handed"); | ||||
|  | ||||
|       /* Also update touchpads if they're following mouse settings */ | ||||
|       if (touchpad_handedness == G_DESKTOP_TOUCHPAD_HANDEDNESS_MOUSE) | ||||
|         update_touchpad_left_handed (input_settings, NULL); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static GSettings * | ||||
| get_settings_for_device_type (MetaInputSettings      *input_settings, | ||||
|                               ClutterInputDeviceType  type) | ||||
| { | ||||
|   MetaInputSettingsPrivate *priv; | ||||
|   priv = meta_input_settings_get_instance_private (input_settings); | ||||
|   switch (type) | ||||
|     { | ||||
|     case CLUTTER_POINTER_DEVICE: | ||||
|       return priv->mouse_settings; | ||||
|     case CLUTTER_TOUCHPAD_DEVICE: | ||||
|       return priv->touchpad_settings; | ||||
|     default: | ||||
|       return NULL; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_device_speed (MetaInputSettings      *input_settings, | ||||
|                      ClutterInputDevice     *device) | ||||
| { | ||||
|   GSettings *settings; | ||||
|   ConfigDoubleFunc func; | ||||
|   const gchar *key = "speed"; | ||||
|  | ||||
|   func = META_INPUT_SETTINGS_GET_CLASS (input_settings)->set_speed; | ||||
|  | ||||
|   if (device) | ||||
|     { | ||||
|       settings = get_settings_for_device_type (input_settings, | ||||
|                                                clutter_input_device_get_device_type (device)); | ||||
|       if (!settings) | ||||
|         return; | ||||
|  | ||||
|       settings_device_set_double_setting (input_settings, device, func, | ||||
|                                           g_settings_get_double (settings, key)); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       settings = get_settings_for_device_type (input_settings, CLUTTER_POINTER_DEVICE); | ||||
|       settings_set_double_setting (input_settings, CLUTTER_POINTER_DEVICE, func, | ||||
|                                    g_settings_get_double (settings, key)); | ||||
|       settings = get_settings_for_device_type (input_settings, CLUTTER_TOUCHPAD_DEVICE); | ||||
|       settings_set_double_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, func, | ||||
|                                    g_settings_get_double (settings, key)); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_device_natural_scroll (MetaInputSettings      *input_settings, | ||||
|                               ClutterInputDevice     *device) | ||||
| { | ||||
|   GSettings *settings; | ||||
|   ConfigBoolFunc func; | ||||
|   const gchar *key = "natural-scroll"; | ||||
|  | ||||
|   func = META_INPUT_SETTINGS_GET_CLASS (input_settings)->set_invert_scroll; | ||||
|  | ||||
|   if (device) | ||||
|     { | ||||
|       settings = get_settings_for_device_type (input_settings, | ||||
|                                                clutter_input_device_get_device_type (device)); | ||||
|       if (!settings) | ||||
|         return; | ||||
|  | ||||
|       settings_device_set_bool_setting (input_settings, device, func, | ||||
|                                         g_settings_get_boolean (settings, key)); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       settings = get_settings_for_device_type (input_settings, CLUTTER_POINTER_DEVICE); | ||||
|       settings_set_bool_setting (input_settings, CLUTTER_POINTER_DEVICE, func, | ||||
|                                  g_settings_get_boolean (settings, key)); | ||||
|       settings = get_settings_for_device_type (input_settings, CLUTTER_TOUCHPAD_DEVICE); | ||||
|       settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, func, | ||||
|                                  g_settings_get_boolean (settings, key)); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_touchpad_tap_enabled (MetaInputSettings  *input_settings, | ||||
|                              ClutterInputDevice *device) | ||||
| { | ||||
|   MetaInputSettingsClass *input_settings_class; | ||||
|   MetaInputSettingsPrivate *priv; | ||||
|   gboolean enabled; | ||||
|  | ||||
|   if (device && | ||||
|       clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE) | ||||
|     return; | ||||
|  | ||||
|   priv = meta_input_settings_get_instance_private (input_settings); | ||||
|   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); | ||||
|   enabled = g_settings_get_boolean (priv->touchpad_settings, "tap-to-click"); | ||||
|  | ||||
|   if (device) | ||||
|     { | ||||
|       settings_device_set_bool_setting (input_settings, device, | ||||
|                                         input_settings_class->set_tap_enabled, | ||||
|                                         enabled); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, | ||||
|                                  input_settings_class->set_tap_enabled, | ||||
|                                  enabled); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_touchpad_edge_scroll (MetaInputSettings *input_settings, | ||||
|                              ClutterInputDevice *device) | ||||
| { | ||||
|   MetaInputSettingsClass *input_settings_class; | ||||
|   gboolean edge_scroll_enabled; | ||||
|   MetaInputSettingsPrivate *priv; | ||||
|  | ||||
|   if (device && | ||||
|       clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE) | ||||
|     return; | ||||
|  | ||||
|   priv = meta_input_settings_get_instance_private (input_settings); | ||||
|   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); | ||||
|   edge_scroll_enabled = g_settings_get_boolean (priv->touchpad_settings, "edge-scrolling-enabled"); | ||||
|  | ||||
|   if (device) | ||||
|     { | ||||
|       settings_device_set_bool_setting (input_settings, device, | ||||
|                                         input_settings_class->set_edge_scroll, | ||||
|                                         edge_scroll_enabled); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, | ||||
|                                  (ConfigBoolFunc) input_settings_class->set_edge_scroll, | ||||
|                                  edge_scroll_enabled); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_touchpad_click_method (MetaInputSettings *input_settings, | ||||
|                               ClutterInputDevice *device) | ||||
| { | ||||
|   MetaInputSettingsClass *input_settings_class; | ||||
|   GDesktopTouchpadClickMethod method; | ||||
|   MetaInputSettingsPrivate *priv; | ||||
|  | ||||
|   if (device && | ||||
|       clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE) | ||||
|     return; | ||||
|  | ||||
|   priv = meta_input_settings_get_instance_private (input_settings); | ||||
|   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); | ||||
|   method = g_settings_get_enum (priv->touchpad_settings, "click-method"); | ||||
|  | ||||
|   if (device) | ||||
|     { | ||||
|       settings_device_set_uint_setting (input_settings, device, | ||||
|                                         input_settings_class->set_click_method, | ||||
|                                         method); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       settings_set_uint_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, | ||||
|                                  (ConfigUintFunc) input_settings_class->set_click_method, | ||||
|                                  method); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_touchpad_send_events (MetaInputSettings  *input_settings, | ||||
|                              ClutterInputDevice *device) | ||||
| { | ||||
|   MetaInputSettingsClass *input_settings_class; | ||||
|   MetaInputSettingsPrivate *priv; | ||||
|   GDesktopDeviceSendEvents mode; | ||||
|  | ||||
|   if (device && | ||||
|       clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE) | ||||
|     return; | ||||
|  | ||||
|   priv = meta_input_settings_get_instance_private (input_settings); | ||||
|   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); | ||||
|   mode = g_settings_get_enum (priv->touchpad_settings, "send-events"); | ||||
|  | ||||
|   if (device) | ||||
|     { | ||||
|       settings_device_set_uint_setting (input_settings, device, | ||||
|                                         input_settings_class->set_send_events, | ||||
|                                         mode); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       settings_set_uint_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, | ||||
|                                  input_settings_class->set_send_events, | ||||
|                                  mode); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| device_is_trackball (ClutterInputDevice *device) | ||||
| { | ||||
|   gboolean is_trackball; | ||||
|   char *name; | ||||
|  | ||||
|   if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_MASTER) | ||||
|     return FALSE; | ||||
|  | ||||
|   name = g_ascii_strdown (clutter_input_device_get_device_name (device), -1); | ||||
|   is_trackball = strstr (name, "trackball") != NULL; | ||||
|   g_free (name); | ||||
|  | ||||
|   return is_trackball; | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_trackball_scroll_button (MetaInputSettings  *input_settings, | ||||
|                                 ClutterInputDevice *device) | ||||
| { | ||||
|   MetaInputSettingsClass *input_settings_class; | ||||
|   MetaInputSettingsPrivate *priv; | ||||
|   guint button; | ||||
|  | ||||
|   if (device && !device_is_trackball (device)) | ||||
|     return; | ||||
|  | ||||
|   priv = meta_input_settings_get_instance_private (input_settings); | ||||
|   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); | ||||
|   /* This key is 'i' in the schema but it also specifies a minimum | ||||
|    * range of 0 so the cast here is safe. */ | ||||
|   button = (guint) g_settings_get_int (priv->trackball_settings, "scroll-wheel-emulation-button"); | ||||
|  | ||||
|   if (device) | ||||
|     { | ||||
|       input_settings_class->set_scroll_button (input_settings, device, button); | ||||
|     } | ||||
|   else if (!device) | ||||
|     { | ||||
|       const GSList *devices; | ||||
|  | ||||
|       devices = clutter_device_manager_peek_devices (priv->device_manager); | ||||
|  | ||||
|       while (devices) | ||||
|         { | ||||
|           device = devices->data; | ||||
|  | ||||
|           if (device_is_trackball (device)) | ||||
|             input_settings_class->set_scroll_button (input_settings, device, button); | ||||
|  | ||||
|           devices = devices->next; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_keyboard_repeat (MetaInputSettings *input_settings) | ||||
| { | ||||
|   MetaInputSettingsClass *input_settings_class; | ||||
|   MetaInputSettingsPrivate *priv; | ||||
|   guint delay, interval; | ||||
|   gboolean repeat; | ||||
|  | ||||
|   priv = meta_input_settings_get_instance_private (input_settings); | ||||
|   repeat = g_settings_get_boolean (priv->keyboard_settings, "repeat"); | ||||
|   delay = g_settings_get_uint (priv->keyboard_settings, "delay"); | ||||
|   interval = g_settings_get_uint (priv->keyboard_settings, "repeat-interval"); | ||||
|  | ||||
|   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); | ||||
|   input_settings_class->set_keyboard_repeat (input_settings, | ||||
|                                              repeat, delay, interval); | ||||
| } | ||||
|  | ||||
| static MetaOutput * | ||||
| meta_input_settings_find_output (MetaInputSettings  *input_settings, | ||||
|                                  GSettings          *settings, | ||||
|                                  ClutterInputDevice *device) | ||||
| { | ||||
|   MetaInputSettingsPrivate *priv; | ||||
|   guint n_values, n_outputs, i; | ||||
|   MetaOutput *outputs; | ||||
|   gchar **edid; | ||||
|  | ||||
|   priv = meta_input_settings_get_instance_private (input_settings); | ||||
|   edid = g_settings_get_strv (settings, "display"); | ||||
|   n_values = g_strv_length (edid); | ||||
|  | ||||
|   if (n_values != 3) | ||||
|     { | ||||
|       g_warning ("EDID configuration for device '%s' " | ||||
|                  "is incorrect, must have 3 values", | ||||
|                  clutter_input_device_get_device_name (device)); | ||||
|       return NULL; | ||||
|     } | ||||
|  | ||||
|   if (!*edid[0] && !*edid[1] && !*edid[2]) | ||||
|     return NULL; | ||||
|  | ||||
|   outputs = meta_monitor_manager_get_outputs (priv->monitor_manager, | ||||
|                                               &n_outputs); | ||||
|   for (i = 0; i < n_outputs; i++) | ||||
|     { | ||||
|       if (g_strcmp0 (outputs[i].vendor, edid[0]) == 0 && | ||||
|           g_strcmp0 (outputs[i].product, edid[1]) == 0 && | ||||
|           g_strcmp0 (outputs[i].serial, edid[2]) == 0) | ||||
|         return &outputs[i]; | ||||
|     } | ||||
|  | ||||
|   return NULL; | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_device_display (MetaInputSettings  *input_settings, | ||||
|                        GSettings          *settings, | ||||
|                        ClutterInputDevice *device) | ||||
| { | ||||
|   MetaInputSettingsClass *input_settings_class; | ||||
|   MetaInputSettingsPrivate *priv; | ||||
|   gfloat matrix[6] = { 1, 0, 0, 0, 1, 0 }; | ||||
|   MetaOutput *output; | ||||
|  | ||||
|   priv = meta_input_settings_get_instance_private (input_settings); | ||||
|   input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); | ||||
|   output = meta_input_settings_find_output (input_settings, settings, device); | ||||
|  | ||||
|   if (output) | ||||
|     meta_monitor_manager_get_monitor_matrix (priv->monitor_manager, | ||||
|                                              output, matrix); | ||||
|  | ||||
|   input_settings_class->set_matrix (input_settings, device, matrix); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_settings_changed_cb (GSettings  *settings, | ||||
|                                 const char *key, | ||||
|                                 gpointer    user_data) | ||||
| { | ||||
|   MetaInputSettings *input_settings = META_INPUT_SETTINGS (user_data); | ||||
|   MetaInputSettingsPrivate *priv = meta_input_settings_get_instance_private (input_settings); | ||||
|  | ||||
|   if (settings == priv->mouse_settings) | ||||
|     { | ||||
|       if (strcmp (key, "left-handed") == 0) | ||||
|         update_mouse_left_handed (input_settings, NULL); | ||||
|       else if (strcmp (key, "speed") == 0) | ||||
|         update_device_speed (input_settings, NULL); | ||||
|       else if (strcmp (key, "natural-scroll") == 0) | ||||
|         update_device_natural_scroll (input_settings, NULL); | ||||
|     } | ||||
|   else if (settings == priv->touchpad_settings) | ||||
|     { | ||||
|       if (strcmp (key, "left-handed") == 0) | ||||
|         update_touchpad_left_handed (input_settings, NULL); | ||||
|       else if (strcmp (key, "speed") == 0) | ||||
|         update_device_speed (input_settings, NULL); | ||||
|       else if (strcmp (key, "natural-scroll") == 0) | ||||
|         update_device_natural_scroll (input_settings, NULL); | ||||
|       else if (strcmp (key, "tap-to-click") == 0) | ||||
|         update_touchpad_tap_enabled (input_settings, NULL); | ||||
|       else if (strcmp (key, "send-events") == 0) | ||||
|         update_touchpad_send_events (input_settings, NULL); | ||||
|       else if (strcmp (key, "edge-scrolling-enabled") == 0) | ||||
|         update_touchpad_edge_scroll (input_settings, NULL); | ||||
|       else if (strcmp (key, "click-method") == 0) | ||||
|         update_touchpad_click_method (input_settings, NULL); | ||||
|     } | ||||
|   else if (settings == priv->trackball_settings) | ||||
|     { | ||||
|       if (strcmp (key, "scroll-wheel-emulation-button") == 0) | ||||
|         update_trackball_scroll_button (input_settings, NULL); | ||||
|     } | ||||
|   else if (settings == priv->keyboard_settings) | ||||
|     { | ||||
|       if (strcmp (key, "repeat") == 0 || | ||||
|           strcmp (key, "repeat-interval") == 0 || | ||||
|           strcmp (key, "delay") == 0) | ||||
|         update_keyboard_repeat (input_settings); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| mapped_device_changed_cb (GSettings         *settings, | ||||
|                           const gchar       *key, | ||||
|                           DeviceMappingInfo *info) | ||||
| { | ||||
|   if (strcmp (key, "display") == 0) | ||||
|     update_device_display (info->input_settings, settings, info->device); | ||||
| } | ||||
|  | ||||
| static GSettings * | ||||
| lookup_device_settings (ClutterInputDevice *device) | ||||
| { | ||||
|   const gchar *group, *schema, *vendor, *product; | ||||
|   ClutterInputDeviceType type; | ||||
|   GSettings *settings; | ||||
|   gchar *path; | ||||
|  | ||||
|   type = clutter_input_device_get_device_type (device); | ||||
|  | ||||
|   if (type == CLUTTER_TOUCHSCREEN_DEVICE) | ||||
|     { | ||||
|       group = "touchscreens"; | ||||
|       schema = "org.gnome.desktop.peripherals.touchscreen"; | ||||
|     } | ||||
|   else if (type == CLUTTER_TABLET_DEVICE || | ||||
|            type == CLUTTER_PEN_DEVICE || | ||||
|            type == CLUTTER_ERASER_DEVICE || | ||||
|            type == CLUTTER_CURSOR_DEVICE) | ||||
|     { | ||||
|       group = "tablets"; | ||||
|       schema = "org.gnome.desktop.peripherals.tablet"; | ||||
|     } | ||||
|   else | ||||
|     return NULL; | ||||
|  | ||||
|   vendor = clutter_input_device_get_vendor_id (device); | ||||
|   product = clutter_input_device_get_product_id (device); | ||||
|   path = g_strdup_printf ("/org/gnome/desktop/peripherals/%s/%s:%s/", | ||||
|                           group, vendor, product); | ||||
|  | ||||
|   settings = g_settings_new_with_path (schema, path); | ||||
|   g_free (path); | ||||
|  | ||||
|   return settings; | ||||
| } | ||||
|  | ||||
| static void | ||||
| monitors_changed_cb (MetaMonitorManager *monitor_manager, | ||||
|                      MetaInputSettings  *input_settings) | ||||
| { | ||||
|   MetaInputSettingsPrivate *priv; | ||||
|   ClutterInputDevice *device; | ||||
|   GSettings *settings; | ||||
|   GHashTableIter iter; | ||||
|  | ||||
|   priv = meta_input_settings_get_instance_private (input_settings); | ||||
|   g_hash_table_iter_init (&iter, priv->mappable_devices); | ||||
|  | ||||
|   while (g_hash_table_iter_next (&iter, (gpointer *) &device, | ||||
|                                  (gpointer *) &settings)) | ||||
|     update_device_display (input_settings, settings, device); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| check_add_mappable_device (MetaInputSettings  *input_settings, | ||||
|                            ClutterInputDevice *device) | ||||
| { | ||||
|   MetaInputSettingsPrivate *priv; | ||||
|   DeviceMappingInfo *info; | ||||
|   GSettings *settings; | ||||
|  | ||||
|   settings = lookup_device_settings (device); | ||||
|  | ||||
|   if (!settings) | ||||
|     return FALSE; | ||||
|  | ||||
|   priv = meta_input_settings_get_instance_private (input_settings); | ||||
|  | ||||
|   info = g_new0 (DeviceMappingInfo, 1); | ||||
|   info->input_settings = input_settings; | ||||
|   info->device = device; | ||||
|   info->settings = settings; | ||||
|  | ||||
|   g_signal_connect_data (settings, "changed", | ||||
|                          G_CALLBACK (mapped_device_changed_cb), | ||||
|                          info, (GClosureNotify) g_free, 0); | ||||
|  | ||||
|   g_hash_table_insert (priv->mappable_devices, device, settings); | ||||
|  | ||||
|   update_device_display (input_settings, settings, device); | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| apply_device_settings (MetaInputSettings  *input_settings, | ||||
|                        ClutterInputDevice *device) | ||||
| { | ||||
|   update_mouse_left_handed (input_settings, device); | ||||
|   update_device_speed (input_settings, device); | ||||
|   update_device_natural_scroll (input_settings, device); | ||||
|  | ||||
|   update_touchpad_left_handed (input_settings, device); | ||||
|   update_device_speed (input_settings, device); | ||||
|   update_device_natural_scroll (input_settings, device); | ||||
|   update_touchpad_tap_enabled (input_settings, device); | ||||
|   update_touchpad_send_events (input_settings, device); | ||||
|   update_touchpad_edge_scroll (input_settings, device); | ||||
|   update_touchpad_click_method (input_settings, device); | ||||
|  | ||||
|   update_trackball_scroll_button (input_settings, device); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_settings_device_added (ClutterDeviceManager *device_manager, | ||||
|                                   ClutterInputDevice   *device, | ||||
|                                   MetaInputSettings    *input_settings) | ||||
| { | ||||
|   if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_MASTER) | ||||
|     return; | ||||
|  | ||||
|   apply_device_settings (input_settings, device); | ||||
|   check_add_mappable_device (input_settings, device); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_settings_device_removed (ClutterDeviceManager *device_manager, | ||||
|                                     ClutterInputDevice   *device, | ||||
|                                     MetaInputSettings    *input_settings) | ||||
| { | ||||
|   MetaInputSettingsPrivate *priv; | ||||
|  | ||||
|   priv = meta_input_settings_get_instance_private (input_settings); | ||||
|   g_hash_table_remove (priv->mappable_devices, device); | ||||
| } | ||||
|  | ||||
| static void | ||||
| check_mappable_devices (MetaInputSettings *input_settings) | ||||
| { | ||||
|   MetaInputSettingsPrivate *priv; | ||||
|   const GSList *devices, *l; | ||||
|  | ||||
|   priv = meta_input_settings_get_instance_private (input_settings); | ||||
|   devices = clutter_device_manager_peek_devices (priv->device_manager); | ||||
|  | ||||
|   for (l = devices; l; l = l->next) | ||||
|     { | ||||
|       ClutterInputDevice *device = l->data; | ||||
|  | ||||
|       if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_MASTER) | ||||
|         continue; | ||||
|  | ||||
|       check_add_mappable_device (input_settings, device); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_settings_constructed (GObject *object) | ||||
| { | ||||
|   MetaInputSettings *input_settings = META_INPUT_SETTINGS (object); | ||||
|  | ||||
|   apply_device_settings (input_settings, NULL); | ||||
|   update_keyboard_repeat (input_settings); | ||||
|   check_mappable_devices (input_settings); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_settings_class_init (MetaInputSettingsClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|  | ||||
|   object_class->dispose = meta_input_settings_dispose; | ||||
|   object_class->constructed = meta_input_settings_constructed; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_settings_init (MetaInputSettings *settings) | ||||
| { | ||||
|   MetaInputSettingsPrivate *priv; | ||||
|  | ||||
|   priv = meta_input_settings_get_instance_private (settings); | ||||
|   priv->device_manager = clutter_device_manager_get_default (); | ||||
|   g_signal_connect (priv->device_manager, "device-added", | ||||
|                     G_CALLBACK (meta_input_settings_device_added), settings); | ||||
|   g_signal_connect (priv->device_manager, "device-removed", | ||||
|                     G_CALLBACK (meta_input_settings_device_removed), settings); | ||||
|  | ||||
|   priv->mouse_settings = g_settings_new ("org.gnome.desktop.peripherals.mouse"); | ||||
|   g_signal_connect (priv->mouse_settings, "changed", | ||||
|                     G_CALLBACK (meta_input_settings_changed_cb), settings); | ||||
|  | ||||
|   priv->touchpad_settings = g_settings_new ("org.gnome.desktop.peripherals.touchpad"); | ||||
|   g_signal_connect (priv->touchpad_settings, "changed", | ||||
|                     G_CALLBACK (meta_input_settings_changed_cb), settings); | ||||
|  | ||||
|   priv->trackball_settings = g_settings_new ("org.gnome.desktop.peripherals.trackball"); | ||||
|   g_signal_connect (priv->trackball_settings, "changed", | ||||
|                     G_CALLBACK (meta_input_settings_changed_cb), settings); | ||||
|  | ||||
|   priv->keyboard_settings = g_settings_new ("org.gnome.desktop.peripherals.keyboard"); | ||||
|   g_signal_connect (priv->keyboard_settings, "changed", | ||||
|                     G_CALLBACK (meta_input_settings_changed_cb), settings); | ||||
|  | ||||
|   priv->mappable_devices = | ||||
|     g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) g_object_unref); | ||||
|  | ||||
|   priv->monitor_manager = g_object_ref (meta_monitor_manager_get ()); | ||||
|   g_signal_connect (priv->monitor_manager, "monitors-changed", | ||||
|                     G_CALLBACK (monitors_changed_cb), settings); | ||||
| } | ||||
|  | ||||
| MetaInputSettings * | ||||
| meta_input_settings_create (void) | ||||
| { | ||||
| #ifdef HAVE_NATIVE_BACKEND | ||||
|   MetaBackend *backend; | ||||
|  | ||||
|   backend = meta_get_backend (); | ||||
|  | ||||
|   if (META_IS_BACKEND_NATIVE (backend)) | ||||
|     return g_object_new (META_TYPE_INPUT_SETTINGS_NATIVE, NULL); | ||||
| #endif | ||||
|   if (!meta_is_wayland_compositor ()) | ||||
|     return g_object_new (META_TYPE_INPUT_SETTINGS_X11, NULL); | ||||
|  | ||||
|   return NULL; | ||||
| } | ||||
| @@ -34,6 +34,7 @@ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include "boxes-private.h" | ||||
| #include "meta-monitor-config.h" | ||||
|  | ||||
| #include <string.h> | ||||
| @@ -64,9 +65,11 @@ typedef struct { | ||||
|  | ||||
|   gboolean is_primary; | ||||
|   gboolean is_presentation; | ||||
|   gboolean is_underscanning; | ||||
| } MetaOutputConfig; | ||||
|  | ||||
| typedef struct { | ||||
|   guint refcount; | ||||
|   MetaOutputKey *keys; | ||||
|   MetaOutputConfig *outputs; | ||||
|   unsigned int n_outputs; | ||||
| @@ -77,11 +80,11 @@ struct _MetaMonitorConfig { | ||||
|  | ||||
|   GHashTable *configs; | ||||
|   MetaConfiguration *current; | ||||
|   gboolean current_is_stored; | ||||
|   gboolean current_is_for_laptop_lid; | ||||
|   MetaConfiguration *previous; | ||||
|  | ||||
|   GFile *file; | ||||
|   GFile *user_file; | ||||
|   GFile *system_file; | ||||
|   GCancellable *save_cancellable; | ||||
|  | ||||
|   UpClient *up_client; | ||||
| @@ -124,11 +127,29 @@ config_clear (MetaConfiguration *config) | ||||
|   g_free (config->outputs); | ||||
| } | ||||
|  | ||||
| static void | ||||
| config_free (gpointer config) | ||||
| static MetaConfiguration * | ||||
| config_ref (MetaConfiguration *config) | ||||
| { | ||||
|   config_clear (config); | ||||
|   g_slice_free (MetaConfiguration, config); | ||||
|   config->refcount++; | ||||
|   return config; | ||||
| } | ||||
|  | ||||
| static void | ||||
| config_unref (MetaConfiguration *config) | ||||
| { | ||||
|   if (--config->refcount == 0) | ||||
|     { | ||||
|       config_clear (config); | ||||
|       g_slice_free (MetaConfiguration, config); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static MetaConfiguration * | ||||
| config_new (void) | ||||
| { | ||||
|   MetaConfiguration *config = g_slice_new0 (MetaConfiguration); | ||||
|   config->refcount = 1; | ||||
|   return config; | ||||
| } | ||||
|  | ||||
| static unsigned long | ||||
| @@ -219,17 +240,26 @@ meta_monitor_config_init (MetaMonitorConfig *self) | ||||
| { | ||||
|   const char *filename; | ||||
|   char *path; | ||||
|   const char * const *system_dirs; | ||||
|  | ||||
|   self->configs = g_hash_table_new_full (config_hash, config_equal, NULL, config_free); | ||||
|   self->configs = g_hash_table_new_full (config_hash, config_equal, NULL, (GDestroyNotify) config_unref); | ||||
|  | ||||
|   filename = g_getenv ("MUTTER_MONITOR_FILENAME"); | ||||
|   if (filename == NULL) | ||||
|     filename = "monitors.xml"; | ||||
|  | ||||
|   path = g_build_filename (g_get_user_config_dir (), filename, NULL); | ||||
|   self->file = g_file_new_for_path (path); | ||||
|   self->user_file = g_file_new_for_path (path); | ||||
|   g_free (path); | ||||
|  | ||||
|   for (system_dirs = g_get_system_config_dirs (); !self->system_file && *system_dirs; system_dirs++) | ||||
|     { | ||||
|       path = g_build_filename (*system_dirs, filename, NULL); | ||||
|       if (g_file_test (path, G_FILE_TEST_EXISTS)) | ||||
|         self->system_file = g_file_new_for_path (path); | ||||
|       g_free (path); | ||||
|     } | ||||
|  | ||||
|   self->up_client = up_client_new (); | ||||
|   self->lid_is_closed = up_client_get_lid_is_closed (self->up_client); | ||||
|  | ||||
| @@ -374,7 +404,8 @@ handle_start_element (GMarkupParseContext  *context, | ||||
|              strcmp (element_name, "reflect_x") == 0 || | ||||
|              strcmp (element_name, "reflect_y") == 0 || | ||||
|              strcmp (element_name, "primary") == 0 || | ||||
|              strcmp (element_name, "presentation") == 0) && parser->unknown_count == 0) | ||||
|              strcmp (element_name, "presentation") == 0 || | ||||
|              strcmp (element_name, "underscanning") == 0) && parser->unknown_count == 0) | ||||
|           { | ||||
|             parser->state = STATE_OUTPUT_FIELD; | ||||
|  | ||||
| @@ -458,8 +489,8 @@ handle_end_element (GMarkupParseContext  *context, | ||||
|               } | ||||
|             else | ||||
|               { | ||||
|                 if (parser->output.rect.width == 0 && | ||||
|                     parser->output.rect.width == 0) | ||||
|                 if (parser->output.rect.width == 0 || | ||||
|                     parser->output.rect.height == 0) | ||||
|                   parser->output.enabled = FALSE; | ||||
|                 else | ||||
|                   parser->output.enabled = TRUE; | ||||
| @@ -681,6 +712,8 @@ handle_text (GMarkupParseContext *context, | ||||
|           parser->output.is_primary = read_bool (text, text_len, error); | ||||
|         else if (strcmp (parser->output_field, "presentation") == 0) | ||||
|           parser->output.is_presentation = read_bool (text, text_len, error); | ||||
|         else if (strcmp (parser->output_field, "underscanning") == 0) | ||||
|           parser->output.is_underscanning = read_bool (text, text_len, error); | ||||
|         else | ||||
|           g_assert_not_reached (); | ||||
|         return; | ||||
| @@ -698,8 +731,8 @@ static const GMarkupParser config_parser = { | ||||
|   .text = handle_text, | ||||
| }; | ||||
|  | ||||
| static void | ||||
| meta_monitor_config_load (MetaMonitorConfig  *self) | ||||
| static gboolean | ||||
| load_config_file (MetaMonitorConfig *self, GFile *file) | ||||
| { | ||||
|   char *contents; | ||||
|   gsize size; | ||||
| @@ -717,14 +750,12 @@ meta_monitor_config_load (MetaMonitorConfig  *self) | ||||
|   */ | ||||
|  | ||||
|   error = NULL; | ||||
|   ok = g_file_load_contents (self->file, NULL, &contents, &size, NULL, &error); | ||||
|   ok = g_file_load_contents (file, NULL, &contents, &size, NULL, &error); | ||||
|   if (!ok) | ||||
|     { | ||||
|       if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) | ||||
|         meta_warning ("Failed to load stored monitor configuration: %s\n", error->message); | ||||
|  | ||||
|       g_error_free (error); | ||||
|       return; | ||||
|       return FALSE; | ||||
|     } | ||||
|  | ||||
|   memset (&parser, 0, sizeof (ConfigParser)); | ||||
| @@ -753,6 +784,17 @@ meta_monitor_config_load (MetaMonitorConfig  *self) | ||||
|  | ||||
|   g_markup_parse_context_free (context); | ||||
|   g_free (contents); | ||||
|  | ||||
|   return ok; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_monitor_config_load (MetaMonitorConfig *self) | ||||
| { | ||||
|   if (self->user_file && load_config_file (self, self->user_file)) | ||||
|     return; | ||||
|   if (self->system_file && load_config_file (self, self->system_file)) | ||||
|     return; | ||||
| } | ||||
|  | ||||
| MetaMonitorConfig * | ||||
| @@ -830,72 +872,39 @@ meta_monitor_config_get_stored (MetaMonitorConfig *self, | ||||
|   return stored; | ||||
| } | ||||
|  | ||||
| static void | ||||
| set_current (MetaMonitorConfig *self, | ||||
|              MetaConfiguration *config) | ||||
| { | ||||
|   g_clear_pointer (&self->previous, (GDestroyNotify) config_unref); | ||||
|   self->previous = self->current; | ||||
|   self->current = config_ref (config); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| apply_configuration (MetaMonitorConfig  *self, | ||||
|                      MetaConfiguration  *config, | ||||
| 		     MetaMonitorManager *manager, | ||||
|                      gboolean            stored) | ||||
| 		     MetaMonitorManager *manager) | ||||
| { | ||||
|   GPtrArray *crtcs, *outputs; | ||||
|   g_autoptr(GPtrArray) crtcs = NULL; | ||||
|   g_autoptr(GPtrArray) outputs = NULL; | ||||
|  | ||||
|   crtcs = g_ptr_array_new_full (config->n_outputs, (GDestroyNotify)meta_crtc_info_free); | ||||
|   outputs = g_ptr_array_new_full (config->n_outputs, (GDestroyNotify)meta_output_info_free); | ||||
|  | ||||
|   if (!meta_monitor_config_assign_crtcs (config, manager, crtcs, outputs)) | ||||
|     { | ||||
|       g_ptr_array_unref (crtcs); | ||||
|       g_ptr_array_unref (outputs); | ||||
|       if (!stored) | ||||
|         config_free (config); | ||||
|  | ||||
|       return FALSE; | ||||
|     } | ||||
|     return FALSE; | ||||
|  | ||||
|   meta_monitor_manager_apply_configuration (manager, | ||||
|                                             (MetaCRTCInfo**)crtcs->pdata, crtcs->len, | ||||
|                                             (MetaOutputInfo**)outputs->pdata, outputs->len); | ||||
|  | ||||
|   /* Stored (persistent) configurations override the previous one always. | ||||
|      Also, we clear the previous configuration if the current one (which is | ||||
|      about to become previous) is stored, or if the current one has | ||||
|      different outputs. | ||||
|   */ | ||||
|   if (stored || | ||||
|       (self->current && self->current_is_stored)) | ||||
|     { | ||||
|       if (self->previous) | ||||
|         config_free (self->previous); | ||||
|       self->previous = NULL; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       /* Despite the name, config_equal() only checks the set of outputs, | ||||
|          not their modes | ||||
|       */ | ||||
|       if (self->current && config_equal (self->current, config)) | ||||
|         { | ||||
|           self->previous = self->current; | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           if (self->current) | ||||
|             config_free (self->current); | ||||
|           self->previous = NULL; | ||||
|         } | ||||
|     } | ||||
|   set_current (self, config); | ||||
|  | ||||
|   self->current = config; | ||||
|   self->current_is_stored = stored; | ||||
|   /* If true, we'll be overridden at the end of this call | ||||
|      inside turn_off_laptop_display() | ||||
|   */ | ||||
|    * inside turn_off_laptop_display / apply_configuration_with_lid */ | ||||
|   self->current_is_for_laptop_lid = FALSE; | ||||
|  | ||||
|   if (self->current == self->previous) | ||||
|     self->previous = NULL; | ||||
|  | ||||
|   g_ptr_array_unref (crtcs); | ||||
|   g_ptr_array_unref (outputs); | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| @@ -907,6 +916,20 @@ key_is_laptop (MetaOutputKey *key) | ||||
|     g_str_has_prefix (key->connector, "eDP"); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| output_is_laptop (MetaOutput *output) | ||||
| { | ||||
|   /* FIXME: extend with better heuristics */ | ||||
|   switch (output->connector_type) | ||||
|     { | ||||
|     case META_CONNECTOR_TYPE_eDP: | ||||
|     case META_CONNECTOR_TYPE_LVDS: | ||||
|       return TRUE; | ||||
|     default: | ||||
|       return FALSE; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| laptop_display_is_on (MetaConfiguration *config) | ||||
| { | ||||
| @@ -948,7 +971,7 @@ make_laptop_lid_config (MetaConfiguration  *reference) | ||||
|  | ||||
|   g_assert (multiple_outputs_are_enabled (reference)); | ||||
|  | ||||
|   new = g_slice_new0 (MetaConfiguration); | ||||
|   new = config_new (); | ||||
|   new->n_outputs = reference->n_outputs; | ||||
|   new->keys = g_new0 (MetaOutputKey, reference->n_outputs); | ||||
|   new->outputs = g_new0 (MetaOutputConfig, reference->n_outputs); | ||||
| @@ -965,8 +988,7 @@ make_laptop_lid_config (MetaConfiguration  *reference) | ||||
|       new->keys[i].product = g_strdup (current_key->product); | ||||
|       new->keys[i].serial = g_strdup (current_key->serial); | ||||
|  | ||||
|       if (g_str_has_prefix (current_key->connector, "LVDS") || | ||||
|           g_str_has_prefix (current_key->connector, "eDP")) | ||||
|       if (key_is_laptop (current_key)) | ||||
|         { | ||||
|           new->outputs[i].enabled = FALSE; | ||||
|           x_after = current_output->rect.x; | ||||
| @@ -1003,6 +1025,32 @@ make_laptop_lid_config (MetaConfiguration  *reference) | ||||
|   return new; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| apply_configuration_with_lid (MetaMonitorConfig  *self, | ||||
|                               MetaConfiguration  *config, | ||||
|                               MetaMonitorManager *manager) | ||||
| { | ||||
|   if (self->lid_is_closed && | ||||
|       multiple_outputs_are_enabled (config) && | ||||
|       laptop_display_is_on (config)) | ||||
|     { | ||||
|       MetaConfiguration *laptop_lid_config = make_laptop_lid_config (config); | ||||
|       if (apply_configuration (self, laptop_lid_config, manager)) | ||||
|         { | ||||
|           self->current_is_for_laptop_lid = TRUE; | ||||
|           config_unref (laptop_lid_config); | ||||
|           return TRUE; | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           config_unref (laptop_lid_config); | ||||
|           return FALSE; | ||||
|         } | ||||
|     } | ||||
|   else | ||||
|     return apply_configuration (self, config, manager); | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_monitor_config_apply_stored (MetaMonitorConfig  *self, | ||||
| 				  MetaMonitorManager *manager) | ||||
| @@ -1015,23 +1063,7 @@ meta_monitor_config_apply_stored (MetaMonitorConfig  *self, | ||||
|   stored = meta_monitor_config_get_stored (self, outputs, n_outputs); | ||||
|  | ||||
|   if (stored) | ||||
|     { | ||||
|       if (self->lid_is_closed && | ||||
|           multiple_outputs_are_enabled (stored) && | ||||
|           laptop_display_is_on (stored)) | ||||
|         { | ||||
|           if (apply_configuration (self, make_laptop_lid_config (stored), | ||||
|                                    manager, FALSE)) | ||||
|             { | ||||
|               self->current_is_for_laptop_lid = TRUE; | ||||
|               return TRUE; | ||||
|             } | ||||
|           else | ||||
|             return FALSE; | ||||
|         } | ||||
|       else | ||||
|         return apply_configuration (self, stored, manager, TRUE); | ||||
|     } | ||||
|     return apply_configuration_with_lid (self, stored, manager); | ||||
|   else | ||||
|     return FALSE; | ||||
| } | ||||
| @@ -1042,12 +1074,12 @@ meta_monitor_config_apply_stored (MetaMonitorConfig  *self, | ||||
|  * which are internal monitors), or failing that, the one with the | ||||
|  * best resolution | ||||
|  */ | ||||
| static MetaOutput * | ||||
| static int | ||||
| find_primary_output (MetaOutput *outputs, | ||||
|                      unsigned    n_outputs) | ||||
| { | ||||
|   unsigned i; | ||||
|   MetaOutput *best; | ||||
|   int best; | ||||
|   int best_width, best_height; | ||||
|  | ||||
|   g_assert (n_outputs >= 1); | ||||
| @@ -1055,24 +1087,23 @@ find_primary_output (MetaOutput *outputs, | ||||
|   for (i = 0; i < n_outputs; i++) | ||||
|     { | ||||
|       if (outputs[i].is_primary) | ||||
|         return &outputs[i]; | ||||
|         return i; | ||||
|     } | ||||
|  | ||||
|   for (i = 0; i < n_outputs; i++) | ||||
|     { | ||||
|       if (g_str_has_prefix (outputs[i].name, "LVDS") || | ||||
|           g_str_has_prefix (outputs[i].name, "eDP")) | ||||
|         return &outputs[i]; | ||||
|       if (output_is_laptop (&outputs[i])) | ||||
|         return i; | ||||
|     } | ||||
|  | ||||
|   best = NULL; | ||||
|   best = -1; | ||||
|   best_width = 0; best_height = 0; | ||||
|   for (i = 0; i < n_outputs; i++) | ||||
|     { | ||||
|       if (outputs[i].preferred_mode->width * outputs[i].preferred_mode->height > | ||||
|           best_width * best_height) | ||||
|         { | ||||
|           best = &outputs[i]; | ||||
|           best = i; | ||||
|           best_width = outputs[i].preferred_mode->width; | ||||
|           best_height = outputs[i].preferred_mode->height; | ||||
|         } | ||||
| @@ -1081,47 +1112,208 @@ find_primary_output (MetaOutput *outputs, | ||||
|   return best; | ||||
| } | ||||
|  | ||||
| static MetaConfiguration * | ||||
| make_default_config (MetaMonitorConfig *self, | ||||
|                      MetaOutput        *outputs, | ||||
|                      unsigned           n_outputs, | ||||
|                      int                max_width, | ||||
|                      int                max_height) | ||||
| static void | ||||
| init_config_from_preferred_mode (MetaOutputConfig *config, | ||||
|                                  MetaOutput *output) | ||||
| { | ||||
|   unsigned i, j; | ||||
|   int x, y; | ||||
|   MetaConfiguration *ret; | ||||
|   MetaOutput *primary; | ||||
|   config->enabled = TRUE; | ||||
|   config->rect.x = 0; | ||||
|   config->rect.y = 0; | ||||
|   config->rect.width = output->preferred_mode->width; | ||||
|   config->rect.height = output->preferred_mode->height; | ||||
|   config->refresh_rate = output->preferred_mode->refresh_rate; | ||||
|   config->transform = META_MONITOR_TRANSFORM_NORMAL; | ||||
|   config->is_primary = FALSE; | ||||
|   config->is_presentation = FALSE; | ||||
| } | ||||
|  | ||||
|   ret = g_slice_new (MetaConfiguration); | ||||
|   make_config_key (ret, outputs, n_outputs, -1); | ||||
|   ret->outputs = g_new0 (MetaOutputConfig, n_outputs); | ||||
| /* This function handles configuring the outputs when the driver provides a | ||||
|  * suggested layout position for each output. This is done in recent versions | ||||
|  * of qxl and allows displays to be aligned on the guest in the same order as | ||||
|  * they are aligned on the client. | ||||
|  */ | ||||
| static gboolean | ||||
| make_suggested_config (MetaMonitorConfig *self, | ||||
|                        MetaOutput        *outputs, | ||||
|                        unsigned           n_outputs, | ||||
|                        int                max_width, | ||||
|                        int                max_height, | ||||
|                        MetaConfiguration *config) | ||||
| { | ||||
|   unsigned int i; | ||||
|   int primary; | ||||
|   GList *region = NULL; | ||||
|  | ||||
|   /* Special case the simple case: one output, primary at preferred mode, | ||||
|      nothing else to do */ | ||||
|   if (n_outputs == 1) | ||||
|   g_return_val_if_fail (config != NULL, FALSE); | ||||
|   primary = find_primary_output (outputs, n_outputs); | ||||
|  | ||||
|   for (i = 0; i < n_outputs; i++) | ||||
|     { | ||||
|       ret->outputs[0].enabled = TRUE; | ||||
|       ret->outputs[0].rect.x = 0; | ||||
|       ret->outputs[0].rect.y = 0; | ||||
|       ret->outputs[0].rect.width = outputs[0].preferred_mode->width; | ||||
|       ret->outputs[0].rect.height = outputs[0].preferred_mode->height; | ||||
|       ret->outputs[0].refresh_rate = outputs[0].preferred_mode->refresh_rate; | ||||
|       ret->outputs[0].transform = META_MONITOR_TRANSFORM_NORMAL; | ||||
|       ret->outputs[0].is_primary = TRUE; | ||||
|       gboolean is_primary = ((int)i == primary); | ||||
|  | ||||
|       return ret; | ||||
|       if (outputs[i].suggested_x < 0 || outputs[i].suggested_y < 0) | ||||
|           return FALSE; | ||||
|  | ||||
|       init_config_from_preferred_mode (&config->outputs[i], &outputs[i]); | ||||
|       config->outputs[i].is_primary = is_primary; | ||||
|  | ||||
|       config->outputs[i].rect.x = outputs[i].suggested_x; | ||||
|       config->outputs[i].rect.y = outputs[i].suggested_y; | ||||
|  | ||||
|       /* Reject the configuration if the suggested positions result in | ||||
|        * overlapping displays */ | ||||
|       if (meta_rectangle_overlaps_with_region (region, &config->outputs[i].rect)) | ||||
|         { | ||||
|           g_warning ("Overlapping outputs, rejecting suggested configuration"); | ||||
|           g_list_free (region); | ||||
|           return FALSE; | ||||
|         } | ||||
|  | ||||
|       region = g_list_prepend (region, &config->outputs[i].rect); | ||||
|     } | ||||
|  | ||||
|   /* If we reach this point, this is either the first time mutter runs | ||||
|      on this system ever, or we just hotplugged a new screen. | ||||
|      In the latter case, search for a configuration that includes one | ||||
|      less screen, then add the new one as a presentation screen | ||||
|      in preferred mode. | ||||
|   g_list_free (region); | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
|      XXX: but presentation mode is not implemented in the control-center | ||||
|      or in mutter core, so let's do extended for now. | ||||
| static void | ||||
| config_one_untiled_output (MetaOutput *outputs, | ||||
|                            MetaConfiguration *config, | ||||
|                            int idx, gboolean is_primary, | ||||
|                            int *x, unsigned long *output_configured_bitmap) | ||||
| { | ||||
|   MetaOutput *output = &outputs[idx]; | ||||
|  | ||||
|   if (*output_configured_bitmap & (1 << idx)) | ||||
|     return; | ||||
|  | ||||
|   init_config_from_preferred_mode (&config->outputs[idx], output); | ||||
|   config->outputs[idx].is_primary = is_primary; | ||||
|   config->outputs[idx].rect.x = *x; | ||||
|   *x += config->outputs[idx].rect.width; | ||||
|   *output_configured_bitmap |= (1 << idx); | ||||
| } | ||||
|  | ||||
| static void | ||||
| config_one_tiled_group (MetaOutput *outputs, | ||||
|                         MetaConfiguration *config, | ||||
|                         int base_idx, gboolean is_primary, | ||||
|                         int n_outputs, | ||||
|                         int *x, unsigned long *output_configured_bitmap) | ||||
| { | ||||
|   guint32 num_h_tile, num_v_tile, ht, vt; | ||||
|   int j; | ||||
|   int cur_x, cur_y, addx = 0; | ||||
|  | ||||
|   if (*output_configured_bitmap & (1 << base_idx)) | ||||
|       return; | ||||
|  | ||||
|   if (outputs[base_idx].tile_info.group_id == 0) | ||||
|     return; | ||||
|  | ||||
|   cur_x = cur_y = 0; | ||||
|   num_h_tile = outputs[base_idx].tile_info.max_h_tiles; | ||||
|   num_v_tile = outputs[base_idx].tile_info.max_v_tiles; | ||||
|  | ||||
|   /* iterate over horizontal tiles */ | ||||
|   cur_x = *x; | ||||
|   for (ht = 0; ht < num_h_tile; ht++) | ||||
|     { | ||||
|       cur_y = 0; | ||||
|       addx = 0; | ||||
|       for (vt = 0; vt < num_v_tile; vt++) | ||||
|         { | ||||
|           for (j = 0; j < n_outputs; j++) | ||||
|             { | ||||
|               if (outputs[j].tile_info.group_id != outputs[base_idx].tile_info.group_id) | ||||
|                 continue; | ||||
|  | ||||
|               if (outputs[j].tile_info.loc_h_tile != ht || | ||||
|                   outputs[j].tile_info.loc_v_tile != vt) | ||||
|                 continue; | ||||
|  | ||||
|               if (ht == 0 && vt == 0 && is_primary) | ||||
|                 config->outputs[j].is_primary = TRUE; | ||||
|  | ||||
|               init_config_from_preferred_mode (&config->outputs[j], &outputs[j]); | ||||
|               config->outputs[j].rect.x = cur_x; | ||||
|               config->outputs[j].rect.y = cur_y; | ||||
|  | ||||
|               *output_configured_bitmap |= (1 << j); | ||||
|               cur_y += outputs[j].tile_info.tile_h; | ||||
|               if (vt == 0) | ||||
|                 addx += outputs[j].tile_info.tile_w; | ||||
|             } | ||||
|         } | ||||
|       cur_x += addx; | ||||
|     } | ||||
|   *x = cur_x; | ||||
|  | ||||
| } | ||||
|  | ||||
| static void | ||||
| make_linear_config (MetaMonitorConfig *self, | ||||
|                     MetaOutput        *outputs, | ||||
|                     unsigned           n_outputs, | ||||
|                     int                max_width, | ||||
|                     int                max_height, | ||||
|                     MetaConfiguration *config) | ||||
| { | ||||
|   unsigned long output_configured_bitmap = 0; | ||||
|   unsigned i; | ||||
|   int x; | ||||
|   int primary; | ||||
|  | ||||
|   g_return_if_fail (config != NULL); | ||||
|  | ||||
|   primary = find_primary_output (outputs, n_outputs); | ||||
|  | ||||
|   x = 0; | ||||
|   /* set the primary up first at 0 */ | ||||
|   if (outputs[primary].tile_info.group_id) | ||||
|     { | ||||
|       config_one_tiled_group (outputs, config, primary, TRUE, n_outputs, | ||||
|                               &x, &output_configured_bitmap); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       config_one_untiled_output (outputs, config, primary, TRUE, | ||||
|                                  &x, &output_configured_bitmap); | ||||
|     } | ||||
|  | ||||
|   /* then add other tiled monitors */ | ||||
|   for (i = 0; i < n_outputs; i++) | ||||
|     { | ||||
|       config_one_tiled_group (outputs, config, i, FALSE, n_outputs, | ||||
|                               &x, &output_configured_bitmap); | ||||
|     } | ||||
|  | ||||
|   /* then add remaining monitors */ | ||||
|   for (i = 0; i < n_outputs; i++) | ||||
|     { | ||||
|       config_one_untiled_output (outputs, config, i, FALSE, | ||||
|                                  &x, &output_configured_bitmap); | ||||
|  | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* Search for a configuration that includes one less screen, then add the new | ||||
|  * one as a presentation screen in preferred mode. | ||||
|  * | ||||
|  * XXX: but presentation mode is not implemented in the control-center or in | ||||
|  * mutter core, so let's do extended for now. | ||||
|   */ | ||||
| static gboolean | ||||
| extend_stored_config (MetaMonitorConfig *self, | ||||
|                       MetaOutput        *outputs, | ||||
|                       unsigned           n_outputs, | ||||
|                       int                max_width, | ||||
|                       int                max_height, | ||||
|                       MetaConfiguration *config) | ||||
| { | ||||
|   int x, y; | ||||
|   unsigned i, j; | ||||
|  | ||||
|   x = 0; | ||||
|   y = 0; | ||||
|   for (i = 0; i < n_outputs; i++) | ||||
| @@ -1139,69 +1331,80 @@ make_default_config (MetaMonitorConfig *self, | ||||
|             { | ||||
|               if (j < i) | ||||
|                 { | ||||
|                   g_assert (output_key_equal (&ret->keys[j], &ref->keys[j])); | ||||
|                   ret->outputs[j] = ref->outputs[j]; | ||||
|                   g_assert (output_key_equal (&config->keys[j], &ref->keys[j])); | ||||
|                   config->outputs[j] = ref->outputs[j]; | ||||
|                   x = MAX (x, ref->outputs[j].rect.x + ref->outputs[j].rect.width); | ||||
|                   y = MAX (y, ref->outputs[j].rect.y + ref->outputs[j].rect.height); | ||||
|                 } | ||||
|               else if (j > i) | ||||
|                 { | ||||
|                   g_assert (output_key_equal (&ret->keys[j], &ref->keys[j - 1])); | ||||
|                   ret->outputs[j] = ref->outputs[j - 1]; | ||||
|                   g_assert (output_key_equal (&config->keys[j], &ref->keys[j - 1])); | ||||
|                   config->outputs[j] = ref->outputs[j - 1]; | ||||
|                   x = MAX (x, ref->outputs[j - 1].rect.x + ref->outputs[j - 1].rect.width); | ||||
|                   y = MAX (y, ref->outputs[j - 1].rect.y + ref->outputs[j - 1].rect.height); | ||||
|                 } | ||||
|               else | ||||
|                 { | ||||
|                   ret->outputs[j].enabled = TRUE; | ||||
|                   ret->outputs[j].rect.x = 0; | ||||
|                   ret->outputs[j].rect.y = 0; | ||||
|                   ret->outputs[j].rect.width = outputs[0].preferred_mode->width; | ||||
|                   ret->outputs[j].rect.height = outputs[0].preferred_mode->height; | ||||
|                   ret->outputs[j].refresh_rate = outputs[0].preferred_mode->refresh_rate; | ||||
|                   ret->outputs[j].transform = META_MONITOR_TRANSFORM_NORMAL; | ||||
|                   ret->outputs[j].is_primary = FALSE; | ||||
|                   ret->outputs[j].is_presentation = FALSE; | ||||
|                   init_config_from_preferred_mode (&config->outputs[j], &outputs[0]); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|           /* Place the new output at the right end of the screen, if it fits, | ||||
|              otherwise below it, otherwise disable it (or apply_configuration will fail) */ | ||||
|           if (x + ret->outputs[i].rect.width <= max_width) | ||||
|             ret->outputs[i].rect.x = x; | ||||
|           else if (y + ret->outputs[i].rect.height <= max_height) | ||||
|             ret->outputs[i].rect.y = y; | ||||
|           if (x + config->outputs[i].rect.width <= max_width) | ||||
|             config->outputs[i].rect.x = x; | ||||
|           else if (y + config->outputs[i].rect.height <= max_height) | ||||
|             config->outputs[i].rect.y = y; | ||||
|           else | ||||
|             ret->outputs[i].enabled = FALSE; | ||||
|             config->outputs[i].enabled = FALSE; | ||||
|  | ||||
|           return ret; | ||||
|           return TRUE; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   /* No previous configuration found, try with a really default one, which | ||||
|      is one primary that goes first and the rest to the right of it, extended. | ||||
|   */ | ||||
|   primary = find_primary_output (outputs, n_outputs); | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
|   x = primary->preferred_mode->width; | ||||
| static MetaConfiguration * | ||||
| make_default_config (MetaMonitorConfig *self, | ||||
|                      MetaOutput        *outputs, | ||||
|                      unsigned           n_outputs, | ||||
|                      int                max_width, | ||||
|                      int                max_height, | ||||
|                      gboolean           use_stored_config) | ||||
| { | ||||
|   MetaConfiguration *ret = NULL; | ||||
|   unsigned i; | ||||
|  | ||||
|   ret = config_new (); | ||||
|   make_config_key (ret, outputs, n_outputs, -1); | ||||
|   ret->outputs = g_new0 (MetaOutputConfig, n_outputs); | ||||
|  | ||||
|   /* Special case the simple case: one output, primary at preferred mode, | ||||
|      nothing else to do */ | ||||
|   if (n_outputs == 1) | ||||
|     { | ||||
|       init_config_from_preferred_mode (&ret->outputs[0], &outputs[0]); | ||||
|       ret->outputs[0].is_primary = TRUE; | ||||
|       goto check_limits; | ||||
|     } | ||||
|  | ||||
|   if (make_suggested_config (self, outputs, n_outputs, max_width, max_height, ret)) | ||||
|       goto check_limits; | ||||
|  | ||||
|   if (use_stored_config && | ||||
|       extend_stored_config (self, outputs, n_outputs, max_width, max_height, ret)) | ||||
|       goto check_limits; | ||||
|  | ||||
|   make_linear_config (self, outputs, n_outputs, max_width, max_height, ret); | ||||
|  | ||||
| check_limits: | ||||
|   /* Disable outputs that would go beyond framebuffer limits */ | ||||
|   for (i = 0; i < n_outputs; i++) | ||||
|     { | ||||
|       MetaOutput *output = &outputs[i]; | ||||
|  | ||||
|       ret->outputs[i].enabled = TRUE; | ||||
|       ret->outputs[i].rect.x = (output == primary) ? 0 : x; | ||||
|       ret->outputs[i].rect.y = 0; | ||||
|       ret->outputs[i].rect.width = output->preferred_mode->width; | ||||
|       ret->outputs[i].rect.height = output->preferred_mode->height; | ||||
|       ret->outputs[i].refresh_rate = output->preferred_mode->refresh_rate; | ||||
|       ret->outputs[i].transform = META_MONITOR_TRANSFORM_NORMAL; | ||||
|       ret->outputs[i].is_primary = (output == primary); | ||||
|  | ||||
|       /* Disable outputs that would go beyond framebuffer limits */ | ||||
|       if (ret->outputs[i].rect.x + ret->outputs[i].rect.width > max_width) | ||||
|         ret->outputs[i].enabled = FALSE; | ||||
|       else if (output != primary) | ||||
|         x += output->preferred_mode->width; | ||||
|         if ((ret->outputs[i].rect.x + ret->outputs[i].rect.width > max_width) | ||||
|             || (ret->outputs[i].rect.y + ret->outputs[i].rect.height > max_height)) | ||||
|           ret->outputs[i].enabled = FALSE; | ||||
|     } | ||||
|  | ||||
|   return ret; | ||||
| @@ -1213,8 +1416,8 @@ ensure_at_least_one_output (MetaMonitorConfig  *self, | ||||
|                             MetaOutput         *outputs, | ||||
|                             unsigned            n_outputs) | ||||
| { | ||||
|   MetaConfiguration *ret; | ||||
|   MetaOutput *primary; | ||||
|   MetaConfiguration *config; | ||||
|   int primary; | ||||
|   unsigned i; | ||||
|  | ||||
|   /* Check that we have at least one active output */ | ||||
| @@ -1224,34 +1427,29 @@ ensure_at_least_one_output (MetaMonitorConfig  *self, | ||||
|  | ||||
|   /* Oh no, we don't! Activate the primary one and disable everything else */ | ||||
|  | ||||
|   ret = g_slice_new (MetaConfiguration); | ||||
|   make_config_key (ret, outputs, n_outputs, -1); | ||||
|   ret->outputs = g_new0 (MetaOutputConfig, n_outputs); | ||||
|   config = config_new (); | ||||
|   make_config_key (config, outputs, n_outputs, -1); | ||||
|   config->outputs = g_new0 (MetaOutputConfig, n_outputs); | ||||
|  | ||||
|   primary = find_primary_output (outputs, n_outputs); | ||||
|  | ||||
|   for (i = 0; i < n_outputs; i++) | ||||
|     { | ||||
|       MetaOutput *output = &outputs[i]; | ||||
|       gboolean is_primary = ((int)i == primary); | ||||
|  | ||||
|       if (output == primary) | ||||
|       if (is_primary) | ||||
|         { | ||||
|           ret->outputs[i].enabled = TRUE; | ||||
|           ret->outputs[i].rect.x = 0; | ||||
|           ret->outputs[i].rect.y = 0; | ||||
|           ret->outputs[i].rect.width = output->preferred_mode->width; | ||||
|           ret->outputs[i].rect.height = output->preferred_mode->height; | ||||
|           ret->outputs[i].refresh_rate = output->preferred_mode->refresh_rate; | ||||
|           ret->outputs[i].transform = META_MONITOR_TRANSFORM_NORMAL; | ||||
|           ret->outputs[i].is_primary = TRUE; | ||||
|           init_config_from_preferred_mode (&config->outputs[i], &outputs[0]); | ||||
|           config->outputs[i].is_primary = TRUE; | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           ret->outputs[i].enabled = FALSE; | ||||
|           config->outputs[i].enabled = FALSE; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   apply_configuration (self, ret, manager, FALSE); | ||||
|   apply_configuration (self, config, manager); | ||||
|   config_unref (config); | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| @@ -1262,8 +1460,9 @@ meta_monitor_config_make_default (MetaMonitorConfig  *self, | ||||
|   MetaOutput *outputs; | ||||
|   MetaConfiguration *default_config; | ||||
|   unsigned n_outputs; | ||||
|   gboolean ok; | ||||
|   gboolean ok = FALSE; | ||||
|   int max_width, max_height; | ||||
|   gboolean use_stored_config; | ||||
|  | ||||
|   outputs = meta_monitor_manager_get_outputs (manager, &n_outputs); | ||||
|   meta_monitor_manager_get_screen_limits (manager, &max_width, &max_height); | ||||
| @@ -1274,23 +1473,21 @@ meta_monitor_config_make_default (MetaMonitorConfig  *self, | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   default_config = make_default_config (self, outputs, n_outputs, max_width, max_height); | ||||
|   /* if the device has hotplug_mode_update, it's possible that the | ||||
|    * current display configuration does not match a stored configuration. | ||||
|    * Since extend_existing_config() tries to build a configuration that is | ||||
|    * based on a previously-stored configuration, it's quite likely that the | ||||
|    * resulting config will fail. Even if it doesn't fail, it may result in | ||||
|    * an unexpected configuration, so don't attempt to use a stored config | ||||
|    * in this situation. */ | ||||
|   use_stored_config = !meta_monitor_manager_has_hotplug_mode_update (manager); | ||||
|   default_config = make_default_config (self, outputs, n_outputs, max_width, max_height, use_stored_config); | ||||
|  | ||||
|   if (default_config != NULL) | ||||
|     { | ||||
|       if (self->lid_is_closed && | ||||
|           multiple_outputs_are_enabled (default_config) && | ||||
|           laptop_display_is_on (default_config)) | ||||
|         { | ||||
|           ok = apply_configuration (self, make_laptop_lid_config (default_config), | ||||
|                                     manager, FALSE); | ||||
|           config_free (default_config); | ||||
|         } | ||||
|       else | ||||
|         ok = apply_configuration (self, default_config, manager, FALSE); | ||||
|       ok = apply_configuration_with_lid (self, default_config, manager); | ||||
|       config_unref (default_config); | ||||
|     } | ||||
|   else | ||||
|     ok = FALSE; | ||||
|  | ||||
|   if (!ok) | ||||
|     { | ||||
| @@ -1314,6 +1511,7 @@ init_config_from_output (MetaOutputConfig *config, | ||||
|   config->transform = output->crtc->transform; | ||||
|   config->is_primary = output->is_primary; | ||||
|   config->is_presentation = output->is_presentation; | ||||
|   config->is_underscanning = output->is_underscanning; | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -1327,7 +1525,7 @@ meta_monitor_config_update_current (MetaMonitorConfig  *self, | ||||
|  | ||||
|   outputs = meta_monitor_manager_get_outputs (manager, &n_outputs); | ||||
|  | ||||
|   current = g_slice_new (MetaConfiguration); | ||||
|   current = config_new (); | ||||
|   current->n_outputs = n_outputs; | ||||
|   current->outputs = g_new0 (MetaOutputConfig, n_outputs); | ||||
|   current->keys = g_new0 (MetaOutputKey, n_outputs); | ||||
| @@ -1340,15 +1538,11 @@ meta_monitor_config_update_current (MetaMonitorConfig  *self, | ||||
|  | ||||
|   if (self->current && config_equal_full (current, self->current)) | ||||
|     { | ||||
|       config_free (current); | ||||
|       config_unref (current); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   if (self->current && !self->current_is_stored) | ||||
|     config_free (self->current); | ||||
|  | ||||
|   self->current = current; | ||||
|   self->current_is_stored = FALSE; | ||||
|   set_current (self, current); | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -1356,7 +1550,17 @@ meta_monitor_config_restore_previous (MetaMonitorConfig  *self, | ||||
|                                       MetaMonitorManager *manager) | ||||
| { | ||||
|   if (self->previous) | ||||
|     apply_configuration (self, self->previous, manager, FALSE); | ||||
|     { | ||||
|       /* The user chose to restore the previous configuration. In this | ||||
|        * case, restore the previous configuration. */ | ||||
|       MetaConfiguration *prev_config = config_ref (self->previous); | ||||
|       apply_configuration (self, prev_config, manager); | ||||
|       config_unref (prev_config); | ||||
|  | ||||
|       /* After this, self->previous contains the rejected configuration. | ||||
|        * Since it was rejected, nuke it. */ | ||||
|       g_clear_pointer (&self->previous, (GDestroyNotify) config_unref); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       if (!meta_monitor_config_apply_stored (self, manager)) | ||||
| @@ -1374,7 +1578,8 @@ turn_off_laptop_display (MetaMonitorConfig  *self, | ||||
|     return; | ||||
|  | ||||
|   new = make_laptop_lid_config (self->current); | ||||
|   apply_configuration (self, new, manager, FALSE); | ||||
|   apply_configuration (self, new, manager); | ||||
|   config_unref (new); | ||||
|   self->current_is_for_laptop_lid = TRUE; | ||||
| } | ||||
|  | ||||
| @@ -1497,7 +1702,8 @@ meta_monitor_config_save (MetaMonitorConfig *self) | ||||
|                                       "      <reflect_x>%s</reflect_x>\n" | ||||
|                                       "      <reflect_y>no</reflect_y>\n" | ||||
|                                       "      <primary>%s</primary>\n" | ||||
|                                       "      <presentation>%s</presentation>\n", | ||||
|                                       "      <presentation>%s</presentation>\n" | ||||
|                                       "      <underscanning>%s</underscanning>\n", | ||||
|                                       output->rect.width, | ||||
|                                       output->rect.height, | ||||
|                                       refresh_rate, | ||||
| @@ -1506,7 +1712,8 @@ meta_monitor_config_save (MetaMonitorConfig *self) | ||||
|                                       rotation_map[output->transform & 0x3], | ||||
|                                       output->transform >= META_MONITOR_TRANSFORM_FLIPPED ? "yes" : "no", | ||||
|                                       output->is_primary ? "yes" : "no", | ||||
|                                       output->is_presentation ? "yes" : "no"); | ||||
|                                       output->is_presentation ? "yes" : "no", | ||||
|                                       output->is_underscanning ? "yes" : "no"); | ||||
|             } | ||||
|  | ||||
|           g_string_append (buffer, "    </output>\n"); | ||||
| @@ -1521,7 +1728,7 @@ meta_monitor_config_save (MetaMonitorConfig *self) | ||||
|   closure->config = g_object_ref (self); | ||||
|   closure->buffer = buffer; | ||||
|  | ||||
|   g_file_replace_contents_async (self->file, | ||||
|   g_file_replace_contents_async (self->user_file, | ||||
|                                  buffer->str, buffer->len, | ||||
|                                  NULL, /* etag */ | ||||
|                                  TRUE, | ||||
| @@ -1533,16 +1740,7 @@ meta_monitor_config_save (MetaMonitorConfig *self) | ||||
| void | ||||
| meta_monitor_config_make_persistent (MetaMonitorConfig *self) | ||||
| { | ||||
|   if (self->current_is_stored) | ||||
|     return; | ||||
|  | ||||
|   self->current_is_stored = TRUE; | ||||
|   g_hash_table_replace (self->configs, self->current, self->current); | ||||
|  | ||||
|   if (self->previous) | ||||
|     config_free (self->previous); | ||||
|   self->previous = NULL; | ||||
|  | ||||
|   g_hash_table_replace (self->configs, self->current, config_ref (self->current)); | ||||
|   meta_monitor_config_save (self); | ||||
| } | ||||
|  | ||||
| @@ -1648,7 +1846,7 @@ crtc_assignment_assign (CrtcAssignment       *assign, | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       MetaCRTCInfo *info = g_slice_new0 (MetaCRTCInfo); | ||||
|       info = g_slice_new0 (MetaCRTCInfo); | ||||
|  | ||||
|       info->crtc = crtc; | ||||
|       info->mode = mode; | ||||
| @@ -1722,7 +1920,6 @@ real_assign_crtcs (CrtcAssignment     *assignment, | ||||
|   MetaOutputKey *output_key; | ||||
|   MetaOutputConfig *output_config; | ||||
|   unsigned int i; | ||||
|   gboolean success; | ||||
|  | ||||
|   if (output_num == assignment->config->n_outputs) | ||||
|     return TRUE; | ||||
| @@ -1739,8 +1936,6 @@ real_assign_crtcs (CrtcAssignment     *assignment, | ||||
|                                       &crtcs, &n_crtcs, | ||||
|                                       &outputs, &n_outputs); | ||||
|  | ||||
|   success = FALSE; | ||||
|  | ||||
|   for (i = 0; i < n_crtcs; i++) | ||||
|     { | ||||
|       MetaCRTC *crtc = &crtcs[i]; | ||||
| @@ -1787,10 +1982,7 @@ real_assign_crtcs (CrtcAssignment     *assignment, | ||||
|                                               output)) | ||||
|                     { | ||||
|                       if (real_assign_crtcs (assignment, output_num + 1)) | ||||
|                         { | ||||
|                           success = TRUE; | ||||
|                           goto out; | ||||
|                         } | ||||
|                         return TRUE; | ||||
|  | ||||
|                       crtc_assignment_unassign (assignment, crtc, output); | ||||
|                     } | ||||
| @@ -1799,8 +1991,7 @@ real_assign_crtcs (CrtcAssignment     *assignment, | ||||
| 	} | ||||
|     } | ||||
|  | ||||
| out: | ||||
|   return success; | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| @@ -1849,6 +2040,7 @@ meta_monitor_config_assign_crtcs (MetaConfiguration  *config, | ||||
|                                                 &config->keys[i]); | ||||
|       output_info->is_primary = output_config->is_primary; | ||||
|       output_info->is_presentation = output_config->is_presentation; | ||||
|       output_info->is_underscanning = output_config->is_underscanning; | ||||
|  | ||||
|       g_ptr_array_add (outputs, output_info); | ||||
|     } | ||||
|   | ||||
| @@ -23,7 +23,7 @@ | ||||
| #ifndef META_MONITOR_CONFIG_H | ||||
| #define META_MONITOR_CONFIG_H | ||||
|  | ||||
| #include "meta-monitor-manager.h" | ||||
| #include "meta-monitor-manager-private.h" | ||||
|  | ||||
| #define META_TYPE_MONITOR_CONFIG            (meta_monitor_config_get_type ()) | ||||
| #define META_MONITOR_CONFIG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_CONFIG, MetaMonitorConfig)) | ||||
|   | ||||
| @@ -27,6 +27,10 @@ | ||||
|  | ||||
| #include "meta-monitor-manager-dummy.h" | ||||
|  | ||||
| #include <stdlib.h> | ||||
|  | ||||
| #include <meta/util.h> | ||||
|  | ||||
| #define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1) | ||||
|  | ||||
| struct _MetaMonitorManagerDummy | ||||
| @@ -44,9 +48,69 @@ G_DEFINE_TYPE (MetaMonitorManagerDummy, meta_monitor_manager_dummy, META_TYPE_MO | ||||
| static void | ||||
| meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager) | ||||
| { | ||||
|   unsigned int num_monitors = 1; | ||||
|   int *monitor_scales = NULL; | ||||
|   const char *num_monitors_str; | ||||
|   const char *monitor_scales_str; | ||||
|   unsigned int i; | ||||
|   int current_x = 0; | ||||
|  | ||||
|   /* To control what monitor configuration is generated, there are two available | ||||
|    * environmental variables that can be used: | ||||
|    * | ||||
|    * MUTTER_DEBUG_NUM_DUMMY_MONITORS | ||||
|    * | ||||
|    * Specifies the number of dummy monitors to include in the stage. Every | ||||
|    * monitor is 1024x786 pixels and they are placed on a horizontal row. | ||||
|    * | ||||
|    * MUTTER_DEBUG_DUMMY_MONITOR_SCALES | ||||
|    * | ||||
|    * A comma separated list that specifies the scales of the dummy monitors. | ||||
|    * | ||||
|    * For example the following configuration results in two monitors, where the | ||||
|    * first one has the monitor scale 1, and the other the monitor scale 2. | ||||
|    * | ||||
|    * MUTTER_DEBUG_NUM_DUMMY_MONITORS=2 | ||||
|    * MUTTER_DEBUG_DUMMY_MONITOR_SCALES=1,2 | ||||
|    */ | ||||
|   num_monitors_str = getenv ("MUTTER_DEBUG_NUM_DUMMY_MONITORS"); | ||||
|   if (num_monitors_str) | ||||
|     { | ||||
|       num_monitors = g_ascii_strtoll (num_monitors_str, NULL, 10); | ||||
|       if (num_monitors <= 0) | ||||
|         { | ||||
|           meta_warning ("Invalid number of dummy monitors"); | ||||
|           num_monitors = 1; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   monitor_scales = g_newa (int, num_monitors); | ||||
|   for (i = 0; i < num_monitors; i++) | ||||
|     monitor_scales[i] = 1; | ||||
|  | ||||
|   monitor_scales_str = getenv ("MUTTER_DEBUG_DUMMY_MONITOR_SCALES"); | ||||
|   if (monitor_scales_str) | ||||
|     { | ||||
|       gchar **scales_str_list; | ||||
|  | ||||
|       scales_str_list = g_strsplit (monitor_scales_str, ",", -1); | ||||
|       if (g_strv_length (scales_str_list) != num_monitors) | ||||
|         meta_warning ("Number of specified monitor scales differ from number " | ||||
|                       "of monitors (defaults to 1).\n"); | ||||
|       for (i = 0; i < num_monitors && scales_str_list[i]; i++) | ||||
|         { | ||||
|           int scale = g_ascii_strtoll (scales_str_list[i], NULL, 10); | ||||
|           if (scale == 1 || scale == 2) | ||||
|             monitor_scales[i] = scale; | ||||
|           else | ||||
|             meta_warning ("Invalid dummy monitor scale"); | ||||
|         } | ||||
|       g_strfreev (scales_str_list); | ||||
|     } | ||||
|  | ||||
|   manager->max_screen_width = 65535; | ||||
|   manager->max_screen_height = 65535; | ||||
|   manager->screen_width = 1024; | ||||
|   manager->screen_width = 1024 * num_monitors; | ||||
|   manager->screen_height = 768; | ||||
|  | ||||
|   manager->modes = g_new0 (MetaMonitorMode, 1); | ||||
| @@ -57,44 +121,52 @@ meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager) | ||||
|   manager->modes[0].height = 768; | ||||
|   manager->modes[0].refresh_rate = 60.0; | ||||
|  | ||||
|   manager->crtcs = g_new0 (MetaCRTC, 1); | ||||
|   manager->n_crtcs = 1; | ||||
|   manager->crtcs = g_new0 (MetaCRTC, num_monitors); | ||||
|   manager->n_crtcs = num_monitors; | ||||
|   manager->outputs = g_new0 (MetaOutput, num_monitors); | ||||
|   manager->n_outputs = num_monitors; | ||||
|  | ||||
|   manager->crtcs[0].crtc_id = 1; | ||||
|   manager->crtcs[0].rect.x = 0; | ||||
|   manager->crtcs[0].rect.y = 0; | ||||
|   manager->crtcs[0].rect.width = manager->modes[0].width; | ||||
|   manager->crtcs[0].rect.height = manager->modes[0].height; | ||||
|   manager->crtcs[0].current_mode = &manager->modes[0]; | ||||
|   manager->crtcs[0].transform = META_MONITOR_TRANSFORM_NORMAL; | ||||
|   manager->crtcs[0].all_transforms = ALL_TRANSFORMS; | ||||
|   manager->crtcs[0].is_dirty = FALSE; | ||||
|   manager->crtcs[0].logical_monitor = NULL; | ||||
|   for (i = 0; i < num_monitors; i++) | ||||
|     { | ||||
|       manager->crtcs[i].crtc_id = i + 1; | ||||
|       manager->crtcs[i].rect.x = current_x; | ||||
|       manager->crtcs[i].rect.y = 0; | ||||
|       manager->crtcs[i].rect.width = manager->modes[0].width; | ||||
|       manager->crtcs[i].rect.height = manager->modes[0].height; | ||||
|       manager->crtcs[i].current_mode = &manager->modes[0]; | ||||
|       manager->crtcs[i].transform = META_MONITOR_TRANSFORM_NORMAL; | ||||
|       manager->crtcs[i].all_transforms = ALL_TRANSFORMS; | ||||
|       manager->crtcs[i].is_dirty = FALSE; | ||||
|       manager->crtcs[i].logical_monitor = NULL; | ||||
|  | ||||
|   manager->outputs = g_new0 (MetaOutput, 1); | ||||
|   manager->n_outputs = 1; | ||||
|       current_x += manager->crtcs[i].rect.width; | ||||
|  | ||||
|   manager->outputs[0].crtc = &manager->crtcs[0]; | ||||
|   manager->outputs[0].winsys_id = 1; | ||||
|   manager->outputs[0].name = g_strdup ("LVDS"); | ||||
|   manager->outputs[0].vendor = g_strdup ("MetaProducts Inc."); | ||||
|   manager->outputs[0].product = g_strdup ("unknown"); | ||||
|   manager->outputs[0].serial = g_strdup ("0xC0FFEE"); | ||||
|   manager->outputs[0].width_mm = 222; | ||||
|   manager->outputs[0].height_mm = 125; | ||||
|   manager->outputs[0].subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN; | ||||
|   manager->outputs[0].preferred_mode = &manager->modes[0]; | ||||
|   manager->outputs[0].n_modes = 1; | ||||
|   manager->outputs[0].modes = g_new0 (MetaMonitorMode *, 1); | ||||
|   manager->outputs[0].modes[0] = &manager->modes[0]; | ||||
|   manager->outputs[0].n_possible_crtcs = 1; | ||||
|   manager->outputs[0].possible_crtcs = g_new0 (MetaCRTC *, 1); | ||||
|   manager->outputs[0].possible_crtcs[0] = &manager->crtcs[0]; | ||||
|   manager->outputs[0].n_possible_clones = 0; | ||||
|   manager->outputs[0].possible_clones = g_new0 (MetaOutput *, 0); | ||||
|   manager->outputs[0].backlight = -1; | ||||
|   manager->outputs[0].backlight_min = 0; | ||||
|   manager->outputs[0].backlight_max = 0; | ||||
|       manager->outputs[i].crtc = &manager->crtcs[i]; | ||||
|       manager->outputs[i].winsys_id = i + 1; | ||||
|       manager->outputs[i].name = g_strdup_printf ("LVDS%d", i + 1); | ||||
|       manager->outputs[i].vendor = g_strdup ("MetaProducts Inc."); | ||||
|       manager->outputs[i].product = g_strdup ("unknown"); | ||||
|       manager->outputs[i].serial = g_strdup ("0xC0FFEE"); | ||||
|       manager->outputs[i].suggested_x = -1; | ||||
|       manager->outputs[i].suggested_y = -1; | ||||
|       manager->outputs[i].width_mm = 222; | ||||
|       manager->outputs[i].height_mm = 125; | ||||
|       manager->outputs[i].subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN; | ||||
|       manager->outputs[i].preferred_mode = &manager->modes[0]; | ||||
|       manager->outputs[i].n_modes = 1; | ||||
|       manager->outputs[i].modes = g_new0 (MetaMonitorMode *, 1); | ||||
|       manager->outputs[i].modes[0] = &manager->modes[0]; | ||||
|       manager->outputs[i].n_possible_crtcs = 1; | ||||
|       manager->outputs[i].possible_crtcs = g_new0 (MetaCRTC *, 1); | ||||
|       manager->outputs[i].possible_crtcs[0] = &manager->crtcs[i]; | ||||
|       manager->outputs[i].n_possible_clones = 0; | ||||
|       manager->outputs[i].possible_clones = g_new0 (MetaOutput *, 0); | ||||
|       manager->outputs[i].backlight = -1; | ||||
|       manager->outputs[i].backlight_min = 0; | ||||
|       manager->outputs[i].backlight_max = 0; | ||||
|       manager->outputs[i].connector_type = META_CONNECTOR_TYPE_LVDS; | ||||
|       manager->outputs[i].scale = monitor_scales[i]; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -125,7 +197,7 @@ meta_monitor_manager_dummy_apply_config (MetaMonitorManager *manager, | ||||
|         { | ||||
|           MetaMonitorMode *mode; | ||||
|           MetaOutput *output; | ||||
|           int i, n_outputs; | ||||
|           unsigned int j; | ||||
|           int width, height; | ||||
|  | ||||
|           mode = crtc_info->mode; | ||||
| @@ -151,10 +223,9 @@ meta_monitor_manager_dummy_apply_config (MetaMonitorManager *manager, | ||||
|           screen_width = MAX (screen_width, crtc_info->x + width); | ||||
|           screen_height = MAX (screen_height, crtc_info->y + height); | ||||
|  | ||||
|           n_outputs = crtc_info->outputs->len; | ||||
|           for (i = 0; i < n_outputs; i++) | ||||
|           for (j = 0; j < crtc_info->outputs->len; j++) | ||||
|             { | ||||
|               output = ((MetaOutput**)crtc_info->outputs->pdata)[i]; | ||||
|               output = ((MetaOutput**)crtc_info->outputs->pdata)[j]; | ||||
|  | ||||
|               output->is_dirty = TRUE; | ||||
|               output->crtc = crtc; | ||||
|   | ||||
| @@ -23,7 +23,7 @@ | ||||
| #ifndef META_MONITOR_MANAGER_DUMMY_H | ||||
| #define META_MONITOR_MANAGER_DUMMY_H | ||||
|  | ||||
| #include "meta-monitor-manager.h" | ||||
| #include "meta-monitor-manager-private.h" | ||||
|  | ||||
| #define META_TYPE_MONITOR_MANAGER_DUMMY            (meta_monitor_manager_dummy_get_type ()) | ||||
| #define META_MONITOR_MANAGER_DUMMY(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_DUMMY, MetaMonitorManagerDummy)) | ||||
|   | ||||
| @@ -41,22 +41,22 @@ | ||||
| #include "display-private.h" | ||||
| #include <meta/screen.h> | ||||
| #include "stack-tracker.h" | ||||
| #include <meta/meta-monitor-manager.h> | ||||
| 
 | ||||
| #include "meta-display-config-shared.h" | ||||
| #include "meta-dbus-display-config.h" | ||||
| #include "meta-cursor.h" | ||||
| 
 | ||||
| typedef struct _MetaMonitorManagerClass    MetaMonitorManagerClass; | ||||
| typedef struct _MetaMonitorManager         MetaMonitorManager; | ||||
| typedef struct _MetaMonitorConfigClass    MetaMonitorConfigClass; | ||||
| typedef struct _MetaMonitorConfig         MetaMonitorConfig; | ||||
| 
 | ||||
| typedef struct _MetaOutput MetaOutput; | ||||
| typedef struct _MetaCRTC MetaCRTC; | ||||
| typedef struct _MetaOutput MetaOutput; | ||||
| typedef struct _MetaMonitorMode MetaMonitorMode; | ||||
| typedef struct _MetaMonitorInfo MetaMonitorInfo; | ||||
| typedef struct _MetaCRTCInfo MetaCRTCInfo; | ||||
| typedef struct _MetaOutputInfo MetaOutputInfo; | ||||
| typedef struct _MetaTileInfo MetaTileInfo; | ||||
| 
 | ||||
| typedef enum { | ||||
|   META_MONITOR_TRANSFORM_NORMAL, | ||||
| @@ -69,6 +69,38 @@ typedef enum { | ||||
|   META_MONITOR_TRANSFORM_FLIPPED_270, | ||||
| } MetaMonitorTransform; | ||||
| 
 | ||||
| /* This matches the values in drm_mode.h */ | ||||
| typedef enum { | ||||
|   META_CONNECTOR_TYPE_Unknown = 0, | ||||
|   META_CONNECTOR_TYPE_VGA = 1, | ||||
|   META_CONNECTOR_TYPE_DVII = 2, | ||||
|   META_CONNECTOR_TYPE_DVID = 3, | ||||
|   META_CONNECTOR_TYPE_DVIA = 4, | ||||
|   META_CONNECTOR_TYPE_Composite = 5, | ||||
|   META_CONNECTOR_TYPE_SVIDEO = 6, | ||||
|   META_CONNECTOR_TYPE_LVDS = 7, | ||||
|   META_CONNECTOR_TYPE_Component = 8, | ||||
|   META_CONNECTOR_TYPE_9PinDIN = 9, | ||||
|   META_CONNECTOR_TYPE_DisplayPort = 10, | ||||
|   META_CONNECTOR_TYPE_HDMIA = 11, | ||||
|   META_CONNECTOR_TYPE_HDMIB = 12, | ||||
|   META_CONNECTOR_TYPE_TV = 13, | ||||
|   META_CONNECTOR_TYPE_eDP = 14, | ||||
|   META_CONNECTOR_TYPE_VIRTUAL = 15, | ||||
|   META_CONNECTOR_TYPE_DSI = 16, | ||||
| } MetaConnectorType; | ||||
| 
 | ||||
| struct _MetaTileInfo { | ||||
|   guint32 group_id; | ||||
|   guint32 flags; | ||||
|   guint32 max_h_tiles; | ||||
|   guint32 max_v_tiles; | ||||
|   guint32 loc_h_tile; | ||||
|   guint32 loc_v_tile; | ||||
|   guint32 tile_w; | ||||
|   guint32 tile_h; | ||||
| }; | ||||
| 
 | ||||
| struct _MetaOutput | ||||
| { | ||||
|   /* The CRTC driving this output, NULL if the output is not enabled */ | ||||
| @@ -84,6 +116,8 @@ struct _MetaOutput | ||||
|   CoglSubpixelOrder subpixel_order; | ||||
|   int scale; | ||||
| 
 | ||||
|   MetaConnectorType connector_type; | ||||
| 
 | ||||
|   MetaMonitorMode *preferred_mode; | ||||
|   MetaMonitorMode **modes; | ||||
|   unsigned int n_modes; | ||||
| @@ -110,12 +144,18 @@ struct _MetaOutput | ||||
|   */ | ||||
|   gboolean is_primary; | ||||
|   gboolean is_presentation; | ||||
|   gboolean is_underscanning; | ||||
|   gboolean supports_underscanning; | ||||
| 
 | ||||
|   gpointer driver_private; | ||||
|   GDestroyNotify driver_notify; | ||||
| 
 | ||||
|   /* get a new preferred mode on hotplug events, to handle dynamic guest resizing */ | ||||
|   gboolean hotplug_mode_update; | ||||
|   gint suggested_x; | ||||
|   gint suggested_y; | ||||
| 
 | ||||
|   MetaTileInfo tile_info; | ||||
| }; | ||||
| 
 | ||||
| struct _MetaCRTC | ||||
| @@ -134,7 +174,11 @@ struct _MetaCRTC | ||||
|   /* Used when changing configuration */ | ||||
|   gboolean is_dirty; | ||||
| 
 | ||||
|   MetaCursorReference *cursor; | ||||
|   /* Used by cursor renderer backend */ | ||||
|   void *cursor_renderer_private; | ||||
| 
 | ||||
|   gpointer driver_private; | ||||
|   GDestroyNotify driver_notify; | ||||
| }; | ||||
| 
 | ||||
| struct _MetaMonitorMode | ||||
| @@ -151,6 +195,7 @@ struct _MetaMonitorMode | ||||
|   GDestroyNotify driver_notify; | ||||
| }; | ||||
| 
 | ||||
| #define META_MAX_OUTPUTS_PER_MONITOR 4 | ||||
| /**
 | ||||
|  * MetaMonitorInfo: | ||||
|  * | ||||
| @@ -166,9 +211,14 @@ struct _MetaMonitorInfo | ||||
|   int number; | ||||
|   int xinerama_index; | ||||
|   MetaRectangle rect; | ||||
|   /* for tiled monitors these are calculated, from untiled just copied */ | ||||
|   float refresh_rate; | ||||
|   int width_mm; | ||||
|   int height_mm; | ||||
|   gboolean is_primary; | ||||
|   gboolean is_presentation; /* XXX: not yet used */ | ||||
|   gboolean in_fullscreen; | ||||
|   int scale; | ||||
| 
 | ||||
|   /* The primary or first output for this monitor, 0 if we can't figure out.
 | ||||
|      It can be matched to a winsys_id of a MetaOutput. | ||||
| @@ -179,6 +229,12 @@ struct _MetaMonitorInfo | ||||
|      the primary one). | ||||
|   */ | ||||
|   glong winsys_id; | ||||
| 
 | ||||
|   guint32 tile_group_id; | ||||
| 
 | ||||
|   int monitor_winsys_xid; | ||||
|   int n_outputs; | ||||
|   MetaOutput *outputs[META_MAX_OUTPUTS_PER_MONITOR]; | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
| @@ -200,12 +256,13 @@ struct _MetaCRTCInfo { | ||||
| 
 | ||||
| /*
 | ||||
|  * MetaOutputInfo: | ||||
|  * this is the same as MetaOutputInfo, but for CRTCs | ||||
|  * this is the same as MetaCRTCInfo, but for outputs | ||||
|  */ | ||||
| struct _MetaOutputInfo { | ||||
|   MetaOutput  *output; | ||||
|   gboolean     is_primary; | ||||
|   gboolean     is_presentation; | ||||
|   gboolean     is_underscanning; | ||||
| }; | ||||
| 
 | ||||
| #define META_TYPE_MONITOR_MANAGER            (meta_monitor_manager_get_type ()) | ||||
| @@ -295,12 +352,15 @@ struct _MetaMonitorManagerClass | ||||
|                           unsigned short     *, | ||||
|                           unsigned short     *, | ||||
|                           unsigned short     *); | ||||
| 
 | ||||
|   void (*add_monitor) (MetaMonitorManager *, | ||||
|                        MetaMonitorInfo *); | ||||
| 
 | ||||
|   void (*delete_monitor) (MetaMonitorManager *, | ||||
|                           int monitor_winsys_xid); | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| GType meta_monitor_manager_get_type (void); | ||||
| 
 | ||||
| MetaMonitorManager *meta_monitor_manager_get  (void); | ||||
| 
 | ||||
| void                meta_monitor_manager_rebuild_derived   (MetaMonitorManager *manager); | ||||
| 
 | ||||
| MetaMonitorInfo    *meta_monitor_manager_get_monitor_infos (MetaMonitorManager *manager, | ||||
| @@ -336,14 +396,27 @@ void                meta_monitor_manager_apply_configuration (MetaMonitorManager | ||||
| void                meta_monitor_manager_confirm_configuration (MetaMonitorManager *manager, | ||||
|                                                                 gboolean            ok); | ||||
| 
 | ||||
| void               meta_output_parse_edid (MetaOutput *output, | ||||
|                                            GBytes     *edid); | ||||
| 
 | ||||
| void               meta_crtc_info_free   (MetaCRTCInfo   *info); | ||||
| void               meta_output_info_free (MetaOutputInfo *info); | ||||
| 
 | ||||
| void               meta_monitor_manager_free_output_array (MetaOutput *old_outputs, | ||||
|                                                            int         n_old_outputs); | ||||
| void               meta_monitor_manager_free_mode_array (MetaMonitorMode *old_modes, | ||||
|                                                          int              n_old_modes); | ||||
| gboolean           meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager); | ||||
| void               meta_monitor_manager_read_current_config (MetaMonitorManager *manager); | ||||
| void               meta_monitor_manager_on_hotplug (MetaMonitorManager *manager); | ||||
| 
 | ||||
| gboolean           meta_monitor_manager_get_monitor_matrix (MetaMonitorManager *manager, | ||||
|                                                             MetaOutput         *output, | ||||
|                                                             gfloat              matrix[6]); | ||||
| 
 | ||||
| gint               meta_monitor_manager_get_monitor_at_point (MetaMonitorManager *manager, | ||||
|                                                               gfloat              x, | ||||
|                                                               gfloat              y); | ||||
| 
 | ||||
| void meta_monitor_manager_clear_output (MetaOutput *output); | ||||
| void meta_monitor_manager_clear_mode (MetaMonitorMode *mode); | ||||
| void meta_monitor_manager_clear_crtc (MetaCRTC *crtc); | ||||
| 
 | ||||
| /* Returns true if transform causes width and height to be inverted
 | ||||
|    This is true for the odd transforms in the enum */ | ||||
| @@ -25,7 +25,7 @@ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include "meta-monitor-manager.h" | ||||
| #include "meta-monitor-manager-private.h" | ||||
|  | ||||
| #include <string.h> | ||||
| #include <math.h> | ||||
| @@ -35,6 +35,7 @@ | ||||
| #include <meta/main.h> | ||||
| #include "util-private.h" | ||||
| #include <meta/errors.h> | ||||
| #include "edid.h" | ||||
| #include "meta-monitor-config.h" | ||||
| #include "backends/x11/meta-monitor-manager-xrandr.h" | ||||
| #include "meta-backend-private.h" | ||||
| @@ -44,6 +45,18 @@ enum { | ||||
|   SIGNALS_LAST | ||||
| }; | ||||
|  | ||||
| /* Array index matches MetaMonitorTransform */ | ||||
| static gfloat transform_matrices[][6] = { | ||||
|   {  1,  0,  0,  0,  1,  0 }, /* normal */ | ||||
|   {  0, -1,  1,  1,  0,  0 }, /* 90° */ | ||||
|   { -1,  0,  1,  0, -1,  1 }, /* 180° */ | ||||
|   {  0,  1,  0, -1,  0,  1 }, /* 270° */ | ||||
|   { -1,  0,  1,  0,  1,  0 }, /* normal flipped */ | ||||
|   {  0,  1,  0,  1,  0,  0 }, /* 90° flipped */ | ||||
|   {  1,  0,  0,  0, -1,  1 }, /* 180° flipped */ | ||||
|   {  0, -1,  1, -1,  0,  1 }, /* 270° flipped */ | ||||
| }; | ||||
|  | ||||
| static int signals[SIGNALS_LAST]; | ||||
|  | ||||
| static void meta_monitor_manager_display_config_init (MetaDBusDisplayConfigIface *iface); | ||||
| @@ -58,12 +71,96 @@ meta_monitor_manager_init (MetaMonitorManager *manager) | ||||
| { | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * rules for constructing a tiled monitor | ||||
|  * 1. find a tile_group_id | ||||
|  * 2. iterate over all outputs for that tile group id | ||||
|  * 3. see if output has a crtc and if it is configured for the tile size | ||||
|  * 4. calculate the total tile size | ||||
|  * 5. set tile finished size | ||||
|  * 6. check for more tile_group_id | ||||
| */ | ||||
| static void | ||||
| read_current_config (MetaMonitorManager *manager) | ||||
| construct_tile_monitor (MetaMonitorManager *manager, | ||||
|                         GArray *monitor_infos, | ||||
|                         guint32 tile_group_id) | ||||
| { | ||||
|   manager->serial++; | ||||
|   MetaMonitorInfo info; | ||||
|   unsigned i; | ||||
|  | ||||
|   META_MONITOR_MANAGER_GET_CLASS (manager)->read_current (manager); | ||||
|   for (i = 0; i < monitor_infos->len; i++) | ||||
|     { | ||||
|       MetaMonitorInfo *pinfo = &g_array_index (monitor_infos, MetaMonitorInfo, i); | ||||
|  | ||||
|       if (pinfo->tile_group_id == tile_group_id) | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|   /* didn't find it */ | ||||
|   info.number = monitor_infos->len; | ||||
|   info.tile_group_id = tile_group_id; | ||||
|   info.is_presentation = FALSE; | ||||
|   info.refresh_rate = 0.0; | ||||
|   info.width_mm = 0; | ||||
|   info.height_mm = 0; | ||||
|   info.is_primary = FALSE; | ||||
|   info.rect.x = INT_MAX; | ||||
|   info.rect.y = INT_MAX; | ||||
|   info.rect.width = 0; | ||||
|   info.rect.height = 0; | ||||
|   info.winsys_id = 0; | ||||
|   info.n_outputs = 0; | ||||
|   info.monitor_winsys_xid = 0; | ||||
|  | ||||
|   for (i = 0; i < manager->n_outputs; i++) | ||||
|     { | ||||
|       MetaOutput *output = &manager->outputs[i]; | ||||
|  | ||||
|       if (!output->tile_info.group_id) | ||||
|         continue; | ||||
|  | ||||
|       if (output->tile_info.group_id != tile_group_id) | ||||
|         continue; | ||||
|  | ||||
|       if (!output->crtc) | ||||
|         continue; | ||||
|  | ||||
|       if (output->crtc->rect.width != (int)output->tile_info.tile_w || | ||||
|           output->crtc->rect.height != (int)output->tile_info.tile_h) | ||||
|         continue; | ||||
|  | ||||
|       if (output->tile_info.loc_h_tile == 0 && output->tile_info.loc_v_tile == 0) | ||||
|         { | ||||
|           info.refresh_rate = output->crtc->current_mode->refresh_rate; | ||||
|           info.width_mm = output->width_mm; | ||||
|           info.height_mm = output->height_mm; | ||||
|           info.winsys_id = output->winsys_id; | ||||
|         } | ||||
|  | ||||
|       /* hack */ | ||||
|       if (output->crtc->rect.x < info.rect.x) | ||||
|         info.rect.x = output->crtc->rect.x; | ||||
|       if (output->crtc->rect.y < info.rect.y) | ||||
|         info.rect.y = output->crtc->rect.y; | ||||
|  | ||||
|       if (output->tile_info.loc_h_tile == 0) | ||||
|         info.rect.height += output->tile_info.tile_h; | ||||
|  | ||||
|       if (output->tile_info.loc_v_tile == 0) | ||||
|         info.rect.width += output->tile_info.tile_w; | ||||
|  | ||||
|       if (info.n_outputs > META_MAX_OUTPUTS_PER_MONITOR) | ||||
|         continue; | ||||
|  | ||||
|       info.outputs[info.n_outputs++] = output; | ||||
|     } | ||||
|  | ||||
|   /* if we don't have a winsys id, i.e. we haven't found tile 0,0 | ||||
|      don't try and add this to the monitor infos */ | ||||
|   if (!info.winsys_id) | ||||
|     return; | ||||
|  | ||||
|   g_array_append_val (monitor_infos, info); | ||||
| } | ||||
|  | ||||
| /* | ||||
| @@ -76,16 +173,26 @@ read_current_config (MetaMonitorManager *manager) | ||||
| static void | ||||
| make_logical_config (MetaMonitorManager *manager) | ||||
| { | ||||
|   MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_GET_CLASS (manager); | ||||
|   GArray *monitor_infos; | ||||
|   unsigned int i, j; | ||||
|  | ||||
|   monitor_infos = g_array_sized_new (FALSE, TRUE, sizeof (MetaMonitorInfo), | ||||
|                                      manager->n_outputs); | ||||
|                                      manager->n_crtcs); | ||||
|  | ||||
|   /* Walk the list of MetaCRTCs, and build a MetaMonitorInfo | ||||
|      for each of them, unless they reference a rectangle that | ||||
|      is already there. | ||||
|   */ | ||||
|   /* for tiling we need to work out how many tiled outputs there are */ | ||||
|   for (i = 0; i < manager->n_outputs; i++) | ||||
|     { | ||||
|       MetaOutput *output = &manager->outputs[i]; | ||||
|  | ||||
|       if (output->tile_info.group_id) | ||||
|         construct_tile_monitor (manager, monitor_infos, output->tile_info.group_id); | ||||
|     } | ||||
|  | ||||
|   for (i = 0; i < manager->n_crtcs; i++) | ||||
|     { | ||||
|       MetaCRTC *crtc = &manager->crtcs[i]; | ||||
| @@ -97,8 +204,8 @@ make_logical_config (MetaMonitorManager *manager) | ||||
|       for (j = 0; j < monitor_infos->len; j++) | ||||
|         { | ||||
|           MetaMonitorInfo *info = &g_array_index (monitor_infos, MetaMonitorInfo, j); | ||||
|           if (meta_rectangle_equal (&crtc->rect, | ||||
|                                     &info->rect)) | ||||
|           if (meta_rectangle_contains_rect (&info->rect, | ||||
|                                             &crtc->rect)) | ||||
|             { | ||||
|               crtc->logical_monitor = info; | ||||
|               break; | ||||
| @@ -110,7 +217,10 @@ make_logical_config (MetaMonitorManager *manager) | ||||
|           MetaMonitorInfo info; | ||||
|  | ||||
|           info.number = monitor_infos->len; | ||||
|           info.tile_group_id = 0; | ||||
|           info.rect = crtc->rect; | ||||
|           info.refresh_rate = crtc->current_mode->refresh_rate; | ||||
|           info.scale = 1; | ||||
|           info.is_primary = FALSE; | ||||
|           /* This starts true because we want | ||||
|              is_presentation only if all outputs are | ||||
| @@ -120,7 +230,8 @@ make_logical_config (MetaMonitorManager *manager) | ||||
|           info.is_presentation = TRUE; | ||||
|           info.in_fullscreen = -1; | ||||
|           info.winsys_id = 0; | ||||
|  | ||||
|           info.n_outputs = 0; | ||||
|           info.monitor_winsys_xid = 0; | ||||
|           g_array_append_val (monitor_infos, info); | ||||
|  | ||||
|           crtc->logical_monitor = &g_array_index (monitor_infos, MetaMonitorInfo, | ||||
| @@ -142,6 +253,9 @@ make_logical_config (MetaMonitorManager *manager) | ||||
|       if (output->crtc == NULL) | ||||
|         continue; | ||||
|  | ||||
|       if (output->tile_info.group_id) | ||||
|         continue; | ||||
|  | ||||
|       /* We must have a logical monitor on every CRTC at this point */ | ||||
|       g_assert (output->crtc->logical_monitor != NULL); | ||||
|  | ||||
| @@ -150,8 +264,17 @@ make_logical_config (MetaMonitorManager *manager) | ||||
|       info->is_primary = info->is_primary || output->is_primary; | ||||
|       info->is_presentation = info->is_presentation && output->is_presentation; | ||||
|  | ||||
|       info->width_mm = output->width_mm; | ||||
|       info->height_mm = output->height_mm; | ||||
|  | ||||
|       info->outputs[0] = output; | ||||
|       info->n_outputs = 1; | ||||
|  | ||||
|       if (output->is_primary || info->winsys_id == 0) | ||||
|         info->winsys_id = output->winsys_id; | ||||
|         { | ||||
|           info->scale = output->scale; | ||||
|           info->winsys_id = output->winsys_id; | ||||
|         } | ||||
|  | ||||
|       if (info->is_primary) | ||||
|         manager->primary_monitor_index = info->number; | ||||
| @@ -159,6 +282,10 @@ make_logical_config (MetaMonitorManager *manager) | ||||
|  | ||||
|   manager->n_monitor_infos = monitor_infos->len; | ||||
|   manager->monitor_infos = (void*)g_array_free (monitor_infos, FALSE); | ||||
|  | ||||
|   if (manager_class->add_monitor) | ||||
|     for (i = 0; i < manager->n_monitor_infos; i++) | ||||
|       manager_class->add_monitor (manager, &manager->monitor_infos[i]); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -198,7 +325,7 @@ meta_monitor_manager_constructed (GObject *object) | ||||
|  | ||||
|   manager->config = meta_monitor_config_new (); | ||||
|  | ||||
|   read_current_config (manager); | ||||
|   meta_monitor_manager_read_current_config (manager); | ||||
|  | ||||
|   if (!meta_monitor_config_apply_stored (manager->config, manager)) | ||||
|     meta_monitor_config_make_default (manager->config, manager); | ||||
| @@ -211,24 +338,7 @@ meta_monitor_manager_constructed (GObject *object) | ||||
|      so this is not needed. | ||||
|   */ | ||||
|   if (META_IS_MONITOR_MANAGER_XRANDR (manager)) | ||||
|     { | ||||
|       MetaOutput *old_outputs; | ||||
|       MetaCRTC *old_crtcs; | ||||
|       MetaMonitorMode *old_modes; | ||||
|       unsigned int n_old_outputs, n_old_modes; | ||||
|  | ||||
|       old_outputs = manager->outputs; | ||||
|       n_old_outputs = manager->n_outputs; | ||||
|       old_modes = manager->modes; | ||||
|       n_old_modes = manager->n_modes; | ||||
|       old_crtcs = manager->crtcs; | ||||
|  | ||||
|       read_current_config (manager); | ||||
|  | ||||
|       meta_monitor_manager_free_output_array (old_outputs, n_old_outputs); | ||||
|       meta_monitor_manager_free_mode_array (old_modes, n_old_modes); | ||||
|       g_free (old_crtcs); | ||||
|     } | ||||
|     meta_monitor_manager_read_current_config (manager); | ||||
|  | ||||
|   make_logical_config (manager); | ||||
|   initialize_dbus_interface (manager); | ||||
| @@ -237,45 +347,78 @@ meta_monitor_manager_constructed (GObject *object) | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_monitor_manager_clear_output (MetaOutput *output) | ||||
| { | ||||
|   g_free (output->name); | ||||
|   g_free (output->vendor); | ||||
|   g_free (output->product); | ||||
|   g_free (output->serial); | ||||
|   g_free (output->modes); | ||||
|   g_free (output->possible_crtcs); | ||||
|   g_free (output->possible_clones); | ||||
|  | ||||
|   if (output->driver_notify) | ||||
|     output->driver_notify (output); | ||||
|  | ||||
|   memset (output, 0, sizeof (*output)); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_monitor_manager_free_output_array (MetaOutput *old_outputs, | ||||
|                                         int         n_old_outputs) | ||||
| { | ||||
|   int i; | ||||
|  | ||||
|   for (i = 0; i < n_old_outputs; i++) | ||||
|     { | ||||
|       g_free (old_outputs[i].name); | ||||
|       g_free (old_outputs[i].vendor); | ||||
|       g_free (old_outputs[i].product); | ||||
|       g_free (old_outputs[i].serial); | ||||
|       g_free (old_outputs[i].modes); | ||||
|       g_free (old_outputs[i].possible_crtcs); | ||||
|       g_free (old_outputs[i].possible_clones); | ||||
|  | ||||
|       if (old_outputs[i].driver_notify) | ||||
|         old_outputs[i].driver_notify (&old_outputs[i]); | ||||
|     } | ||||
|     meta_monitor_manager_clear_output (&old_outputs[i]); | ||||
|  | ||||
|   g_free (old_outputs); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_monitor_manager_clear_mode (MetaMonitorMode *mode) | ||||
| { | ||||
|   g_free (mode->name); | ||||
|  | ||||
|   if (mode->driver_notify) | ||||
|     mode->driver_notify (mode); | ||||
|  | ||||
|   memset (mode, 0, sizeof (*mode)); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_monitor_manager_free_mode_array (MetaMonitorMode *old_modes, | ||||
|                                       int              n_old_modes) | ||||
| { | ||||
|   int i; | ||||
|  | ||||
|   for (i = 0; i < n_old_modes; i++) | ||||
|     { | ||||
|       g_free (old_modes[i].name); | ||||
|  | ||||
|       if (old_modes[i].driver_notify) | ||||
|         old_modes[i].driver_notify (&old_modes[i]); | ||||
|     } | ||||
|     meta_monitor_manager_clear_mode (&old_modes[i]); | ||||
|  | ||||
|   g_free (old_modes); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_monitor_manager_clear_crtc (MetaCRTC *crtc) | ||||
| { | ||||
|   if (crtc->driver_notify) | ||||
|     crtc->driver_notify (crtc); | ||||
|  | ||||
|   memset (crtc, 0, sizeof (*crtc)); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_monitor_manager_free_crtc_array (MetaCRTC *old_crtcs, | ||||
|                                       int       n_old_crtcs) | ||||
| { | ||||
|   int i; | ||||
|  | ||||
|   for (i = 0; i < n_old_crtcs; i++) | ||||
|     meta_monitor_manager_clear_crtc (&old_crtcs[i]); | ||||
|  | ||||
|   g_free (old_crtcs); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_monitor_manager_finalize (GObject *object) | ||||
| { | ||||
| @@ -283,8 +426,8 @@ meta_monitor_manager_finalize (GObject *object) | ||||
|  | ||||
|   meta_monitor_manager_free_output_array (manager->outputs, manager->n_outputs); | ||||
|   meta_monitor_manager_free_mode_array (manager->modes, manager->n_modes); | ||||
|   meta_monitor_manager_free_crtc_array (manager->crtcs, manager->n_crtcs); | ||||
|   g_free (manager->monitor_infos); | ||||
|   g_free (manager->crtcs); | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_monitor_manager_parent_class)->finalize (object); | ||||
| } | ||||
| @@ -365,15 +508,16 @@ static char * | ||||
| make_display_name (MetaMonitorManager *manager, | ||||
|                    MetaOutput         *output) | ||||
| { | ||||
|   char *inches = NULL; | ||||
|   char *vendor_name = NULL; | ||||
|   char *ret; | ||||
|   g_autofree char *inches = NULL; | ||||
|   g_autofree char *vendor_name = NULL; | ||||
|  | ||||
|   if (g_str_has_prefix (output->name, "LVDS") || | ||||
|       g_str_has_prefix (output->name, "eDP")) | ||||
|   switch (output->connector_type) | ||||
|     { | ||||
|       ret = g_strdup (_("Built-in display")); | ||||
|       goto out; | ||||
|     case META_CONNECTOR_TYPE_LVDS: | ||||
|     case META_CONNECTOR_TYPE_eDP: | ||||
|       return g_strdup (_("Built-in display")); | ||||
|     default: | ||||
|       break; | ||||
|     } | ||||
|  | ||||
|   if (output->width_mm > 0 && output->height_mm > 0) | ||||
| @@ -407,18 +551,38 @@ make_display_name (MetaMonitorManager *manager, | ||||
|       /* TRANSLATORS: this is a monitor vendor name, followed by a | ||||
|        * size in inches, like 'Dell 15"' | ||||
|        */ | ||||
|       ret = g_strdup_printf (_("%s %s"), vendor_name, inches); | ||||
|       return g_strdup_printf (_("%s %s"), vendor_name, inches); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       ret = g_strdup (vendor_name); | ||||
|       return g_strdup (vendor_name); | ||||
|     } | ||||
| } | ||||
|  | ||||
|  out: | ||||
|   g_free (inches); | ||||
|   g_free (vendor_name); | ||||
|  | ||||
|   return ret; | ||||
| static const char * | ||||
| get_connector_type_name (MetaConnectorType connector_type) | ||||
| { | ||||
|   switch (connector_type) | ||||
|     { | ||||
|     case META_CONNECTOR_TYPE_Unknown: return "Unknown"; | ||||
|     case META_CONNECTOR_TYPE_VGA: return "VGA"; | ||||
|     case META_CONNECTOR_TYPE_DVII: return "DVII"; | ||||
|     case META_CONNECTOR_TYPE_DVID: return "DVID"; | ||||
|     case META_CONNECTOR_TYPE_DVIA: return "DVIA"; | ||||
|     case META_CONNECTOR_TYPE_Composite: return "Composite"; | ||||
|     case META_CONNECTOR_TYPE_SVIDEO: return "SVIDEO"; | ||||
|     case META_CONNECTOR_TYPE_LVDS: return "LVDS"; | ||||
|     case META_CONNECTOR_TYPE_Component: return "Component"; | ||||
|     case META_CONNECTOR_TYPE_9PinDIN: return "9PinDIN"; | ||||
|     case META_CONNECTOR_TYPE_DisplayPort: return "DisplayPort"; | ||||
|     case META_CONNECTOR_TYPE_HDMIA: return "HDMIA"; | ||||
|     case META_CONNECTOR_TYPE_HDMIB: return "HDMIB"; | ||||
|     case META_CONNECTOR_TYPE_TV: return "TV"; | ||||
|     case META_CONNECTOR_TYPE_eDP: return "eDP"; | ||||
|     case META_CONNECTOR_TYPE_VIRTUAL: return "VIRTUAL"; | ||||
|     case META_CONNECTOR_TYPE_DSI: return "DSI"; | ||||
|     default: g_assert_not_reached (); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| @@ -501,6 +665,12 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton, | ||||
|                              g_variant_new_boolean (output->is_primary)); | ||||
|       g_variant_builder_add (&properties, "{sv}", "presentation", | ||||
|                              g_variant_new_boolean (output->is_presentation)); | ||||
|       g_variant_builder_add (&properties, "{sv}", "connector-type", | ||||
|                              g_variant_new_string (get_connector_type_name (output->connector_type))); | ||||
|       g_variant_builder_add (&properties, "{sv}", "underscanning", | ||||
|                              g_variant_new_boolean (output->is_underscanning)); | ||||
|       g_variant_builder_add (&properties, "{sv}", "supports-underscanning", | ||||
|                              g_variant_new_boolean (output->supports_underscanning)); | ||||
|  | ||||
|       edid_file = manager_class->get_edid_file (manager, output); | ||||
|       if (edid_file) | ||||
| @@ -521,6 +691,20 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton, | ||||
|             } | ||||
|         } | ||||
|  | ||||
|       if (output->tile_info.group_id) | ||||
|         { | ||||
|           g_variant_builder_add (&properties, "{sv}", "tile", | ||||
|                                  g_variant_new ("(uuuuuuuu)", | ||||
|                                                 output->tile_info.group_id, | ||||
|                                                 output->tile_info.flags, | ||||
|                                                 output->tile_info.max_h_tiles, | ||||
|                                                 output->tile_info.max_v_tiles, | ||||
|                                                 output->tile_info.loc_h_tile, | ||||
|                                                 output->tile_info.loc_v_tile, | ||||
|                                                 output->tile_info.tile_w, | ||||
|                                                 output->tile_info.tile_h)); | ||||
|         } | ||||
|  | ||||
|       g_variant_builder_add (&output_builder, "(uxiausauaua{sv})", | ||||
|                              i, /* ID */ | ||||
|                              (gint64)output->winsys_id, | ||||
| @@ -718,8 +902,7 @@ meta_monitor_manager_handle_apply_configuration  (MetaDBusDisplayConfig *skeleto | ||||
|           crtc_info->y = 0; | ||||
|         } | ||||
|  | ||||
|       if (transform < META_MONITOR_TRANSFORM_NORMAL || | ||||
|           transform > META_MONITOR_TRANSFORM_FLIPPED_270 || | ||||
|       if (transform > META_MONITOR_TRANSFORM_FLIPPED_270 || | ||||
|           ((crtc->all_transforms & (1 << transform)) == 0)) | ||||
|         { | ||||
|           g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, | ||||
| @@ -789,7 +972,7 @@ meta_monitor_manager_handle_apply_configuration  (MetaDBusDisplayConfig *skeleto | ||||
|   while (g_variant_iter_loop (&output_iter, "(u@a{sv})", &output_index, &properties)) | ||||
|     { | ||||
|       MetaOutputInfo *output_info; | ||||
|       gboolean primary, presentation; | ||||
|       gboolean primary, presentation, underscanning; | ||||
|  | ||||
|       if (output_index >= manager->n_outputs) | ||||
|         { | ||||
| @@ -808,6 +991,9 @@ meta_monitor_manager_handle_apply_configuration  (MetaDBusDisplayConfig *skeleto | ||||
|       if (g_variant_lookup (properties, "presentation", "b", &presentation)) | ||||
|         output_info->is_presentation = presentation; | ||||
|  | ||||
|       if (g_variant_lookup (properties, "underscanning", "b", &underscanning)) | ||||
|         output_info->is_underscanning = underscanning; | ||||
|  | ||||
|       g_ptr_array_add (output_infos, output_info); | ||||
|     } | ||||
|  | ||||
| @@ -1088,6 +1274,13 @@ initialize_dbus_interface (MetaMonitorManager *manager) | ||||
|                                           g_object_unref); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_monitor_manager_get: | ||||
|  * | ||||
|  * Accessor for the singleton MetaMonitorManager. | ||||
|  * | ||||
|  * Returns: (transfer none): The only #MetaMonitorManager there is. | ||||
|  */ | ||||
| MetaMonitorManager * | ||||
| meta_monitor_manager_get (void) | ||||
| { | ||||
| @@ -1162,20 +1355,238 @@ meta_monitor_manager_get_screen_limits (MetaMonitorManager *manager, | ||||
|   *height = manager->max_screen_height; | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_monitor_manager_read_current_config (MetaMonitorManager *manager) | ||||
| { | ||||
|   MetaOutput *old_outputs; | ||||
|   MetaCRTC *old_crtcs; | ||||
|   MetaMonitorMode *old_modes; | ||||
|   unsigned int n_old_outputs, n_old_crtcs, n_old_modes; | ||||
|  | ||||
|   /* Some implementations of read_current use the existing information | ||||
|    * we have available, so don't free the old configuration until after | ||||
|    * read_current finishes. */ | ||||
|   old_outputs = manager->outputs; | ||||
|   n_old_outputs = manager->n_outputs; | ||||
|   old_crtcs = manager->crtcs; | ||||
|   n_old_crtcs = manager->n_crtcs; | ||||
|   old_modes = manager->modes; | ||||
|   n_old_modes = manager->n_modes; | ||||
|  | ||||
|   manager->serial++; | ||||
|   META_MONITOR_MANAGER_GET_CLASS (manager)->read_current (manager); | ||||
|  | ||||
|   meta_monitor_manager_free_output_array (old_outputs, n_old_outputs); | ||||
|   meta_monitor_manager_free_mode_array (old_modes, n_old_modes); | ||||
|   meta_monitor_manager_free_crtc_array (old_crtcs, n_old_crtcs); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager) | ||||
| { | ||||
|   MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_GET_CLASS (manager); | ||||
|   MetaMonitorInfo *old_monitor_infos; | ||||
|  | ||||
|   unsigned old_n_monitor_infos; | ||||
|   unsigned i, j; | ||||
|   old_monitor_infos = manager->monitor_infos; | ||||
|   old_n_monitor_infos = manager->n_monitor_infos; | ||||
|  | ||||
|   if (manager->in_init) | ||||
|     return; | ||||
|  | ||||
|   make_logical_config (manager); | ||||
|  | ||||
|   if (manager_class->delete_monitor) | ||||
|     { | ||||
|       for (i = 0; i < old_n_monitor_infos; i++) | ||||
|         { | ||||
|           gboolean delete_mon = TRUE; | ||||
|           for (j = 0; j < manager->n_monitor_infos; j++) | ||||
|             { | ||||
|               if (manager->monitor_infos[j].monitor_winsys_xid == old_monitor_infos[i].monitor_winsys_xid) | ||||
|                 { | ||||
|                   delete_mon = FALSE; | ||||
|                   break; | ||||
|                 } | ||||
|             } | ||||
|           if (delete_mon) | ||||
|             manager_class->delete_monitor (manager, old_monitor_infos[i].monitor_winsys_xid); | ||||
|         } | ||||
|     } | ||||
|   g_signal_emit_by_name (manager, "monitors-changed"); | ||||
|  | ||||
|   g_free (old_monitor_infos); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_output_parse_edid (MetaOutput *meta_output, | ||||
|                         GBytes     *edid) | ||||
| { | ||||
|   MonitorInfo *parsed_edid; | ||||
|   gsize len; | ||||
|  | ||||
|   if (!edid) | ||||
|     goto out; | ||||
|  | ||||
|   parsed_edid = decode_edid (g_bytes_get_data (edid, &len)); | ||||
|  | ||||
|   if (parsed_edid) | ||||
|     { | ||||
|       meta_output->vendor = g_strndup (parsed_edid->manufacturer_code, 4); | ||||
|       if (!g_utf8_validate (meta_output->vendor, -1, NULL)) | ||||
|         g_clear_pointer (&meta_output->vendor, g_free); | ||||
|  | ||||
|       meta_output->product = g_strndup (parsed_edid->dsc_product_name, 14); | ||||
|       if (!g_utf8_validate (meta_output->product, -1, NULL) || | ||||
|           meta_output->product[0] == '\0') | ||||
|         { | ||||
|           g_clear_pointer (&meta_output->product, g_free); | ||||
|           meta_output->product = g_strdup_printf ("0x%04x", (unsigned) parsed_edid->product_code); | ||||
|         } | ||||
|  | ||||
|       meta_output->serial = g_strndup (parsed_edid->dsc_serial_number, 14); | ||||
|       if (!g_utf8_validate (meta_output->serial, -1, NULL) || | ||||
|           meta_output->serial[0] == '\0') | ||||
|         { | ||||
|           g_clear_pointer (&meta_output->serial, g_free); | ||||
|           meta_output->serial = g_strdup_printf ("0x%08x", parsed_edid->serial_number); | ||||
|         } | ||||
|  | ||||
|       g_free (parsed_edid); | ||||
|     } | ||||
|  | ||||
|  out: | ||||
|   if (!meta_output->vendor) | ||||
|     meta_output->vendor = g_strdup ("unknown"); | ||||
|   if (!meta_output->product) | ||||
|     meta_output->product = g_strdup ("unknown"); | ||||
|   if (!meta_output->serial) | ||||
|     meta_output->serial = g_strdup ("unknown"); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_monitor_manager_on_hotplug (MetaMonitorManager *manager) | ||||
| { | ||||
|   gboolean applied_config = FALSE; | ||||
|  | ||||
|   /* If the monitor has hotplug_mode_update (which is used by VMs), don't bother | ||||
|    * applying our stored configuration, because it's likely the user just resizing | ||||
|    * the window. | ||||
|    */ | ||||
|   if (!meta_monitor_manager_has_hotplug_mode_update (manager)) | ||||
|     { | ||||
|       if (meta_monitor_config_apply_stored (manager->config, manager)) | ||||
|         applied_config = TRUE; | ||||
|     } | ||||
|  | ||||
|   /* If we haven't applied any configuration, apply the default configuration. */ | ||||
|   if (!applied_config) | ||||
|     meta_monitor_config_make_default (manager->config, manager); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| calculate_viewport_matrix (MetaMonitorManager *manager, | ||||
|                            MetaOutput         *output, | ||||
|                            gfloat              viewport[6]) | ||||
| { | ||||
|   gfloat x, y, width, height; | ||||
|  | ||||
|   if (!output->crtc) | ||||
|     return FALSE; | ||||
|  | ||||
|   x = (float) output->crtc->rect.x / manager->screen_width; | ||||
|   y = (float) output->crtc->rect.y / manager->screen_height; | ||||
|   width  = (float) output->crtc->rect.width / manager->screen_width; | ||||
|   height = (float) output->crtc->rect.height / manager->screen_height; | ||||
|  | ||||
|   viewport[0] = width; | ||||
|   viewport[1] = 0.0f; | ||||
|   viewport[2] = x; | ||||
|   viewport[3] = 0.0f; | ||||
|   viewport[4] = height; | ||||
|   viewport[5] = y; | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static inline void | ||||
| multiply_matrix (float a[6], | ||||
| 		 float b[6], | ||||
| 		 float res[6]) | ||||
| { | ||||
|   res[0] = a[0] * b[0] + a[1] * b[3]; | ||||
|   res[1] = a[0] * b[1] + a[1] * b[4]; | ||||
|   res[2] = a[0] * b[2] + a[1] * b[5] + a[2]; | ||||
|   res[3] = a[3] * b[0] + a[4] * b[3]; | ||||
|   res[4] = a[3] * b[1] + a[4] * b[4]; | ||||
|   res[5] = a[3] * b[2] + a[4] * b[5] + a[5]; | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_monitor_manager_get_monitor_matrix (MetaMonitorManager *manager, | ||||
|                                          MetaOutput         *output, | ||||
|                                          gfloat              matrix[6]) | ||||
| { | ||||
|   gfloat viewport[9]; | ||||
|  | ||||
|   if (!calculate_viewport_matrix (manager, output, viewport)) | ||||
|     return FALSE; | ||||
|  | ||||
|   multiply_matrix (viewport, transform_matrices[output->crtc->transform], | ||||
|                    matrix); | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_monitor_manager_get_output_geometry: | ||||
|  * @manager: A #MetaMonitorManager | ||||
|  * @id: A valid #MetaOutput id | ||||
|  * | ||||
|  * Returns: The monitor index or -1 if @id isn't valid or the output | ||||
|  * isn't associated with a logical monitor. | ||||
|  */ | ||||
| gint | ||||
| meta_monitor_manager_get_monitor_for_output (MetaMonitorManager *manager, | ||||
|                                              guint               id) | ||||
| { | ||||
|   MetaOutput *output; | ||||
|   guint i; | ||||
|  | ||||
|   g_return_val_if_fail (META_IS_MONITOR_MANAGER (manager), -1); | ||||
|   g_return_val_if_fail (id < manager->n_outputs, -1); | ||||
|  | ||||
|   output = &manager->outputs[id]; | ||||
|   if (!output || !output->crtc) | ||||
|     return -1; | ||||
|  | ||||
|   for (i = 0; i < manager->n_monitor_infos; i++) | ||||
|     if (meta_rectangle_contains_rect (&manager->monitor_infos[i].rect, | ||||
|                                       &output->crtc->rect)) | ||||
|       return i; | ||||
|  | ||||
|   return -1; | ||||
| } | ||||
|  | ||||
| gint | ||||
| meta_monitor_manager_get_monitor_at_point (MetaMonitorManager *manager, | ||||
|                                            gfloat              x, | ||||
|                                            gfloat              y) | ||||
| { | ||||
|   unsigned int i; | ||||
|  | ||||
|   for (i = 0; i < manager->n_monitor_infos; i++) | ||||
|     { | ||||
|       MetaMonitorInfo *monitor = &manager->monitor_infos[i]; | ||||
|       int left, right, top, bottom; | ||||
|  | ||||
|       left = monitor->rect.x; | ||||
|       right = left + monitor->rect.width; | ||||
|       top = monitor->rect.y; | ||||
|       bottom = top + monitor->rect.height; | ||||
|  | ||||
|       if ((x >= left) && (x < right) && (y >= top) && (y < bottom)) | ||||
| 	return i; | ||||
|     } | ||||
|  | ||||
|   return -1; | ||||
| } | ||||
|   | ||||
							
								
								
									
										57
									
								
								src/backends/meta-pointer-constraint.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								src/backends/meta-pointer-constraint.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2015 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Jonas Ådahl <jadahl@gmail.com> | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include "backends/meta-pointer-constraint.h" | ||||
|  | ||||
| #include <glib-object.h> | ||||
|  | ||||
| G_DEFINE_TYPE (MetaPointerConstraint, meta_pointer_constraint, G_TYPE_OBJECT); | ||||
|  | ||||
| static void | ||||
| meta_pointer_constraint_init (MetaPointerConstraint *constraint) | ||||
| { | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_pointer_constraint_class_init (MetaPointerConstraintClass *klass) | ||||
| { | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_pointer_constraint_constrain (MetaPointerConstraint *constraint, | ||||
|                                    ClutterInputDevice    *device, | ||||
|                                    guint32                time, | ||||
|                                    float                  prev_x, | ||||
|                                    float                  prev_y, | ||||
|                                    float                  *x, | ||||
|                                    float                  *y) | ||||
| { | ||||
|   META_POINTER_CONSTRAINT_GET_CLASS (constraint)->constrain (constraint, | ||||
|                                                              device, | ||||
|                                                              time, | ||||
|                                                              prev_x, prev_y, | ||||
|                                                              x, y); | ||||
| } | ||||
							
								
								
									
										60
									
								
								src/backends/meta-pointer-constraint.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								src/backends/meta-pointer-constraint.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2015 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Jonas Ådahl <jadahl@gmail.com> | ||||
|  */ | ||||
|  | ||||
| #ifndef META_POINTER_CONSTRAINT_H | ||||
| #define META_POINTER_CONSTRAINT_H | ||||
|  | ||||
| #include <glib-object.h> | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define META_TYPE_POINTER_CONSTRAINT (meta_pointer_constraint_get_type ()) | ||||
| G_DECLARE_DERIVABLE_TYPE (MetaPointerConstraint, meta_pointer_constraint, | ||||
|                           META, POINTER_CONSTRAINT, GObject); | ||||
|  | ||||
| struct _MetaPointerConstraintClass | ||||
| { | ||||
|   GObjectClass parent_class; | ||||
|  | ||||
|   void (*constrain) (MetaPointerConstraint *constraint, | ||||
|                      ClutterInputDevice *device, | ||||
|                      guint32 time, | ||||
|                      float prev_x, | ||||
|                      float prev_y, | ||||
|                      float *x, | ||||
|                      float *y); | ||||
| }; | ||||
|  | ||||
| void meta_pointer_constraint_constrain (MetaPointerConstraint *constraint, | ||||
|                                         ClutterInputDevice    *device, | ||||
|                                         guint32                time, | ||||
|                                         float                  prev_x, | ||||
|                                         float                  prev_y, | ||||
|                                         float                 *x, | ||||
|                                         float                 *y); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* META_POINTER_CONSTRAINT_H */ | ||||
| @@ -24,7 +24,6 @@ | ||||
|  | ||||
| #include "meta-stage.h" | ||||
|  | ||||
| #include "meta-cursor-private.h" | ||||
| #include <meta/meta-backend.h> | ||||
| #include <meta/util.h> | ||||
|  | ||||
| @@ -41,6 +40,7 @@ typedef struct { | ||||
|  | ||||
| struct _MetaStagePrivate { | ||||
|   MetaOverlay cursor_overlay; | ||||
|   gboolean is_active; | ||||
| }; | ||||
| typedef struct _MetaStagePrivate MetaStagePrivate; | ||||
|  | ||||
| @@ -126,15 +126,41 @@ meta_stage_paint (ClutterActor *actor) | ||||
|   meta_overlay_paint (&priv->cursor_overlay); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_stage_activate (ClutterStage *actor) | ||||
| { | ||||
|   MetaStage *stage = META_STAGE (actor); | ||||
|   MetaStagePrivate *priv = meta_stage_get_instance_private (stage); | ||||
|  | ||||
|   CLUTTER_STAGE_CLASS (meta_stage_parent_class)->activate (actor); | ||||
|  | ||||
|   priv->is_active = TRUE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_stage_deactivate (ClutterStage *actor) | ||||
| { | ||||
|   MetaStage *stage = META_STAGE (actor); | ||||
|   MetaStagePrivate *priv = meta_stage_get_instance_private (stage); | ||||
|  | ||||
|   CLUTTER_STAGE_CLASS (meta_stage_parent_class)->deactivate (actor); | ||||
|  | ||||
|   priv->is_active = FALSE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_stage_class_init (MetaStageClass *klass) | ||||
| { | ||||
|   ClutterStageClass *stage_class = (ClutterStageClass *) klass; | ||||
|   ClutterActorClass *actor_class = (ClutterActorClass *) klass; | ||||
|   GObjectClass *object_class = (GObjectClass *) klass; | ||||
|  | ||||
|   object_class->finalize = meta_stage_finalize; | ||||
|  | ||||
|   actor_class->paint = meta_stage_paint; | ||||
|  | ||||
|   stage_class->activate = meta_stage_activate; | ||||
|   stage_class->deactivate = meta_stage_deactivate; | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -195,3 +221,43 @@ meta_stage_set_cursor (MetaStage     *stage, | ||||
|   meta_overlay_set (&priv->cursor_overlay, texture, rect); | ||||
|   queue_redraw_for_overlay (stage, &priv->cursor_overlay); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_stage_set_active (MetaStage *stage, | ||||
|                        gboolean   is_active) | ||||
| { | ||||
|   MetaStagePrivate *priv = meta_stage_get_instance_private (stage); | ||||
|   ClutterEvent event = { 0 }; | ||||
|  | ||||
|   /* Used by the native backend to inform accessibility technologies | ||||
|    * about when the stage loses and gains input focus. | ||||
|    * | ||||
|    * For the X11 backend, clutter transparently takes care of this | ||||
|    * for us. | ||||
|    */ | ||||
|  | ||||
|   if (priv->is_active == is_active) | ||||
|     return; | ||||
|  | ||||
|   event.type = CLUTTER_STAGE_STATE; | ||||
|   clutter_event_set_stage (&event, CLUTTER_STAGE (stage)); | ||||
|   event.stage_state.changed_mask = CLUTTER_STAGE_STATE_ACTIVATED; | ||||
|  | ||||
|   if (is_active) | ||||
|     event.stage_state.new_state = CLUTTER_STAGE_STATE_ACTIVATED; | ||||
|  | ||||
|   /* Emitting this StageState event will result in the stage getting | ||||
|    * activated or deactivated (with the activated or deactivated signal | ||||
|    * getting emitted from the stage) | ||||
|    * | ||||
|    * FIXME: This won't update ClutterStage's own notion of its | ||||
|    * activeness. For that we would need to somehow trigger a | ||||
|    * _clutter_stage_update_state call, which will probably | ||||
|    * require new API in clutter. In practice, nothing relies | ||||
|    * on the ClutterStage's own notion of activeness when using | ||||
|    * the EGL backend. | ||||
|    * | ||||
|    * See http://bugzilla.gnome.org/746670 | ||||
|    */ | ||||
|   clutter_stage_event (CLUTTER_STAGE (stage), &event); | ||||
| } | ||||
|   | ||||
| @@ -54,6 +54,9 @@ ClutterActor     *meta_stage_new                     (void); | ||||
| void meta_stage_set_cursor (MetaStage     *stage, | ||||
|                             CoglTexture   *texture, | ||||
|                             MetaRectangle *rect); | ||||
|  | ||||
| void meta_stage_set_active (MetaStage *stage, | ||||
|                             gboolean   is_active); | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* META_STAGE_H */ | ||||
|   | ||||
							
								
								
									
										32
									
								
								src/backends/native/meta-backend-native-private.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/backends/native/meta-backend-native-private.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2015 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Jonas Ådahl <jadahl@gmail.com> | ||||
|  */ | ||||
|  | ||||
| #ifndef META_BACKEND_NATIVE_PRIVATE_H | ||||
| #define META_BACKEND_NATIVE_PRIVATE_H | ||||
|  | ||||
| #include "backends/native/meta-barrier-native.h" | ||||
|  | ||||
| MetaBarrierManagerNative *meta_backend_native_get_barrier_manager (MetaBackendNative *native); | ||||
|  | ||||
| #endif /* META_BACKEND_NATIVE_PRIVATE_H */ | ||||
| @@ -24,20 +24,31 @@ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include "meta-backend-native.h" | ||||
| #include "meta-backend-native-private.h" | ||||
|  | ||||
| #include <meta/main.h> | ||||
| #include <clutter/evdev/clutter-evdev.h> | ||||
| #include "meta-backend-native.h" | ||||
| #include <libupower-glib/upower.h> | ||||
|  | ||||
| #include "meta-barrier-native.h" | ||||
| #include "meta-idle-monitor-native.h" | ||||
| #include "meta-monitor-manager-kms.h" | ||||
| #include "meta-cursor-renderer-native.h" | ||||
| #include "meta-launcher.h" | ||||
| #include "backends/meta-cursor-tracker-private.h" | ||||
| #include "backends/meta-pointer-constraint.h" | ||||
|  | ||||
| #include <stdlib.h> | ||||
|  | ||||
| struct _MetaBackendNativePrivate | ||||
| { | ||||
|   MetaLauncher *launcher; | ||||
|  | ||||
|   GSettings *keyboard_settings; | ||||
|   MetaBarrierManagerNative *barrier_manager; | ||||
|   UpClient *up_client; | ||||
|   guint sleep_signal_id; | ||||
|   GCancellable *cancellable; | ||||
|   GDBusConnection *system_bus; | ||||
| }; | ||||
| typedef struct _MetaBackendNativePrivate MetaBackendNativePrivate; | ||||
|  | ||||
| @@ -49,11 +60,105 @@ meta_backend_native_finalize (GObject *object) | ||||
|   MetaBackendNative *native = META_BACKEND_NATIVE (object); | ||||
|   MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native); | ||||
|  | ||||
|   g_clear_object (&priv->keyboard_settings); | ||||
|   meta_launcher_free (priv->launcher); | ||||
|  | ||||
|   g_object_unref (priv->up_client); | ||||
|   if (priv->sleep_signal_id) | ||||
|     g_dbus_connection_signal_unsubscribe (priv->system_bus, priv->sleep_signal_id); | ||||
|   g_cancellable_cancel (priv->cancellable); | ||||
|   g_clear_object (&priv->cancellable); | ||||
|   g_clear_object (&priv->system_bus); | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_backend_native_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| prepare_for_sleep_cb (GDBusConnection *connection, | ||||
|                       const gchar     *sender_name, | ||||
|                       const gchar     *object_path, | ||||
|                       const gchar     *interface_name, | ||||
|                       const gchar     *signal_name, | ||||
|                       GVariant        *parameters, | ||||
|                       gpointer         user_data) | ||||
| { | ||||
|   gboolean suspending; | ||||
|   g_variant_get (parameters, "(b)", &suspending); | ||||
|   if (suspending) | ||||
|     return; | ||||
|   meta_idle_monitor_native_reset_idletime (meta_idle_monitor_get_core ()); | ||||
| } | ||||
|  | ||||
| static void | ||||
| system_bus_gotten_cb (GObject      *object, | ||||
|                       GAsyncResult *res, | ||||
|                       gpointer      user_data) | ||||
| { | ||||
|   MetaBackendNativePrivate *priv; | ||||
|   GDBusConnection *bus; | ||||
|  | ||||
|   bus = g_bus_get_finish (res, NULL); | ||||
|   if (!bus) | ||||
|     return; | ||||
|  | ||||
|   priv = meta_backend_native_get_instance_private (META_BACKEND_NATIVE (user_data)); | ||||
|   priv->system_bus = bus; | ||||
|   priv->sleep_signal_id = g_dbus_connection_signal_subscribe (priv->system_bus, | ||||
|                                                               "org.freedesktop.login1", | ||||
|                                                               "org.freedesktop.login1.Manager", | ||||
|                                                               "PrepareForSleep", | ||||
|                                                               "/org/freedesktop/login1", | ||||
|                                                               NULL, | ||||
|                                                               G_DBUS_SIGNAL_FLAGS_NONE, | ||||
|                                                               prepare_for_sleep_cb, | ||||
|                                                               NULL, | ||||
|                                                               NULL); | ||||
| } | ||||
|  | ||||
| static void | ||||
| lid_is_closed_changed_cb (UpClient   *client, | ||||
|                           GParamSpec *pspec, | ||||
|                           gpointer    user_data) | ||||
| { | ||||
|   if (up_client_get_lid_is_closed (client)) | ||||
|     return; | ||||
|  | ||||
|   meta_idle_monitor_native_reset_idletime (meta_idle_monitor_get_core ()); | ||||
| } | ||||
|  | ||||
| static void | ||||
| constrain_to_barriers (ClutterInputDevice *device, | ||||
|                        guint32             time, | ||||
|                        float              *new_x, | ||||
|                        float              *new_y) | ||||
| { | ||||
|   MetaBackendNative *native = META_BACKEND_NATIVE (meta_get_backend ()); | ||||
|   MetaBackendNativePrivate *priv = | ||||
|     meta_backend_native_get_instance_private (native); | ||||
|  | ||||
|   meta_barrier_manager_native_process (priv->barrier_manager, | ||||
|                                        device, | ||||
|                                        time, | ||||
|                                        new_x, new_y); | ||||
| } | ||||
|  | ||||
| static void | ||||
| constrain_to_client_constraint (ClutterInputDevice *device, | ||||
|                                 guint32             time, | ||||
|                                 float               prev_x, | ||||
|                                 float               prev_y, | ||||
|                                 float              *x, | ||||
|                                 float              *y) | ||||
| { | ||||
|   MetaBackend *backend = meta_get_backend (); | ||||
|   MetaPointerConstraint *constraint = backend->client_pointer_constraint; | ||||
|  | ||||
|   if (!constraint) | ||||
|     return; | ||||
|  | ||||
|   meta_pointer_constraint_constrain (constraint, device, | ||||
|                                      time, prev_x, prev_y, x, y); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * The pointer constrain code is mostly a rip-off of the XRandR code from Xorg. | ||||
|  * (from xserver/randr/rrcrtc.c, RRConstrainCursorHarder) | ||||
| @@ -63,31 +168,6 @@ meta_backend_native_finalize (GObject *object) | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| static gboolean | ||||
| check_all_screen_monitors(MetaMonitorInfo *monitors, | ||||
| 			  unsigned         n_monitors, | ||||
| 			  float            x, | ||||
| 			  float            y) | ||||
| { | ||||
|   unsigned int i; | ||||
|  | ||||
|   for (i = 0; i < n_monitors; i++) | ||||
|     { | ||||
|       MetaMonitorInfo *monitor = &monitors[i]; | ||||
|       int left, right, top, bottom; | ||||
|  | ||||
|       left = monitor->rect.x; | ||||
|       right = left + monitor->rect.width; | ||||
|       top = monitor->rect.y; | ||||
|       bottom = left + monitor->rect.height; | ||||
|  | ||||
|       if ((x >= left) && (x < right) && (y >= top) && (y < bottom)) | ||||
| 	return TRUE; | ||||
|     } | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| constrain_all_screen_monitors (ClutterInputDevice *device, | ||||
| 			       MetaMonitorInfo    *monitors, | ||||
| @@ -97,25 +177,25 @@ constrain_all_screen_monitors (ClutterInputDevice *device, | ||||
| { | ||||
|   ClutterPoint current; | ||||
|   unsigned int i; | ||||
|   float cx, cy; | ||||
|  | ||||
|   clutter_input_device_get_coords (device, NULL, ¤t); | ||||
|  | ||||
|   cx = current.x; | ||||
|   cy = current.y; | ||||
|  | ||||
|   /* if we're trying to escape, clamp to the CRTC we're coming from */ | ||||
|   for (i = 0; i < n_monitors; i++) | ||||
|     { | ||||
|       MetaMonitorInfo *monitor = &monitors[i]; | ||||
|       int left, right, top, bottom; | ||||
|       float nx, ny; | ||||
|  | ||||
|       left = monitor->rect.x; | ||||
|       right = left + monitor->rect.width; | ||||
|       top = monitor->rect.y; | ||||
|       bottom = left + monitor->rect.height; | ||||
|       bottom = top + monitor->rect.height; | ||||
|  | ||||
|       nx = current.x; | ||||
|       ny = current.y; | ||||
|  | ||||
|       if ((nx >= left) && (nx < right) && (ny >= top) && (ny < bottom)) | ||||
|       if ((cx >= left) && (cx < right) && (cy >= top) && (cy < bottom)) | ||||
| 	{ | ||||
| 	  if (*x < left) | ||||
| 	    *x = left; | ||||
| @@ -133,68 +213,43 @@ constrain_all_screen_monitors (ClutterInputDevice *device, | ||||
|  | ||||
| static void | ||||
| pointer_constrain_callback (ClutterInputDevice *device, | ||||
| 			    guint32             time, | ||||
| 			    float              *new_x, | ||||
| 			    float              *new_y, | ||||
| 			    gpointer            user_data) | ||||
|                             guint32             time, | ||||
|                             float               prev_x, | ||||
|                             float               prev_y, | ||||
|                             float              *new_x, | ||||
|                             float              *new_y, | ||||
|                             gpointer            user_data) | ||||
| { | ||||
|   MetaMonitorManager *monitor_manager; | ||||
|   MetaMonitorInfo *monitors; | ||||
|   unsigned int n_monitors; | ||||
|   gboolean ret; | ||||
|  | ||||
|   /* Constrain to barriers */ | ||||
|   constrain_to_barriers (device, time, new_x, new_y); | ||||
|  | ||||
|   /* Constrain to pointer lock */ | ||||
|   constrain_to_client_constraint (device, time, prev_x, prev_y, new_x, new_y); | ||||
|  | ||||
|   monitor_manager = meta_monitor_manager_get (); | ||||
|   monitors = meta_monitor_manager_get_monitor_infos (monitor_manager, &n_monitors); | ||||
|  | ||||
|   /* if we're moving inside a monitor, we're fine */ | ||||
|   ret = check_all_screen_monitors(monitors, n_monitors, *new_x, *new_y); | ||||
|   if (ret == TRUE) | ||||
|   if (meta_monitor_manager_get_monitor_at_point (monitor_manager, *new_x, *new_y) >= 0) | ||||
|     return; | ||||
|  | ||||
|   /* if we're trying to escape, clamp to the CRTC we're coming from */ | ||||
|   constrain_all_screen_monitors(device, monitors, n_monitors, new_x, new_y); | ||||
| } | ||||
|  | ||||
| static void | ||||
| set_keyboard_repeat (MetaBackendNative *native) | ||||
| { | ||||
|   MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native); | ||||
|   ClutterDeviceManager *manager = clutter_device_manager_get_default (); | ||||
|   gboolean repeat; | ||||
|   unsigned int delay, interval; | ||||
|  | ||||
|   repeat = g_settings_get_boolean (priv->keyboard_settings, "repeat"); | ||||
|   delay = g_settings_get_uint (priv->keyboard_settings, "delay"); | ||||
|   interval = g_settings_get_uint (priv->keyboard_settings, "repeat-interval"); | ||||
|  | ||||
|   clutter_evdev_set_keyboard_repeat (manager, repeat, delay, interval); | ||||
| } | ||||
|  | ||||
| static void | ||||
| keyboard_settings_changed (GSettings           *settings, | ||||
|                            const char          *key, | ||||
|                            gpointer             data) | ||||
| { | ||||
|   MetaBackendNative *native = data; | ||||
|   set_keyboard_repeat (native); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_backend_native_post_init (MetaBackend *backend) | ||||
| { | ||||
|   MetaBackendNative *native = META_BACKEND_NATIVE (backend); | ||||
|   MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native); | ||||
|   ClutterDeviceManager *manager = clutter_device_manager_get_default (); | ||||
|  | ||||
|   META_BACKEND_CLASS (meta_backend_native_parent_class)->post_init (backend); | ||||
|  | ||||
|   clutter_evdev_set_pointer_constrain_callback (manager, pointer_constrain_callback, | ||||
|                                                 NULL, NULL); | ||||
|  | ||||
|   priv->keyboard_settings = g_settings_new ("org.gnome.settings-daemon.peripherals.keyboard"); | ||||
|   g_signal_connect (priv->keyboard_settings, "changed", | ||||
|                     G_CALLBACK (keyboard_settings_changed), native); | ||||
|   set_keyboard_repeat (native); | ||||
| } | ||||
|  | ||||
| static MetaIdleMonitor * | ||||
| @@ -225,11 +280,16 @@ meta_backend_native_warp_pointer (MetaBackend *backend, | ||||
| { | ||||
|   ClutterDeviceManager *manager = clutter_device_manager_get_default (); | ||||
|   ClutterInputDevice *device = clutter_device_manager_get_core_device (manager, CLUTTER_POINTER_DEVICE); | ||||
|   MetaCursorTracker *tracker = meta_cursor_tracker_get_for_screen (NULL); | ||||
|  | ||||
|   /* XXX */ | ||||
|   guint32 time_ = 0; | ||||
|  | ||||
|   /* Warp the input device pointer state. */ | ||||
|   clutter_evdev_warp_pointer (device, time_, x, y); | ||||
|  | ||||
|   /* Warp displayed pointer cursor. */ | ||||
|   meta_cursor_tracker_update_position (tracker, x, y); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -276,6 +336,19 @@ meta_backend_native_lock_layout_group (MetaBackend *backend, | ||||
|   g_signal_emit_by_name (backend, "keymap-layout-group-changed", idx, 0); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_backend_native_get_relative_motion_deltas (MetaBackend *backend, | ||||
|                                                 const        ClutterEvent *event, | ||||
|                                                 double       *dx, | ||||
|                                                 double       *dy, | ||||
|                                                 double       *dx_unaccel, | ||||
|                                                 double       *dy_unaccel) | ||||
| { | ||||
|   return clutter_evdev_event_get_relative_motion (event, | ||||
|                                                   dx, dy, | ||||
|                                                   dx_unaccel, dy_unaccel); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_backend_native_class_init (MetaBackendNativeClass *klass) | ||||
| { | ||||
| @@ -293,15 +366,33 @@ meta_backend_native_class_init (MetaBackendNativeClass *klass) | ||||
|   backend_class->set_keymap = meta_backend_native_set_keymap; | ||||
|   backend_class->get_keymap = meta_backend_native_get_keymap; | ||||
|   backend_class->lock_layout_group = meta_backend_native_lock_layout_group; | ||||
|   backend_class->get_relative_motion_deltas = meta_backend_native_get_relative_motion_deltas; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_backend_native_init (MetaBackendNative *native) | ||||
| { | ||||
|   MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native); | ||||
|   GError *error = NULL; | ||||
|  | ||||
|   /* We're a display server, so start talking to weston-launch. */ | ||||
|   priv->launcher = meta_launcher_new (); | ||||
|   priv->launcher = meta_launcher_new (&error); | ||||
|   if (priv->launcher == NULL) | ||||
|     { | ||||
|       g_warning ("Can't initialize KMS backend: %s\n", error->message); | ||||
|       exit (1); | ||||
|     } | ||||
|  | ||||
|   priv->barrier_manager = meta_barrier_manager_native_new (); | ||||
|  | ||||
|   priv->up_client = up_client_new (); | ||||
|   g_signal_connect (priv->up_client, "notify::lid-is-closed", | ||||
|                     G_CALLBACK (lid_is_closed_changed_cb), NULL); | ||||
|  | ||||
|   priv->cancellable = g_cancellable_new (); | ||||
|   g_bus_get (G_BUS_TYPE_SYSTEM, | ||||
|              priv->cancellable, | ||||
|              system_bus_gotten_cb, | ||||
|              native); | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| @@ -314,6 +405,15 @@ meta_activate_vt (int vt, GError **error) | ||||
|   return meta_launcher_activate_vt (priv->launcher, vt, error); | ||||
| } | ||||
|  | ||||
| MetaBarrierManagerNative * | ||||
| meta_backend_native_get_barrier_manager (MetaBackendNative *native) | ||||
| { | ||||
|   MetaBackendNativePrivate *priv = | ||||
|     meta_backend_native_get_instance_private (native); | ||||
|  | ||||
|   return priv->barrier_manager; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_activate_session: | ||||
|  * | ||||
|   | ||||
							
								
								
									
										617
									
								
								src/backends/native/meta-barrier-native.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										617
									
								
								src/backends/native/meta-barrier-native.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,617 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2015 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Jonas Ådahl <jadahl@gmail.com> | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * SECTION:barrier-native | ||||
|  * @Title: MetaBarrierImplNative | ||||
|  * @Short_Description: Pointer barriers implementation for the native backend | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include <stdlib.h> | ||||
|  | ||||
| #include <meta/barrier.h> | ||||
| #include <meta/util.h> | ||||
| #include "backends/meta-backend-private.h" | ||||
| #include "backends/meta-barrier-private.h" | ||||
| #include "backends/native/meta-backend-native.h" | ||||
| #include "backends/native/meta-backend-native-private.h" | ||||
| #include "backends/native/meta-barrier-native.h" | ||||
|  | ||||
| struct _MetaBarrierManagerNative | ||||
| { | ||||
|   GHashTable *barriers; | ||||
| }; | ||||
|  | ||||
| typedef enum { | ||||
|   /* The barrier is active and responsive to pointer motion. */ | ||||
|   META_BARRIER_STATE_ACTIVE, | ||||
|  | ||||
|   /* An intermediate state after a pointer hit the pointer barrier. */ | ||||
|   META_BARRIER_STATE_HIT, | ||||
|  | ||||
|   /* The barrier was hit by a pointer and is still within the hit box and | ||||
|    * has not been released.*/ | ||||
|   META_BARRIER_STATE_HELD, | ||||
|  | ||||
|   /* The pointer was released by the user. If the following motion hits | ||||
|    * the barrier, it will pass through. */ | ||||
|   META_BARRIER_STATE_RELEASE, | ||||
|  | ||||
|   /* An intermediate state when the pointer has left the barrier. */ | ||||
|   META_BARRIER_STATE_LEFT, | ||||
| } MetaBarrierState; | ||||
|  | ||||
| struct _MetaBarrierImplNativePrivate | ||||
| { | ||||
|   MetaBarrier              *barrier; | ||||
|   MetaBarrierManagerNative *manager; | ||||
|  | ||||
|   gboolean                  is_active; | ||||
|   MetaBarrierState          state; | ||||
|   int                       trigger_serial; | ||||
|   guint32                   last_event_time; | ||||
|   MetaBarrierDirection      blocked_dir; | ||||
| }; | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_PRIVATE (MetaBarrierImplNative, meta_barrier_impl_native, | ||||
|                             META_TYPE_BARRIER_IMPL) | ||||
|  | ||||
| static int | ||||
| next_serial (void) | ||||
| { | ||||
|   static int barrier_serial = 1; | ||||
|  | ||||
|   barrier_serial++; | ||||
|  | ||||
|   /* If it wraps, avoid 0 as it's not a valid serial. */ | ||||
|   if (barrier_serial == 0) | ||||
|     barrier_serial++; | ||||
|  | ||||
|   return barrier_serial; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| is_barrier_horizontal (MetaBarrier *barrier) | ||||
| { | ||||
|   return meta_border_is_horizontal (&barrier->priv->border); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| is_barrier_blocking_directions (MetaBarrier         *barrier, | ||||
|                                 MetaBarrierDirection directions) | ||||
| { | ||||
|   return meta_border_is_blocking_directions (&barrier->priv->border, | ||||
|                                              directions); | ||||
| } | ||||
|  | ||||
| static void | ||||
| dismiss_pointer (MetaBarrierImplNative *self) | ||||
| { | ||||
|   MetaBarrierImplNativePrivate *priv = | ||||
|     meta_barrier_impl_native_get_instance_private (self); | ||||
|  | ||||
|   priv->state = META_BARRIER_STATE_LEFT; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Calculate the hit box for a held motion. The hit box is a 2 px wide region | ||||
|  * in the opposite direction of every direction the barrier blocks. The purpose | ||||
|  * of this is to allow small movements without receiving a "left" signal. This | ||||
|  * heuristic comes from the X.org pointer barrier implementation. | ||||
|  */ | ||||
| static MetaLine2 | ||||
| calculate_barrier_hit_box (MetaBarrier *barrier) | ||||
| { | ||||
|   MetaLine2 hit_box = barrier->priv->border.line; | ||||
|  | ||||
|   if (is_barrier_horizontal (barrier)) | ||||
|     { | ||||
|       if (is_barrier_blocking_directions (barrier, | ||||
|                                           META_BARRIER_DIRECTION_POSITIVE_Y)) | ||||
|         hit_box.a.y -= 2.0f; | ||||
|       if (is_barrier_blocking_directions (barrier, | ||||
|                                           META_BARRIER_DIRECTION_NEGATIVE_Y)) | ||||
|         hit_box.b.y += 2.0f; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       if (is_barrier_blocking_directions (barrier, | ||||
|                                           META_BARRIER_DIRECTION_POSITIVE_X)) | ||||
|         hit_box.a.x -= 2.0f; | ||||
|       if (is_barrier_blocking_directions (barrier, | ||||
|                                           META_BARRIER_DIRECTION_NEGATIVE_X)) | ||||
|         hit_box.b.x += 2.0f; | ||||
|     } | ||||
|  | ||||
|   return hit_box; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| is_within_box (MetaLine2   box, | ||||
|                MetaVector2 point) | ||||
| { | ||||
|   return (point.x >= box.a.x && point.x < box.b.x && | ||||
|           point.y >= box.a.y && point.y < box.b.y); | ||||
| } | ||||
|  | ||||
| static void | ||||
| maybe_release_barrier (gpointer key, | ||||
|                        gpointer value, | ||||
|                        gpointer user_data) | ||||
| { | ||||
|   MetaBarrierImplNative *self = key; | ||||
|   MetaBarrierImplNativePrivate *priv = | ||||
|     meta_barrier_impl_native_get_instance_private (self); | ||||
|   MetaBarrier *barrier = priv->barrier; | ||||
|   MetaLine2 *motion = user_data; | ||||
|   MetaLine2 hit_box; | ||||
|  | ||||
|   if (priv->state != META_BARRIER_STATE_HELD) | ||||
|     return; | ||||
|  | ||||
|   /* Release if we end up outside barrier end points. */ | ||||
|   if (is_barrier_horizontal (barrier)) | ||||
|     { | ||||
|       if (motion->b.x > MAX (barrier->priv->border.line.a.x, | ||||
|                              barrier->priv->border.line.b.x) || | ||||
|           motion->b.x < MIN (barrier->priv->border.line.a.x, | ||||
|                              barrier->priv->border.line.b.x)) | ||||
|         { | ||||
|           dismiss_pointer (self); | ||||
|           return; | ||||
|         } | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       if (motion->b.y > MAX (barrier->priv->border.line.a.y, | ||||
|                              barrier->priv->border.line.b.y) || | ||||
|           motion->b.y < MIN (barrier->priv->border.line.a.y, | ||||
|                              barrier->priv->border.line.b.y)) | ||||
|         { | ||||
|           dismiss_pointer (self); | ||||
|           return; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   /* Release if we don't intersect and end up outside of hit box. */ | ||||
|   hit_box = calculate_barrier_hit_box (barrier); | ||||
|   if (!is_within_box (hit_box, motion->b)) | ||||
|     { | ||||
|       dismiss_pointer (self); | ||||
|       return; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| maybe_release_barriers (MetaBarrierManagerNative *manager, | ||||
|                         float                     prev_x, | ||||
|                         float                     prev_y, | ||||
|                         float                     x, | ||||
|                         float                     y) | ||||
| { | ||||
|   MetaLine2 motion = { | ||||
|     .a = { | ||||
|       .x = prev_x, | ||||
|       .y = prev_y, | ||||
|     }, | ||||
|     .b = { | ||||
|       .x = x, | ||||
|       .y = y, | ||||
|     }, | ||||
|   }; | ||||
|  | ||||
|   g_hash_table_foreach (manager->barriers, | ||||
|                         maybe_release_barrier, | ||||
|                         &motion); | ||||
| } | ||||
|  | ||||
| typedef struct _MetaClosestBarrierData | ||||
| { | ||||
|   struct | ||||
|   { | ||||
|     MetaLine2                   motion; | ||||
|     MetaBarrierDirection        directions; | ||||
|   } in; | ||||
|  | ||||
|   struct | ||||
|   { | ||||
|     float                       closest_distance_2; | ||||
|     MetaBarrierImplNative      *barrier_impl; | ||||
|   } out; | ||||
| } MetaClosestBarrierData; | ||||
|  | ||||
| static void | ||||
| update_closest_barrier (gpointer key, | ||||
|                         gpointer value, | ||||
|                         gpointer user_data) | ||||
| { | ||||
|   MetaBarrierImplNative *self = key; | ||||
|   MetaBarrierImplNativePrivate *priv = | ||||
|     meta_barrier_impl_native_get_instance_private (self); | ||||
|   MetaBarrier *barrier = priv->barrier; | ||||
|   MetaClosestBarrierData *data = user_data; | ||||
|   MetaVector2 intersection; | ||||
|   float dx, dy; | ||||
|   float distance_2; | ||||
|  | ||||
|   /* Ignore if the barrier is not blocking in any of the motions directions. */ | ||||
|   if (!is_barrier_blocking_directions (barrier, data->in.directions)) | ||||
|     return; | ||||
|  | ||||
|   /* Ignore if the barrier released the pointer. */ | ||||
|   if (priv->state == META_BARRIER_STATE_RELEASE) | ||||
|     return; | ||||
|  | ||||
|   /* Ignore if we are moving away from barrier. */ | ||||
|   if (priv->state == META_BARRIER_STATE_HELD && | ||||
|       (data->in.directions & priv->blocked_dir) == 0) | ||||
|     return; | ||||
|  | ||||
|   /* Check if the motion intersects with the barrier, and retrieve the | ||||
|    * intersection point if any. */ | ||||
|   if (!meta_line2_intersects_with (&barrier->priv->border.line, | ||||
|                                    &data->in.motion, | ||||
|                                    &intersection)) | ||||
|     return; | ||||
|  | ||||
|   /* Calculate the distance to the barrier and keep track of the closest | ||||
|    * barrier. */ | ||||
|   dx = intersection.x - data->in.motion.a.x; | ||||
|   dy = intersection.y - data->in.motion.a.y; | ||||
|   distance_2 = dx*dx + dy*dy; | ||||
|   if (data->out.barrier_impl == NULL || | ||||
|       distance_2 < data->out.closest_distance_2) | ||||
|     { | ||||
|       data->out.barrier_impl = self; | ||||
|       data->out.closest_distance_2 = distance_2; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| get_closest_barrier (MetaBarrierManagerNative *manager, | ||||
|                      float                     prev_x, | ||||
|                      float                     prev_y, | ||||
|                      float                     x, | ||||
|                      float                     y, | ||||
|                      MetaBarrierDirection      motion_dir, | ||||
|                      MetaBarrierImplNative   **barrier_impl) | ||||
| { | ||||
|   MetaClosestBarrierData closest_barrier_data; | ||||
|  | ||||
|   closest_barrier_data = (MetaClosestBarrierData) { | ||||
|     .in = { | ||||
|       .motion = { | ||||
|         .a = { | ||||
|           .x = prev_x, | ||||
|           .y = prev_y, | ||||
|         }, | ||||
|         .b = { | ||||
|           .x = x, | ||||
|           .y = y, | ||||
|         }, | ||||
|       }, | ||||
|       .directions = motion_dir, | ||||
|     }, | ||||
|   }; | ||||
|  | ||||
|   g_hash_table_foreach (manager->barriers, | ||||
|                         update_closest_barrier, | ||||
|                         &closest_barrier_data); | ||||
|  | ||||
|   if (closest_barrier_data.out.barrier_impl != NULL) | ||||
|     { | ||||
|       *barrier_impl = closest_barrier_data.out.barrier_impl; | ||||
|       return TRUE; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       return FALSE; | ||||
|     } | ||||
| } | ||||
|  | ||||
| typedef struct _MetaBarrierEventData | ||||
| { | ||||
|   guint32             time; | ||||
|   float               prev_x; | ||||
|   float               prev_y; | ||||
|   float               x; | ||||
|   float               y; | ||||
|   float               dx; | ||||
|   float               dy; | ||||
| } MetaBarrierEventData; | ||||
|  | ||||
| static void | ||||
| emit_barrier_event (MetaBarrierImplNative *self, | ||||
|                     guint32                time, | ||||
|                     float                  prev_x, | ||||
|                     float                  prev_y, | ||||
|                     float                  x, | ||||
|                     float                  y, | ||||
|                     float                  dx, | ||||
|                     float                  dy) | ||||
| { | ||||
|   MetaBarrierImplNativePrivate *priv = | ||||
|     meta_barrier_impl_native_get_instance_private (self); | ||||
|   MetaBarrier *barrier = priv->barrier; | ||||
|   MetaBarrierEvent *event = g_slice_new0 (MetaBarrierEvent); | ||||
|   MetaBarrierState old_state = priv->state; | ||||
|  | ||||
|   switch (priv->state) | ||||
|     { | ||||
|     case META_BARRIER_STATE_HIT: | ||||
|       priv->state = META_BARRIER_STATE_HELD; | ||||
|       priv->trigger_serial = next_serial (); | ||||
|       event->dt = 0; | ||||
|  | ||||
|       break; | ||||
|     case META_BARRIER_STATE_RELEASE: | ||||
|     case META_BARRIER_STATE_LEFT: | ||||
|       priv->state = META_BARRIER_STATE_ACTIVE; | ||||
|  | ||||
|       /* Intentional fall-through. */ | ||||
|     case META_BARRIER_STATE_HELD: | ||||
|       event->dt = time - priv->last_event_time; | ||||
|  | ||||
|       break; | ||||
|     case META_BARRIER_STATE_ACTIVE: | ||||
|       g_assert_not_reached (); /* Invalid state. */ | ||||
|     } | ||||
|  | ||||
|   event->ref_count = 1; | ||||
|   event->event_id = priv->trigger_serial; | ||||
|   event->time = time; | ||||
|  | ||||
|   event->x = x; | ||||
|   event->y = y; | ||||
|   event->dx = dx; | ||||
|   event->dy = dy; | ||||
|  | ||||
|   event->grabbed = priv->state == META_BARRIER_STATE_HELD; | ||||
|   event->released = old_state == META_BARRIER_STATE_RELEASE; | ||||
|  | ||||
|   priv->last_event_time = time; | ||||
|  | ||||
|   if (priv->state == META_BARRIER_STATE_HELD) | ||||
|     _meta_barrier_emit_hit_signal (barrier, event); | ||||
|   else | ||||
|     _meta_barrier_emit_left_signal (barrier, event); | ||||
|  | ||||
|   meta_barrier_event_unref (event); | ||||
| } | ||||
|  | ||||
| static void | ||||
| maybe_emit_barrier_event (gpointer key, gpointer value, gpointer user_data) | ||||
| { | ||||
|   MetaBarrierImplNative *self = key; | ||||
|   MetaBarrierImplNativePrivate *priv = | ||||
|     meta_barrier_impl_native_get_instance_private (self); | ||||
|   MetaBarrierEventData *data = user_data; | ||||
|  | ||||
|   switch (priv->state) { | ||||
|     case META_BARRIER_STATE_ACTIVE: | ||||
|       break; | ||||
|     case META_BARRIER_STATE_HIT: | ||||
|     case META_BARRIER_STATE_HELD: | ||||
|     case META_BARRIER_STATE_RELEASE: | ||||
|     case META_BARRIER_STATE_LEFT: | ||||
|       emit_barrier_event (self, | ||||
|                           data->time, | ||||
|                           data->prev_x, | ||||
|                           data->prev_y, | ||||
|                           data->x, | ||||
|                           data->y, | ||||
|                           data->dx, | ||||
|                           data->dy); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* Clamp (x, y) to the barrier and remove clamped direction from motion_dir. */ | ||||
| static void | ||||
| clamp_to_barrier (MetaBarrierImplNative *self, | ||||
|                   MetaBarrierDirection *motion_dir, | ||||
|                   float *x, | ||||
|                   float *y) | ||||
| { | ||||
|   MetaBarrierImplNativePrivate *priv = | ||||
|     meta_barrier_impl_native_get_instance_private (self); | ||||
|   MetaBarrier *barrier = priv->barrier; | ||||
|  | ||||
|   if (is_barrier_horizontal (barrier)) | ||||
|     { | ||||
|       if (*motion_dir & META_BARRIER_DIRECTION_POSITIVE_Y) | ||||
|         *y = barrier->priv->border.line.a.y; | ||||
|       else if (*motion_dir & META_BARRIER_DIRECTION_NEGATIVE_Y) | ||||
|         *y = barrier->priv->border.line.a.y; | ||||
|  | ||||
|       priv->blocked_dir = *motion_dir & (META_BARRIER_DIRECTION_POSITIVE_Y | | ||||
|                                          META_BARRIER_DIRECTION_NEGATIVE_Y); | ||||
|       *motion_dir &= ~(META_BARRIER_DIRECTION_POSITIVE_Y | | ||||
|                        META_BARRIER_DIRECTION_NEGATIVE_Y); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       if (*motion_dir & META_BARRIER_DIRECTION_POSITIVE_X) | ||||
|         *x = barrier->priv->border.line.a.x; | ||||
|       else if (*motion_dir & META_BARRIER_DIRECTION_NEGATIVE_X) | ||||
|         *x = barrier->priv->border.line.a.x; | ||||
|  | ||||
|       priv->blocked_dir = *motion_dir & (META_BARRIER_DIRECTION_POSITIVE_X | | ||||
|                                          META_BARRIER_DIRECTION_NEGATIVE_X); | ||||
|       *motion_dir &= ~(META_BARRIER_DIRECTION_POSITIVE_X | | ||||
|                        META_BARRIER_DIRECTION_NEGATIVE_X); | ||||
|     } | ||||
|  | ||||
|   priv->state = META_BARRIER_STATE_HIT; | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_barrier_manager_native_process (MetaBarrierManagerNative *manager, | ||||
|                                      ClutterInputDevice       *device, | ||||
|                                      guint32                   time, | ||||
|                                      float                    *x, | ||||
|                                      float                    *y) | ||||
| { | ||||
|   ClutterPoint prev_pos; | ||||
|   float prev_x; | ||||
|   float prev_y; | ||||
|   float orig_x = *x; | ||||
|   float orig_y = *y; | ||||
|   MetaBarrierDirection motion_dir = 0; | ||||
|   MetaBarrierEventData barrier_event_data; | ||||
|   MetaBarrierImplNative *barrier_impl; | ||||
|  | ||||
|   if (!clutter_input_device_get_coords (device, NULL, &prev_pos)) | ||||
|     return; | ||||
|  | ||||
|   prev_x = prev_pos.x; | ||||
|   prev_y = prev_pos.y; | ||||
|  | ||||
|   /* Get the direction of the motion vector. */ | ||||
|   if (prev_x < *x) | ||||
|     motion_dir |= META_BARRIER_DIRECTION_POSITIVE_X; | ||||
|   else if (prev_x > *x) | ||||
|     motion_dir |= META_BARRIER_DIRECTION_NEGATIVE_X; | ||||
|   if (prev_y < *y) | ||||
|     motion_dir |= META_BARRIER_DIRECTION_POSITIVE_Y; | ||||
|   else if (prev_y > *y) | ||||
|     motion_dir |= META_BARRIER_DIRECTION_NEGATIVE_Y; | ||||
|  | ||||
|   /* Clamp to the closest barrier in any direction until either there are no | ||||
|    * more barriers to clamp to or all directions have been clamped. */ | ||||
|   while (motion_dir != 0) | ||||
|     { | ||||
|       if (get_closest_barrier (manager, | ||||
|                                prev_x, prev_y, | ||||
|                                *x, *y, | ||||
|                                motion_dir, | ||||
|                                &barrier_impl)) | ||||
|         clamp_to_barrier (barrier_impl, &motion_dir, x, y); | ||||
|       else | ||||
|         break; | ||||
|     } | ||||
|  | ||||
|   /* Potentially release active barrier movements. */ | ||||
|   maybe_release_barriers (manager, prev_x, prev_y, *x, *y); | ||||
|  | ||||
|   /* Initiate or continue barrier interaction. */ | ||||
|   barrier_event_data = (MetaBarrierEventData) { | ||||
|     .time = time, | ||||
|     .prev_x = prev_x, | ||||
|     .prev_y = prev_y, | ||||
|     .x = *x, | ||||
|     .y = *y, | ||||
|     .dx = orig_x - prev_x, | ||||
|     .dy = orig_y - prev_y, | ||||
|   }; | ||||
|  | ||||
|   g_hash_table_foreach (manager->barriers, | ||||
|                         maybe_emit_barrier_event, | ||||
|                         &barrier_event_data); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| _meta_barrier_impl_native_is_active (MetaBarrierImpl *impl) | ||||
| { | ||||
|   MetaBarrierImplNative *self = META_BARRIER_IMPL_NATIVE (impl); | ||||
|   MetaBarrierImplNativePrivate *priv = | ||||
|     meta_barrier_impl_native_get_instance_private (self); | ||||
|  | ||||
|   return priv->is_active; | ||||
| } | ||||
|  | ||||
| static void | ||||
| _meta_barrier_impl_native_release (MetaBarrierImpl  *impl, | ||||
|                                    MetaBarrierEvent *event) | ||||
| { | ||||
|   MetaBarrierImplNative *self = META_BARRIER_IMPL_NATIVE (impl); | ||||
|   MetaBarrierImplNativePrivate *priv = | ||||
|     meta_barrier_impl_native_get_instance_private (self); | ||||
|  | ||||
|   if (priv->state == META_BARRIER_STATE_HELD && | ||||
|       event->event_id == priv->trigger_serial) | ||||
|     priv->state = META_BARRIER_STATE_RELEASE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| _meta_barrier_impl_native_destroy (MetaBarrierImpl *impl) | ||||
| { | ||||
|   MetaBarrierImplNative *self = META_BARRIER_IMPL_NATIVE (impl); | ||||
|   MetaBarrierImplNativePrivate *priv = | ||||
|     meta_barrier_impl_native_get_instance_private (self); | ||||
|  | ||||
|   g_hash_table_remove (priv->manager->barriers, self); | ||||
|   priv->is_active = FALSE; | ||||
| } | ||||
|  | ||||
| MetaBarrierImpl * | ||||
| meta_barrier_impl_native_new (MetaBarrier *barrier) | ||||
| { | ||||
|   MetaBarrierImplNative *self; | ||||
|   MetaBarrierImplNativePrivate *priv; | ||||
|   MetaBackendNative *native; | ||||
|   MetaBarrierManagerNative *manager; | ||||
|  | ||||
|   self = g_object_new (META_TYPE_BARRIER_IMPL_NATIVE, NULL); | ||||
|   priv = meta_barrier_impl_native_get_instance_private (self); | ||||
|  | ||||
|   priv->barrier = barrier; | ||||
|   priv->is_active = TRUE; | ||||
|  | ||||
|   native = META_BACKEND_NATIVE (meta_get_backend ()); | ||||
|   manager = meta_backend_native_get_barrier_manager (native); | ||||
|   priv->manager = manager; | ||||
|   g_hash_table_add (manager->barriers, self); | ||||
|  | ||||
|   return META_BARRIER_IMPL (self); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_barrier_impl_native_class_init (MetaBarrierImplNativeClass *klass) | ||||
| { | ||||
|   MetaBarrierImplClass *impl_class = META_BARRIER_IMPL_CLASS (klass); | ||||
|  | ||||
|   impl_class->is_active = _meta_barrier_impl_native_is_active; | ||||
|   impl_class->release = _meta_barrier_impl_native_release; | ||||
|   impl_class->destroy = _meta_barrier_impl_native_destroy; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_barrier_impl_native_init (MetaBarrierImplNative *self) | ||||
| { | ||||
| } | ||||
|  | ||||
| MetaBarrierManagerNative * | ||||
| meta_barrier_manager_native_new (void) | ||||
| { | ||||
|   MetaBarrierManagerNative *manager; | ||||
|  | ||||
|   manager = g_new0 (MetaBarrierManagerNative, 1); | ||||
|  | ||||
|   manager->barriers = g_hash_table_new (NULL, NULL); | ||||
|  | ||||
|   return manager; | ||||
| } | ||||
							
								
								
									
										68
									
								
								src/backends/native/meta-barrier-native.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								src/backends/native/meta-barrier-native.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2015 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Jonas Ådahl <jadahl@gmail.com> | ||||
|  */ | ||||
|  | ||||
| #ifndef META_BARRIER_NATIVE_H | ||||
| #define META_BARRIER_NATIVE_H | ||||
|  | ||||
| #include "backends/meta-barrier-private.h" | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define META_TYPE_BARRIER_IMPL_NATIVE            (meta_barrier_impl_native_get_type ()) | ||||
| #define META_BARRIER_IMPL_NATIVE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BARRIER_IMPL_NATIVE, MetaBarrierImplNative)) | ||||
| #define META_BARRIER_IMPL_NATIVE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_BARRIER_IMPL_NATIVE, MetaBarrierImplNativeClass)) | ||||
| #define META_IS_BARRIER_IMPL_NATIVE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_BARRIER_IMPL_NATIVE)) | ||||
| #define META_IS_BARRIER_IMPL_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_BARRIER_IMPL_NATIVE)) | ||||
| #define META_BARRIER_IMPL_NATIVE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_BARRIER_IMPL_NATIVE, MetaBarrierImplNativeClass)) | ||||
|  | ||||
| typedef struct _MetaBarrierImplNative        MetaBarrierImplNative; | ||||
| typedef struct _MetaBarrierImplNativeClass   MetaBarrierImplNativeClass; | ||||
| typedef struct _MetaBarrierImplNativePrivate MetaBarrierImplNativePrivate; | ||||
|  | ||||
| typedef struct _MetaBarrierManagerNative     MetaBarrierManagerNative; | ||||
|  | ||||
| struct _MetaBarrierImplNative | ||||
| { | ||||
|   MetaBarrierImpl parent; | ||||
| }; | ||||
|  | ||||
| struct _MetaBarrierImplNativeClass | ||||
| { | ||||
|   MetaBarrierImplClass parent_class; | ||||
| }; | ||||
|  | ||||
| GType meta_barrier_impl_native_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| MetaBarrierImpl *meta_barrier_impl_native_new (MetaBarrier *barrier); | ||||
|  | ||||
| MetaBarrierManagerNative *meta_barrier_manager_native_new (void); | ||||
| void meta_barrier_manager_native_process (MetaBarrierManagerNative *manager, | ||||
|                                           ClutterInputDevice       *device, | ||||
|                                           guint32                   time, | ||||
|                                           float                    *x, | ||||
|                                           float                    *y); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* META_BARRIER_NATIVE_H */ | ||||
| @@ -26,11 +26,16 @@ | ||||
|  | ||||
| #include "meta-cursor-renderer-native.h" | ||||
|  | ||||
| #include <string.h> | ||||
| #include <gbm.h> | ||||
| #include <xf86drm.h> | ||||
| #include <errno.h> | ||||
|  | ||||
| #include "meta-cursor-private.h" | ||||
| #include "meta-monitor-manager.h" | ||||
| #include <meta/util.h> | ||||
| #include <meta/meta-backend.h> | ||||
|  | ||||
| #include "meta-monitor-manager-private.h" | ||||
| #include "meta/boxes.h" | ||||
|  | ||||
| #ifndef DRM_CAP_CURSOR_WIDTH | ||||
| #define DRM_CAP_CURSOR_WIDTH 0x8 | ||||
| @@ -39,10 +44,28 @@ | ||||
| #define DRM_CAP_CURSOR_HEIGHT 0x9 | ||||
| #endif | ||||
|  | ||||
| /* When animating a cursor, we usually call drmModeSetCursor2 once per frame. | ||||
|  * Though, testing shows that we need to triple buffer the cursor buffer in | ||||
|  * order to avoid glitches when animating the cursor, at least when running on | ||||
|  * Intel. The reason for this might be (but is not confirmed to be) due to | ||||
|  * the user space gbm_bo cache, making us reuse and overwrite the kernel side | ||||
|  * buffer content before it was scanned out. To avoid this, we keep a user space | ||||
|  * reference to each buffer we set until at least one frame after it was drawn. | ||||
|  * In effect, this means we three active cursor gbm_bo's: one that that just has | ||||
|  * been set, one that was previously set and may or may not have been scanned | ||||
|  * out, and one pending that will be replaced if the cursor sprite changes. | ||||
|  */ | ||||
| #define HW_CURSOR_BUFFER_COUNT 3 | ||||
|  | ||||
| static GQuark quark_cursor_sprite = 0; | ||||
|  | ||||
| struct _MetaCursorRendererNativePrivate | ||||
| { | ||||
|   gboolean has_hw_cursor; | ||||
|  | ||||
|   MetaCursorSprite *last_cursor; | ||||
|   guint animation_timeout_id; | ||||
|  | ||||
|   int drm_fd; | ||||
|   struct gbm_device *gbm; | ||||
|  | ||||
| @@ -51,77 +74,167 @@ struct _MetaCursorRendererNativePrivate | ||||
| }; | ||||
| typedef struct _MetaCursorRendererNativePrivate MetaCursorRendererNativePrivate; | ||||
|  | ||||
| typedef enum _MetaCursorGbmBoState | ||||
| { | ||||
|   META_CURSOR_GBM_BO_STATE_NONE, | ||||
|   META_CURSOR_GBM_BO_STATE_SET, | ||||
|   META_CURSOR_GBM_BO_STATE_INVALIDATED, | ||||
| } MetaCursorGbmBoState; | ||||
|  | ||||
| typedef struct _MetaCursorNativePrivate | ||||
| { | ||||
|   guint active_bo; | ||||
|   MetaCursorGbmBoState pending_bo_state; | ||||
|   struct gbm_bo *bos[HW_CURSOR_BUFFER_COUNT]; | ||||
| } MetaCursorNativePrivate; | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRendererNative, meta_cursor_renderer_native, META_TYPE_CURSOR_RENDERER); | ||||
|  | ||||
| static MetaCursorNativePrivate * | ||||
| ensure_cursor_priv (MetaCursorSprite *cursor_sprite); | ||||
|  | ||||
| static void | ||||
| meta_cursor_renderer_native_finalize (GObject *object) | ||||
| { | ||||
|   MetaCursorRendererNative *renderer = META_CURSOR_RENDERER_NATIVE (object); | ||||
|   MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (renderer); | ||||
|  | ||||
|   if (priv->gbm) | ||||
|     gbm_device_destroy (priv->gbm); | ||||
|   if (priv->animation_timeout_id) | ||||
|     g_source_remove (priv->animation_timeout_id); | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_cursor_renderer_native_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| static guint | ||||
| get_pending_cursor_sprite_gbm_bo_index (MetaCursorSprite *cursor_sprite) | ||||
| { | ||||
|   MetaCursorNativePrivate *cursor_priv = | ||||
|     g_object_get_qdata (G_OBJECT (cursor_sprite), quark_cursor_sprite); | ||||
|  | ||||
|   return (cursor_priv->active_bo + 1) % HW_CURSOR_BUFFER_COUNT; | ||||
| } | ||||
|  | ||||
| static struct gbm_bo * | ||||
| get_pending_cursor_sprite_gbm_bo (MetaCursorSprite *cursor_sprite) | ||||
| { | ||||
|   MetaCursorNativePrivate *cursor_priv = | ||||
|     g_object_get_qdata (G_OBJECT (cursor_sprite), quark_cursor_sprite); | ||||
|   guint pending_bo; | ||||
|  | ||||
|   if (!cursor_priv) | ||||
|     return NULL; | ||||
|  | ||||
|   pending_bo = get_pending_cursor_sprite_gbm_bo_index (cursor_sprite); | ||||
|   return cursor_priv->bos[pending_bo]; | ||||
| } | ||||
|  | ||||
| static struct gbm_bo * | ||||
| get_active_cursor_sprite_gbm_bo (MetaCursorSprite *cursor_sprite) | ||||
| { | ||||
|   MetaCursorNativePrivate *cursor_priv = | ||||
|     g_object_get_qdata (G_OBJECT (cursor_sprite), quark_cursor_sprite); | ||||
|  | ||||
|   if (!cursor_priv) | ||||
|     return NULL; | ||||
|  | ||||
|   return cursor_priv->bos[cursor_priv->active_bo]; | ||||
| } | ||||
|  | ||||
| static void | ||||
| set_pending_cursor_sprite_gbm_bo (MetaCursorSprite *cursor_sprite, | ||||
|                                   struct gbm_bo    *bo) | ||||
| { | ||||
|   MetaCursorNativePrivate *cursor_priv; | ||||
|   guint pending_bo; | ||||
|  | ||||
|   cursor_priv = ensure_cursor_priv (cursor_sprite); | ||||
|  | ||||
|   pending_bo = get_pending_cursor_sprite_gbm_bo_index (cursor_sprite); | ||||
|   cursor_priv->bos[pending_bo] = bo; | ||||
|   cursor_priv->pending_bo_state = META_CURSOR_GBM_BO_STATE_SET; | ||||
| } | ||||
|  | ||||
| static void | ||||
| set_crtc_cursor (MetaCursorRendererNative *native, | ||||
|                  MetaCRTC                 *crtc, | ||||
|                  MetaCursorReference      *cursor, | ||||
|                  MetaCursorSprite         *cursor_sprite, | ||||
|                  gboolean                  force) | ||||
| { | ||||
|   MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native); | ||||
|  | ||||
|   if (crtc->cursor == cursor && !force) | ||||
|     return; | ||||
|  | ||||
|   crtc->cursor = cursor; | ||||
|  | ||||
|   if (cursor) | ||||
|   if (cursor_sprite) | ||||
|     { | ||||
|       MetaCursorNativePrivate *cursor_priv = | ||||
|         g_object_get_qdata (G_OBJECT (cursor_sprite), quark_cursor_sprite); | ||||
|       struct gbm_bo *bo; | ||||
|       union gbm_bo_handle handle; | ||||
|       int hot_x, hot_y; | ||||
|  | ||||
|       bo = meta_cursor_reference_get_gbm_bo (cursor, &hot_x, &hot_y); | ||||
|       if (cursor_priv->pending_bo_state == META_CURSOR_GBM_BO_STATE_SET) | ||||
|         bo = get_pending_cursor_sprite_gbm_bo (cursor_sprite); | ||||
|       else | ||||
|         bo = get_active_cursor_sprite_gbm_bo (cursor_sprite); | ||||
|  | ||||
|       if (!force && bo == crtc->cursor_renderer_private) | ||||
|         return; | ||||
|  | ||||
|       crtc->cursor_renderer_private = bo; | ||||
|  | ||||
|       handle = gbm_bo_get_handle (bo); | ||||
|       meta_cursor_sprite_get_hotspot (cursor_sprite, &hot_x, &hot_y); | ||||
|  | ||||
|       drmModeSetCursor2 (priv->drm_fd, crtc->crtc_id, handle.u32, | ||||
|                          priv->cursor_width, priv->cursor_height, hot_x, hot_y); | ||||
|  | ||||
|       if (cursor_priv->pending_bo_state == META_CURSOR_GBM_BO_STATE_SET) | ||||
|         { | ||||
|           cursor_priv->active_bo = | ||||
|             (cursor_priv->active_bo + 1) % HW_CURSOR_BUFFER_COUNT; | ||||
|           cursor_priv->pending_bo_state = META_CURSOR_GBM_BO_STATE_NONE; | ||||
|         } | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       drmModeSetCursor2 (priv->drm_fd, crtc->crtc_id, 0, 0, 0, 0, 0); | ||||
|       if (force || crtc->cursor_renderer_private != NULL) | ||||
|         { | ||||
|           drmModeSetCursor2 (priv->drm_fd, crtc->crtc_id, 0, 0, 0, 0, 0); | ||||
|           crtc->cursor_renderer_private = NULL; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_hw_cursor (MetaCursorRendererNative *native, | ||||
|                   MetaCursorSprite         *cursor_sprite, | ||||
|                   gboolean                  force) | ||||
| { | ||||
|   MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native); | ||||
|   MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native); | ||||
|   const MetaRectangle *cursor_rect = meta_cursor_renderer_get_rect (renderer); | ||||
|   MetaCursorReference *cursor = meta_cursor_renderer_get_cursor (renderer); | ||||
|   MetaMonitorManager *monitors; | ||||
|   MetaCRTC *crtcs; | ||||
|   unsigned int i, n_crtcs; | ||||
|   MetaRectangle rect; | ||||
|  | ||||
|   monitors = meta_monitor_manager_get (); | ||||
|   meta_monitor_manager_get_resources (monitors, NULL, NULL, &crtcs, &n_crtcs, NULL, NULL); | ||||
|  | ||||
|   if (cursor_sprite) | ||||
|     rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite); | ||||
|   else | ||||
|     rect = (MetaRectangle) { 0 }; | ||||
|  | ||||
|   for (i = 0; i < n_crtcs; i++) | ||||
|     { | ||||
|       gboolean crtc_should_have_cursor; | ||||
|       MetaCursorReference *crtc_cursor; | ||||
|       gboolean crtc_should_use_cursor; | ||||
|       MetaCursorSprite *crtc_cursor; | ||||
|       MetaRectangle *crtc_rect; | ||||
|  | ||||
|       crtc_rect = &crtcs[i].rect; | ||||
|  | ||||
|       crtc_should_have_cursor = (priv->has_hw_cursor && meta_rectangle_overlap (cursor_rect, crtc_rect)); | ||||
|       if (crtc_should_have_cursor) | ||||
|         crtc_cursor = cursor; | ||||
|       crtc_should_use_cursor = (priv->has_hw_cursor && | ||||
|                                 meta_rectangle_overlap (&rect, crtc_rect)); | ||||
|       if (crtc_should_use_cursor) | ||||
|         crtc_cursor = cursor_sprite; | ||||
|       else | ||||
|         crtc_cursor = NULL; | ||||
|  | ||||
| @@ -130,34 +243,382 @@ update_hw_cursor (MetaCursorRendererNative *native, | ||||
|       if (crtc_cursor) | ||||
|         { | ||||
|           drmModeMoveCursor (priv->drm_fd, crtcs[i].crtc_id, | ||||
|                              cursor_rect->x - crtc_rect->x, | ||||
|                              cursor_rect->y - crtc_rect->y); | ||||
|                              rect.x - crtc_rect->x, | ||||
|                              rect.y - crtc_rect->y); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| should_have_hw_cursor (MetaCursorRenderer *renderer) | ||||
| has_valid_cursor_sprite_gbm_bo (MetaCursorSprite *cursor_sprite) | ||||
| { | ||||
|   MetaCursorReference *cursor = meta_cursor_renderer_get_cursor (renderer); | ||||
|   MetaCursorNativePrivate *cursor_priv = | ||||
|     g_object_get_qdata (G_OBJECT (cursor_sprite), quark_cursor_sprite); | ||||
|  | ||||
|   if (cursor) | ||||
|     return (meta_cursor_reference_get_gbm_bo (cursor, NULL, NULL) != NULL); | ||||
|   else | ||||
|   if (!cursor_priv) | ||||
|     return FALSE; | ||||
|  | ||||
|   switch (cursor_priv->pending_bo_state) | ||||
|     { | ||||
|     case META_CURSOR_GBM_BO_STATE_NONE: | ||||
|       return get_active_cursor_sprite_gbm_bo (cursor_sprite) != NULL; | ||||
|     case META_CURSOR_GBM_BO_STATE_SET: | ||||
|       return TRUE; | ||||
|     case META_CURSOR_GBM_BO_STATE_INVALIDATED: | ||||
|       return FALSE; | ||||
|     } | ||||
|  | ||||
|   g_assert_not_reached (); | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer) | ||||
| cursor_over_transformed_crtc (MetaCursorRenderer *renderer, | ||||
|                               MetaCursorSprite   *cursor_sprite) | ||||
| { | ||||
|   MetaMonitorManager *monitors; | ||||
|   MetaCRTC *crtcs; | ||||
|   unsigned int i, n_crtcs; | ||||
|   MetaRectangle rect; | ||||
|  | ||||
|   monitors = meta_monitor_manager_get (); | ||||
|   meta_monitor_manager_get_resources (monitors, NULL, NULL, | ||||
|                                       &crtcs, &n_crtcs, NULL, NULL); | ||||
|   rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite); | ||||
|  | ||||
|   for (i = 0; i < n_crtcs; i++) | ||||
|     { | ||||
|       if (!meta_rectangle_overlap (&rect, &crtcs[i].rect)) | ||||
|         continue; | ||||
|  | ||||
|       if (crtcs[i].transform != META_MONITOR_TRANSFORM_NORMAL) | ||||
|         return TRUE; | ||||
|     } | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| should_have_hw_cursor (MetaCursorRenderer *renderer, | ||||
|                        MetaCursorSprite   *cursor_sprite) | ||||
| { | ||||
|   CoglTexture *texture; | ||||
|  | ||||
|   if (!cursor_sprite) | ||||
|     return FALSE; | ||||
|  | ||||
|   if (cursor_over_transformed_crtc (renderer, cursor_sprite)) | ||||
|     return FALSE; | ||||
|  | ||||
|   texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite); | ||||
|   if (!texture) | ||||
|     return FALSE; | ||||
|  | ||||
|   if (meta_cursor_sprite_get_texture_scale (cursor_sprite) != 1) | ||||
|     return FALSE; | ||||
|  | ||||
|   if (!has_valid_cursor_sprite_gbm_bo (cursor_sprite)) | ||||
|     return FALSE; | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_cursor_renderer_native_update_animation (MetaCursorRendererNative *native) | ||||
| { | ||||
|   MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native); | ||||
|   MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native); | ||||
|   MetaCursorSprite *cursor_sprite = meta_cursor_renderer_get_cursor (renderer); | ||||
|  | ||||
|   priv->animation_timeout_id = 0; | ||||
|   meta_cursor_sprite_tick_frame (cursor_sprite); | ||||
|   meta_cursor_renderer_force_update (renderer); | ||||
|  | ||||
|   return G_SOURCE_REMOVE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_cursor_renderer_native_trigger_frame (MetaCursorRendererNative *native, | ||||
|                                            MetaCursorSprite         *cursor_sprite) | ||||
| { | ||||
|   MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native); | ||||
|   gboolean cursor_change; | ||||
|   guint delay; | ||||
|  | ||||
|   cursor_change = cursor_sprite != priv->last_cursor; | ||||
|   priv->last_cursor = cursor_sprite; | ||||
|  | ||||
|   if (!cursor_change && priv->animation_timeout_id) | ||||
|     return; | ||||
|  | ||||
|   if (priv->animation_timeout_id) | ||||
|     { | ||||
|       g_source_remove (priv->animation_timeout_id); | ||||
|       priv->animation_timeout_id = 0; | ||||
|     } | ||||
|  | ||||
|   if (cursor_sprite && meta_cursor_sprite_is_animated (cursor_sprite)) | ||||
|     { | ||||
|       delay = meta_cursor_sprite_get_current_frame_time (cursor_sprite); | ||||
|  | ||||
|       if (delay == 0) | ||||
|         return; | ||||
|  | ||||
|       priv->animation_timeout_id = | ||||
|         g_timeout_add (delay, | ||||
|                        (GSourceFunc) meta_cursor_renderer_native_update_animation, | ||||
|                        native); | ||||
|       g_source_set_name_by_id (priv->animation_timeout_id, | ||||
|                                "[mutter] meta_cursor_renderer_native_update_animation"); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer, | ||||
|                                            MetaCursorSprite   *cursor_sprite) | ||||
| { | ||||
|   MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer); | ||||
|   MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native); | ||||
|  | ||||
|   priv->has_hw_cursor = should_have_hw_cursor (renderer); | ||||
|   update_hw_cursor (native, FALSE); | ||||
|   if (cursor_sprite) | ||||
|     meta_cursor_sprite_realize_texture (cursor_sprite); | ||||
|  | ||||
|   meta_cursor_renderer_native_trigger_frame (native, cursor_sprite); | ||||
|  | ||||
|   priv->has_hw_cursor = should_have_hw_cursor (renderer, cursor_sprite); | ||||
|   update_hw_cursor (native, cursor_sprite, FALSE); | ||||
|   return priv->has_hw_cursor; | ||||
| } | ||||
|  | ||||
| static void | ||||
| get_hardware_cursor_size (MetaCursorRendererNative *native, | ||||
|                           uint64_t *width, uint64_t *height) | ||||
| { | ||||
|   MetaCursorRendererNativePrivate *priv = | ||||
|     meta_cursor_renderer_native_get_instance_private (native); | ||||
|  | ||||
|   *width = priv->cursor_width; | ||||
|   *height = priv->cursor_height; | ||||
| } | ||||
|  | ||||
| static void | ||||
| cursor_priv_free (gpointer data) | ||||
| { | ||||
|   MetaCursorNativePrivate *cursor_priv = data; | ||||
|   guint i; | ||||
|  | ||||
|   if (!data) | ||||
|     return; | ||||
|  | ||||
|   for (i = 0; i < HW_CURSOR_BUFFER_COUNT; i++) | ||||
|     g_clear_pointer (&cursor_priv->bos[0], (GDestroyNotify) gbm_bo_destroy); | ||||
|   g_slice_free (MetaCursorNativePrivate, cursor_priv); | ||||
| } | ||||
|  | ||||
| static MetaCursorNativePrivate * | ||||
| ensure_cursor_priv (MetaCursorSprite *cursor_sprite) | ||||
| { | ||||
|   MetaCursorNativePrivate *cursor_priv = | ||||
|     g_object_get_qdata (G_OBJECT (cursor_sprite), quark_cursor_sprite); | ||||
|  | ||||
|   if (!cursor_priv) | ||||
|     { | ||||
|       cursor_priv = g_slice_new0 (MetaCursorNativePrivate); | ||||
|       g_object_set_qdata_full (G_OBJECT (cursor_sprite), | ||||
|                                quark_cursor_sprite, | ||||
|                                cursor_priv, | ||||
|                                cursor_priv_free); | ||||
|     } | ||||
|  | ||||
|   return cursor_priv; | ||||
| } | ||||
|  | ||||
| static void | ||||
| load_cursor_sprite_gbm_buffer (MetaCursorRendererNative *native, | ||||
|                                MetaCursorSprite         *cursor_sprite, | ||||
|                                uint8_t                  *pixels, | ||||
|                                uint                      width, | ||||
|                                uint                      height, | ||||
|                                int                       rowstride, | ||||
|                                uint32_t                  gbm_format) | ||||
| { | ||||
|   MetaCursorRendererNativePrivate *priv = | ||||
|     meta_cursor_renderer_native_get_instance_private (native); | ||||
|   uint64_t cursor_width, cursor_height; | ||||
|  | ||||
|   get_hardware_cursor_size (native, &cursor_width, &cursor_height); | ||||
|  | ||||
|   if (width > cursor_width || height > cursor_height) | ||||
|     { | ||||
|       meta_warning ("Invalid theme cursor size (must be at most %ux%u)\n", | ||||
|                     (unsigned int)cursor_width, (unsigned int)cursor_height); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   if (gbm_device_is_format_supported (priv->gbm, gbm_format, | ||||
|                                       GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE)) | ||||
|     { | ||||
|       struct gbm_bo *bo; | ||||
|       uint8_t buf[4 * cursor_width * cursor_height]; | ||||
|       uint i; | ||||
|  | ||||
|       bo = gbm_bo_create (priv->gbm, cursor_width, cursor_height, | ||||
|                           gbm_format, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE); | ||||
|       if (!bo) | ||||
|         { | ||||
|           meta_warning ("Failed to allocate HW cursor buffer\n"); | ||||
|           return; | ||||
|         } | ||||
|  | ||||
|       memset (buf, 0, sizeof(buf)); | ||||
|       for (i = 0; i < height; i++) | ||||
|         memcpy (buf + i * 4 * cursor_width, pixels + i * rowstride, width * 4); | ||||
|       if (gbm_bo_write (bo, buf, cursor_width * cursor_height * 4) != 0) | ||||
|         { | ||||
|           meta_warning ("Failed to write cursors buffer data: %s", | ||||
|                         g_strerror (errno)); | ||||
|           gbm_bo_destroy (bo); | ||||
|           return; | ||||
|         } | ||||
|  | ||||
|       set_pending_cursor_sprite_gbm_bo (cursor_sprite, bo); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       meta_warning ("HW cursor for format %d not supported\n", gbm_format); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| invalidate_pending_cursor_sprite_gbm_bo (MetaCursorSprite *cursor_sprite) | ||||
| { | ||||
|   MetaCursorNativePrivate *cursor_priv = | ||||
|     g_object_get_qdata (G_OBJECT (cursor_sprite), quark_cursor_sprite); | ||||
|   guint pending_bo; | ||||
|  | ||||
|   if (!cursor_priv) | ||||
|     return; | ||||
|  | ||||
|   pending_bo = get_pending_cursor_sprite_gbm_bo_index (cursor_sprite); | ||||
|   g_clear_pointer (&cursor_priv->bos[pending_bo], | ||||
|                    (GDestroyNotify) gbm_bo_destroy); | ||||
|   cursor_priv->pending_bo_state = META_CURSOR_GBM_BO_STATE_INVALIDATED; | ||||
| } | ||||
|  | ||||
| #ifdef HAVE_WAYLAND | ||||
| static void | ||||
| meta_cursor_renderer_native_realize_cursor_from_wl_buffer (MetaCursorRenderer *renderer, | ||||
|                                                            MetaCursorSprite *cursor_sprite, | ||||
|                                                            struct wl_resource *buffer) | ||||
| { | ||||
|   MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer); | ||||
|   MetaCursorRendererNativePrivate *priv = | ||||
|     meta_cursor_renderer_native_get_instance_private (native); | ||||
|   uint32_t gbm_format; | ||||
|   uint64_t cursor_width, cursor_height; | ||||
|   CoglTexture *texture; | ||||
|   uint width, height; | ||||
|  | ||||
|   /* Destroy any previous pending cursor buffer; we'll always either fail (which | ||||
|    * should unset, or succeed, which will set new buffer. | ||||
|    */ | ||||
|   invalidate_pending_cursor_sprite_gbm_bo (cursor_sprite); | ||||
|  | ||||
|   texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite); | ||||
|   width = cogl_texture_get_width (texture); | ||||
|   height = cogl_texture_get_height (texture); | ||||
|  | ||||
|   struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (buffer); | ||||
|   if (shm_buffer) | ||||
|     { | ||||
|       int rowstride = wl_shm_buffer_get_stride (shm_buffer); | ||||
|       uint8_t *buffer_data; | ||||
|  | ||||
|       wl_shm_buffer_begin_access (shm_buffer); | ||||
|  | ||||
|       switch (wl_shm_buffer_get_format (shm_buffer)) | ||||
|         { | ||||
| #if G_BYTE_ORDER == G_BIG_ENDIAN | ||||
|         case WL_SHM_FORMAT_ARGB8888: | ||||
|           gbm_format = GBM_FORMAT_ARGB8888; | ||||
|           break; | ||||
|         case WL_SHM_FORMAT_XRGB8888: | ||||
|           gbm_format = GBM_FORMAT_XRGB8888; | ||||
|           break; | ||||
| #else | ||||
|         case WL_SHM_FORMAT_ARGB8888: | ||||
|           gbm_format = GBM_FORMAT_ARGB8888; | ||||
|           break; | ||||
|         case WL_SHM_FORMAT_XRGB8888: | ||||
|           gbm_format = GBM_FORMAT_XRGB8888; | ||||
|           break; | ||||
| #endif | ||||
|         default: | ||||
|           g_warn_if_reached (); | ||||
|           gbm_format = GBM_FORMAT_ARGB8888; | ||||
|         } | ||||
|  | ||||
|       buffer_data = wl_shm_buffer_get_data (shm_buffer); | ||||
|       load_cursor_sprite_gbm_buffer (native, | ||||
|                                      cursor_sprite, | ||||
|                                      buffer_data, | ||||
|                                      width, height, rowstride, | ||||
|                                      gbm_format); | ||||
|  | ||||
|       wl_shm_buffer_end_access (shm_buffer); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       struct gbm_bo *bo; | ||||
|  | ||||
|       /* HW cursors have a predefined size (at least 64x64), which usually is | ||||
|        * bigger than cursor theme size, so themed cursors must be padded with | ||||
|        * transparent pixels to fill the overlay. This is trivial if we have CPU | ||||
|        * access to the data, but it's not possible if the buffer is in GPU | ||||
|        * memory (and possibly tiled too), so if we don't get the right size, we | ||||
|        * fallback to GL. */ | ||||
|       get_hardware_cursor_size (native, &cursor_width, &cursor_height); | ||||
|  | ||||
|       if (width != cursor_width || height != cursor_height) | ||||
|         { | ||||
|           meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n"); | ||||
|           return; | ||||
|         } | ||||
|  | ||||
|       bo = gbm_bo_import (priv->gbm, | ||||
|                           GBM_BO_IMPORT_WL_BUFFER, | ||||
|                           buffer, | ||||
|                           GBM_BO_USE_CURSOR); | ||||
|       if (!bo) | ||||
|         { | ||||
|           meta_warning ("Importing HW cursor from wl_buffer failed\n"); | ||||
|           return; | ||||
|         } | ||||
|  | ||||
|       set_pending_cursor_sprite_gbm_bo (cursor_sprite, bo); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
|  | ||||
| static void | ||||
| meta_cursor_renderer_native_realize_cursor_from_xcursor (MetaCursorRenderer *renderer, | ||||
|                                                          MetaCursorSprite *cursor_sprite, | ||||
|                                                          XcursorImage *xc_image) | ||||
| { | ||||
|   MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer); | ||||
|  | ||||
|   invalidate_pending_cursor_sprite_gbm_bo (cursor_sprite); | ||||
|  | ||||
|   load_cursor_sprite_gbm_buffer (native, | ||||
|                                  cursor_sprite, | ||||
|                                  (uint8_t *) xc_image->pixels, | ||||
|                                  xc_image->width, | ||||
|                                  xc_image->height, | ||||
|                                  xc_image->width * 4, | ||||
|                                  GBM_FORMAT_ARGB8888); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_cursor_renderer_native_class_init (MetaCursorRendererNativeClass *klass) | ||||
| { | ||||
| @@ -166,6 +627,22 @@ meta_cursor_renderer_native_class_init (MetaCursorRendererNativeClass *klass) | ||||
|  | ||||
|   object_class->finalize = meta_cursor_renderer_native_finalize; | ||||
|   renderer_class->update_cursor = meta_cursor_renderer_native_update_cursor; | ||||
| #ifdef HAVE_WAYLAND | ||||
|   renderer_class->realize_cursor_from_wl_buffer = | ||||
|     meta_cursor_renderer_native_realize_cursor_from_wl_buffer; | ||||
| #endif | ||||
|   renderer_class->realize_cursor_from_xcursor = | ||||
|     meta_cursor_renderer_native_realize_cursor_from_xcursor; | ||||
|  | ||||
|   quark_cursor_sprite = g_quark_from_static_string ("-meta-cursor-native"); | ||||
| } | ||||
|  | ||||
| static void | ||||
| force_update_hw_cursor (MetaCursorRendererNative *native) | ||||
| { | ||||
|   MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native); | ||||
|  | ||||
|   update_hw_cursor (native, meta_cursor_renderer_get_cursor (renderer), TRUE); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -173,7 +650,7 @@ on_monitors_changed (MetaMonitorManager       *monitors, | ||||
|                      MetaCursorRendererNative *native) | ||||
| { | ||||
|   /* Our tracking is all messed up, so force an update. */ | ||||
|   update_hw_cursor (native, TRUE); | ||||
|   force_update_hw_cursor (native); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -192,7 +669,7 @@ meta_cursor_renderer_native_init (MetaCursorRendererNative *native) | ||||
|     { | ||||
|       CoglRenderer *cogl_renderer = cogl_display_get_renderer (cogl_context_get_display (ctx)); | ||||
|       priv->drm_fd = cogl_kms_renderer_get_kms_fd (cogl_renderer); | ||||
|       priv->gbm = gbm_create_device (priv->drm_fd); | ||||
|       priv->gbm = cogl_kms_renderer_get_gbm (cogl_renderer); | ||||
|  | ||||
|       uint64_t width, height; | ||||
|       if (drmGetCap (priv->drm_fd, DRM_CAP_CURSOR_WIDTH, &width) == 0 && | ||||
| @@ -218,18 +695,8 @@ meta_cursor_renderer_native_get_gbm_device (MetaCursorRendererNative *native) | ||||
|   return priv->gbm; | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_renderer_native_get_cursor_size (MetaCursorRendererNative *native, | ||||
|                                              uint64_t *width, uint64_t *height) | ||||
| { | ||||
|   MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native); | ||||
|  | ||||
|   *width = priv->cursor_width; | ||||
|   *height = priv->cursor_height; | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_renderer_native_force_update (MetaCursorRendererNative *native) | ||||
| { | ||||
|   update_hw_cursor (native, TRUE); | ||||
|   force_update_hw_cursor (native); | ||||
| } | ||||
|   | ||||
| @@ -164,56 +164,36 @@ meta_idle_monitor_native_init (MetaIdleMonitorNative *monitor_native) | ||||
|   monitor->watches = g_hash_table_new_full (NULL, NULL, NULL, free_watch); | ||||
| } | ||||
|  | ||||
| typedef struct { | ||||
|   MetaIdleMonitorNative *monitor_native; | ||||
|   GList *fired_watches; | ||||
| } CheckNativeClosure; | ||||
|  | ||||
| static gboolean | ||||
| check_native_watch (gpointer key, | ||||
|                     gpointer value, | ||||
|                     gpointer user_data) | ||||
| { | ||||
|   MetaIdleMonitorWatchNative *watch_native = value; | ||||
|   MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_native; | ||||
|   CheckNativeClosure *closure = user_data; | ||||
|   gboolean steal; | ||||
|  | ||||
|   if (watch->timeout_msec == 0) | ||||
|     { | ||||
|       closure->fired_watches = g_list_prepend (closure->fired_watches, watch); | ||||
|       steal = TRUE; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       g_source_set_ready_time (watch_native->timeout_source, | ||||
|                                closure->monitor_native->last_event_time + | ||||
|                                watch->timeout_msec * 1000); | ||||
|       steal = FALSE; | ||||
|     } | ||||
|  | ||||
|   return steal; | ||||
| } | ||||
|  | ||||
| static void | ||||
| fire_native_watch (gpointer watch, | ||||
|                    gpointer data) | ||||
| { | ||||
|   _meta_idle_monitor_watch_fire (watch); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_idle_monitor_native_reset_idletime (MetaIdleMonitor *monitor) | ||||
| { | ||||
|   MetaIdleMonitorNative *monitor_native = META_IDLE_MONITOR_NATIVE (monitor); | ||||
|   CheckNativeClosure closure; | ||||
|   GList *node, *watch_ids; | ||||
|  | ||||
|   monitor_native->last_event_time = g_get_monotonic_time (); | ||||
|  | ||||
|   closure.monitor_native = monitor_native; | ||||
|   closure.fired_watches = NULL; | ||||
|   g_hash_table_foreach_steal (monitor->watches, check_native_watch, &closure); | ||||
|   watch_ids = g_hash_table_get_keys (monitor->watches); | ||||
|  | ||||
|   g_list_foreach (closure.fired_watches, fire_native_watch, NULL); | ||||
|   g_list_free (closure.fired_watches); | ||||
|   for (node = watch_ids; node != NULL; node = node->next) | ||||
|     { | ||||
|       guint watch_id = GPOINTER_TO_UINT (node->data); | ||||
|       MetaIdleMonitorWatchNative *watch; | ||||
|  | ||||
|       watch = g_hash_table_lookup (monitor->watches, GUINT_TO_POINTER (watch_id)); | ||||
|       if (!watch) | ||||
|         continue; | ||||
|  | ||||
|       if (watch->base.timeout_msec == 0) | ||||
|         { | ||||
|           _meta_idle_monitor_watch_fire ((MetaIdleMonitorWatch *) watch); | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           g_source_set_ready_time (watch->timeout_source, | ||||
|                                    monitor_native->last_event_time + | ||||
|                                    watch->base.timeout_msec * 1000); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   g_list_free (watch_ids); | ||||
| } | ||||
|   | ||||
							
								
								
									
										264
									
								
								src/backends/native/meta-input-settings-native.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										264
									
								
								src/backends/native/meta-input-settings-native.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,264 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2014 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Author: Carlos Garnacho <carlosg@gnome.org> | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include <clutter/evdev/clutter-evdev.h> | ||||
| #include <libinput.h> | ||||
|  | ||||
| #include "meta-input-settings-native.h" | ||||
|  | ||||
| G_DEFINE_TYPE (MetaInputSettingsNative, meta_input_settings_native, META_TYPE_INPUT_SETTINGS) | ||||
|  | ||||
| static void | ||||
| meta_input_settings_native_set_send_events (MetaInputSettings        *settings, | ||||
|                                             ClutterInputDevice       *device, | ||||
|                                             GDesktopDeviceSendEvents  mode) | ||||
| { | ||||
|   enum libinput_config_send_events_mode libinput_mode; | ||||
|   struct libinput_device *libinput_device; | ||||
|  | ||||
|   switch (mode) | ||||
|     { | ||||
|     case G_DESKTOP_DEVICE_SEND_EVENTS_DISABLED: | ||||
|       libinput_mode = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED; | ||||
|       break; | ||||
|     case G_DESKTOP_DEVICE_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE: | ||||
|       libinput_mode = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE; | ||||
|       break; | ||||
|     case G_DESKTOP_DEVICE_SEND_EVENTS_ENABLED: | ||||
|       libinput_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; | ||||
|       break; | ||||
|     default: | ||||
|       g_assert_not_reached (); | ||||
|     } | ||||
|  | ||||
|   libinput_device = clutter_evdev_input_device_get_libinput_device (device); | ||||
|   libinput_device_config_send_events_set_mode (libinput_device, libinput_mode); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_settings_native_set_matrix (MetaInputSettings  *settings, | ||||
|                                        ClutterInputDevice *device, | ||||
|                                        gfloat              matrix[6]) | ||||
| { | ||||
|   struct libinput_device *libinput_device; | ||||
|  | ||||
|   libinput_device = clutter_evdev_input_device_get_libinput_device (device); | ||||
|  | ||||
|   if (libinput_device_config_calibration_has_matrix (libinput_device) > 0) | ||||
|     libinput_device_config_calibration_set_matrix (libinput_device, matrix); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_settings_native_set_speed (MetaInputSettings  *settings, | ||||
|                                       ClutterInputDevice *device, | ||||
|                                       gdouble             speed) | ||||
| { | ||||
|   struct libinput_device *libinput_device; | ||||
|  | ||||
|   libinput_device = clutter_evdev_input_device_get_libinput_device (device); | ||||
|   libinput_device_config_accel_set_speed (libinput_device, | ||||
|                                           CLAMP (speed, -1, 1)); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_settings_native_set_left_handed (MetaInputSettings  *settings, | ||||
|                                             ClutterInputDevice *device, | ||||
|                                             gboolean            enabled) | ||||
| { | ||||
|   struct libinput_device *libinput_device; | ||||
|  | ||||
|   libinput_device = clutter_evdev_input_device_get_libinput_device (device); | ||||
|  | ||||
|   if (libinput_device_config_left_handed_is_available (libinput_device)) | ||||
|     libinput_device_config_left_handed_set (libinput_device, enabled); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_settings_native_set_tap_enabled (MetaInputSettings  *settings, | ||||
|                                             ClutterInputDevice *device, | ||||
|                                             gboolean            enabled) | ||||
| { | ||||
|   struct libinput_device *libinput_device; | ||||
|  | ||||
|   libinput_device = clutter_evdev_input_device_get_libinput_device (device); | ||||
|  | ||||
|   if (libinput_device_config_tap_get_finger_count (libinput_device) > 0) | ||||
|     libinput_device_config_tap_set_enabled (libinput_device, | ||||
|                                             enabled ? | ||||
|                                             LIBINPUT_CONFIG_TAP_ENABLED : | ||||
|                                             LIBINPUT_CONFIG_TAP_DISABLED); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_settings_native_set_invert_scroll (MetaInputSettings  *settings, | ||||
|                                               ClutterInputDevice *device, | ||||
|                                               gboolean            inverted) | ||||
| { | ||||
|   struct libinput_device *libinput_device; | ||||
|  | ||||
|   libinput_device = clutter_evdev_input_device_get_libinput_device (device); | ||||
|  | ||||
|   if (libinput_device_config_scroll_has_natural_scroll (libinput_device)) | ||||
|     libinput_device_config_scroll_set_natural_scroll_enabled (libinput_device, | ||||
|                                                               inverted); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| device_set_scroll_method (struct libinput_device             *libinput_device, | ||||
|                           enum libinput_config_scroll_method  method) | ||||
| { | ||||
|   enum libinput_config_scroll_method supported; | ||||
|  | ||||
|   supported = libinput_device_config_scroll_get_methods (libinput_device); | ||||
|  | ||||
|   if (method & supported) | ||||
|     libinput_device_config_scroll_set_method (libinput_device, method); | ||||
|  | ||||
|   return (method & supported) != 0; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| device_set_click_method (struct libinput_device            *libinput_device, | ||||
|                          enum libinput_config_click_method  method) | ||||
| { | ||||
|   enum libinput_config_click_method supported; | ||||
|  | ||||
|   supported = libinput_device_config_click_get_methods (libinput_device); | ||||
|  | ||||
|   if (method & supported) | ||||
|     libinput_device_config_click_set_method (libinput_device, method); | ||||
|  | ||||
|   return (method & supported) != 0; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_settings_native_set_edge_scroll (MetaInputSettings            *settings, | ||||
|                                             ClutterInputDevice           *device, | ||||
|                                             gboolean                      edge_scrolling_enabled) | ||||
| { | ||||
|   enum libinput_config_scroll_method scroll_method = 0; | ||||
|   struct libinput_device *libinput_device; | ||||
|   enum libinput_config_scroll_method supported; | ||||
|  | ||||
|   libinput_device = clutter_evdev_input_device_get_libinput_device (device); | ||||
|   supported = libinput_device_config_scroll_get_methods (libinput_device); | ||||
|  | ||||
|   if (supported & LIBINPUT_CONFIG_SCROLL_2FG) | ||||
|     { | ||||
|       scroll_method = LIBINPUT_CONFIG_SCROLL_2FG; | ||||
|     } | ||||
|   else if (supported & LIBINPUT_CONFIG_SCROLL_EDGE && | ||||
|            edge_scrolling_enabled) | ||||
|     { | ||||
|       scroll_method = LIBINPUT_CONFIG_SCROLL_EDGE; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       scroll_method = LIBINPUT_CONFIG_SCROLL_NO_SCROLL; | ||||
|     } | ||||
|  | ||||
|   device_set_scroll_method (libinput_device, scroll_method); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_settings_native_set_scroll_button (MetaInputSettings  *settings, | ||||
|                                               ClutterInputDevice *device, | ||||
|                                               guint               button) | ||||
| { | ||||
|   struct libinput_device *libinput_device; | ||||
|  | ||||
|   libinput_device = clutter_evdev_input_device_get_libinput_device (device); | ||||
|  | ||||
|   if (!device_set_scroll_method (libinput_device, | ||||
|                                  LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN)) | ||||
|     return; | ||||
|  | ||||
|   libinput_device_config_scroll_set_button (libinput_device, button); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_settings_native_set_click_method (MetaInputSettings           *settings, | ||||
|                                              ClutterInputDevice          *device, | ||||
|                                              GDesktopTouchpadClickMethod  mode) | ||||
| { | ||||
|   enum libinput_config_click_method click_method = 0; | ||||
|   struct libinput_device *libinput_device; | ||||
|  | ||||
|   libinput_device = clutter_evdev_input_device_get_libinput_device (device); | ||||
|  | ||||
|   switch (mode) | ||||
|     { | ||||
|     case G_DESKTOP_TOUCHPAD_CLICK_METHOD_DEFAULT: | ||||
|       click_method = libinput_device_config_click_get_default_method (libinput_device); | ||||
|       break; | ||||
|     case G_DESKTOP_TOUCHPAD_CLICK_METHOD_NONE: | ||||
|       click_method = LIBINPUT_CONFIG_CLICK_METHOD_NONE; | ||||
|       break; | ||||
|     case G_DESKTOP_TOUCHPAD_CLICK_METHOD_AREAS: | ||||
|       click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS; | ||||
|       break; | ||||
|     case G_DESKTOP_TOUCHPAD_CLICK_METHOD_FINGERS: | ||||
|       click_method = LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER; | ||||
|       break; | ||||
|     default: | ||||
|       g_assert_not_reached (); | ||||
|       return; | ||||
|   } | ||||
|  | ||||
|   device_set_click_method (libinput_device, click_method); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_settings_native_set_keyboard_repeat (MetaInputSettings *settings, | ||||
|                                                 gboolean           enabled, | ||||
|                                                 guint              delay, | ||||
|                                                 guint              interval) | ||||
| { | ||||
|   ClutterDeviceManager *manager = clutter_device_manager_get_default (); | ||||
|  | ||||
|   clutter_evdev_set_keyboard_repeat (manager, enabled, delay, interval); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_settings_native_class_init (MetaInputSettingsNativeClass *klass) | ||||
| { | ||||
|   MetaInputSettingsClass *input_settings_class = META_INPUT_SETTINGS_CLASS (klass); | ||||
|  | ||||
|   input_settings_class->set_send_events = meta_input_settings_native_set_send_events; | ||||
|   input_settings_class->set_matrix = meta_input_settings_native_set_matrix; | ||||
|   input_settings_class->set_speed = meta_input_settings_native_set_speed; | ||||
|   input_settings_class->set_left_handed = meta_input_settings_native_set_left_handed; | ||||
|   input_settings_class->set_tap_enabled = meta_input_settings_native_set_tap_enabled; | ||||
|   input_settings_class->set_invert_scroll = meta_input_settings_native_set_invert_scroll; | ||||
|   input_settings_class->set_edge_scroll = meta_input_settings_native_set_edge_scroll; | ||||
|   input_settings_class->set_scroll_button = meta_input_settings_native_set_scroll_button; | ||||
|   input_settings_class->set_click_method = meta_input_settings_native_set_click_method; | ||||
|   input_settings_class->set_keyboard_repeat = meta_input_settings_native_set_keyboard_repeat; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_settings_native_init (MetaInputSettingsNative *settings) | ||||
| { | ||||
| } | ||||
							
								
								
									
										49
									
								
								src/backends/native/meta-input-settings-native.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/backends/native/meta-input-settings-native.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright 2014 Red Hat, Inc. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * Author: Carlos Garnacho <carlosg@gnome.org> | ||||
|  */ | ||||
|  | ||||
| #ifndef META_INPUT_SETTINGS_NATIVE_H | ||||
| #define META_INPUT_SETTINGS_NATIVE_H | ||||
|  | ||||
| #include "meta-input-settings-private.h" | ||||
|  | ||||
| #define META_TYPE_INPUT_SETTINGS_NATIVE             (meta_input_settings_native_get_type ()) | ||||
| #define META_INPUT_SETTINGS_NATIVE(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_INPUT_SETTINGS_NATIVE, MetaInputSettingsNative)) | ||||
| #define META_INPUT_SETTINGS_NATIVE_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_INPUT_SETTINGS_NATIVE, MetaInputSettingsNativeClass)) | ||||
| #define META_IS_INPUT_SETTINGS_NATIVE(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_INPUT_SETTINGS_NATIVE)) | ||||
| #define META_IS_INPUT_SETTINGS_NATIVE_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_INPUT_SETTINGS_NATIVE)) | ||||
| #define META_INPUT_SETTINGS_NATIVE_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_INPUT_SETTINGS_NATIVE, MetaInputSettingsNativeClass)) | ||||
|  | ||||
| typedef struct _MetaInputSettingsNative MetaInputSettingsNative; | ||||
| typedef struct _MetaInputSettingsNativeClass MetaInputSettingsNativeClass; | ||||
|  | ||||
| struct _MetaInputSettingsNative | ||||
| { | ||||
|   MetaInputSettings parent_instance; | ||||
| }; | ||||
|  | ||||
| struct _MetaInputSettingsNativeClass | ||||
| { | ||||
|   MetaInputSettingsClass parent_class; | ||||
| }; | ||||
|  | ||||
| GType meta_input_settings_native_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| #endif /* META_INPUT_SETTINGS_NATIVE_H */ | ||||
| @@ -37,12 +37,20 @@ | ||||
| #include <unistd.h> | ||||
|  | ||||
| #include <systemd/sd-login.h> | ||||
| #include <gudev/gudev.h> | ||||
|  | ||||
| #include "dbus-utils.h" | ||||
| #include "meta-dbus-login1.h" | ||||
|  | ||||
| #include "backends/meta-backend-private.h" | ||||
| #include "meta-cursor-renderer-native.h" | ||||
| #include "meta-idle-monitor-native.h" | ||||
|  | ||||
| G_DEFINE_AUTOPTR_CLEANUP_FUNC(GUdevDevice, g_object_unref) | ||||
| G_DEFINE_AUTOPTR_CLEANUP_FUNC(GUdevClient, g_object_unref) | ||||
| G_DEFINE_AUTOPTR_CLEANUP_FUNC(GUdevEnumerator, g_object_unref) | ||||
| G_DEFINE_AUTOPTR_CLEANUP_FUNC(Login1Session, g_object_unref) | ||||
| G_DEFINE_AUTOPTR_CLEANUP_FUNC(Login1Seat, g_object_unref) | ||||
|  | ||||
| struct _MetaLauncher | ||||
| { | ||||
| @@ -53,14 +61,21 @@ struct _MetaLauncher | ||||
| }; | ||||
|  | ||||
| static Login1Session * | ||||
| get_session_proxy (GCancellable *cancellable) | ||||
| get_session_proxy (GCancellable *cancellable, | ||||
|                    GError      **error) | ||||
| { | ||||
|   char *proxy_path; | ||||
|   char *session_id; | ||||
|   g_autofree char *proxy_path = NULL; | ||||
|   g_autofree char *session_id = NULL; | ||||
|   Login1Session *session_proxy; | ||||
|  | ||||
|   if (sd_pid_get_session (getpid (), &session_id) < 0) | ||||
|     return NULL; | ||||
|     { | ||||
|       g_set_error (error, | ||||
|                    G_IO_ERROR, | ||||
|                    G_IO_ERROR_NOT_FOUND, | ||||
|                    "Could not get session ID: %m"); | ||||
|       return NULL; | ||||
|     } | ||||
|  | ||||
|   proxy_path = get_escaped_dbus_path ("/org/freedesktop/login1/session", session_id); | ||||
|  | ||||
| @@ -68,31 +83,37 @@ get_session_proxy (GCancellable *cancellable) | ||||
|                                                          G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, | ||||
|                                                          "org.freedesktop.login1", | ||||
|                                                          proxy_path, | ||||
|                                                          cancellable, NULL); | ||||
|   free (proxy_path); | ||||
|                                                          cancellable, error); | ||||
|   if (!session_proxy) | ||||
|     g_prefix_error(error, "Could not get session proxy: "); | ||||
|  | ||||
|   return session_proxy; | ||||
| } | ||||
|  | ||||
| static Login1Seat * | ||||
| get_seat_proxy (GCancellable *cancellable) | ||||
| get_seat_proxy (GCancellable *cancellable, | ||||
|                 GError      **error) | ||||
| { | ||||
|   return login1_seat_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, | ||||
|                                              G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, | ||||
|                                              "org.freedesktop.login1", | ||||
|                                              "/org/freedesktop/login1/seat/self", | ||||
|                                              cancellable, NULL); | ||||
|   Login1Seat *seat = login1_seat_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, | ||||
|                                                          G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, | ||||
|                                                          "org.freedesktop.login1", | ||||
|                                                          "/org/freedesktop/login1/seat/self", | ||||
|                                                          cancellable, error); | ||||
|   if (!seat) | ||||
|     g_prefix_error(error, "Could not get seat proxy: "); | ||||
|  | ||||
|   return seat; | ||||
| } | ||||
|  | ||||
| static void | ||||
| session_unpause (void) | ||||
| { | ||||
|   ClutterBackend *backend; | ||||
|   ClutterBackend *clutter_backend; | ||||
|   CoglContext *cogl_context; | ||||
|   CoglDisplay *cogl_display; | ||||
|  | ||||
|   backend = clutter_get_default_backend (); | ||||
|   cogl_context = clutter_backend_get_cogl_context (backend); | ||||
|   clutter_backend = clutter_get_default_backend (); | ||||
|   cogl_context = clutter_backend_get_cogl_context (clutter_backend); | ||||
|   cogl_display = cogl_context_get_display (cogl_context); | ||||
|   cogl_kms_display_queue_modes_reset (cogl_display); | ||||
|  | ||||
| @@ -110,6 +131,7 @@ session_unpause (void) | ||||
|  | ||||
|     clutter_actor_queue_redraw (stage); | ||||
|     meta_cursor_renderer_native_force_update (META_CURSOR_RENDERER_NATIVE (renderer)); | ||||
|     meta_idle_monitor_native_reset_idletime (meta_idle_monitor_get_core ()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @@ -128,10 +150,9 @@ take_device (Login1Session *session_proxy, | ||||
|              GCancellable  *cancellable, | ||||
|              GError       **error) | ||||
| { | ||||
|   gboolean ret = FALSE; | ||||
|   GVariant *fd_variant = NULL; | ||||
|   g_autoptr (GVariant) fd_variant = NULL; | ||||
|   g_autoptr (GUnixFDList) fd_list = NULL; | ||||
|   int fd = -1; | ||||
|   GUnixFDList *fd_list; | ||||
|  | ||||
|   if (!login1_session_call_take_device_sync (session_proxy, | ||||
|                                              dev_major, | ||||
| @@ -142,21 +163,14 @@ take_device (Login1Session *session_proxy, | ||||
|                                              &fd_list, | ||||
|                                              cancellable, | ||||
|                                              error)) | ||||
|     goto out; | ||||
|     return FALSE; | ||||
|  | ||||
|   fd = g_unix_fd_list_get (fd_list, g_variant_get_handle (fd_variant), error); | ||||
|   if (fd == -1) | ||||
|     goto out; | ||||
|     return FALSE; | ||||
|  | ||||
|   *out_fd = fd; | ||||
|   ret = TRUE; | ||||
|  | ||||
|  out: | ||||
|   if (fd_variant) | ||||
|     g_variant_unref (fd_variant); | ||||
|   if (fd_list) | ||||
|     g_object_unref (fd_list); | ||||
|   return ret; | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| @@ -164,22 +178,16 @@ get_device_info_from_path (const char *path, | ||||
|                            int        *out_major, | ||||
|                            int        *out_minor) | ||||
| { | ||||
|   gboolean ret = FALSE; | ||||
|   int r; | ||||
|   struct stat st; | ||||
|  | ||||
|   r = stat (path, &st); | ||||
|   if (r < 0) | ||||
|     goto out; | ||||
|   if (!S_ISCHR (st.st_mode)) | ||||
|     goto out; | ||||
|   if (r < 0 || !S_ISCHR (st.st_mode)) | ||||
|     return FALSE; | ||||
|  | ||||
|   *out_major = major (st.st_rdev); | ||||
|   *out_minor = minor (st.st_rdev); | ||||
|   ret = TRUE; | ||||
|  | ||||
|  out: | ||||
|   return ret; | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| @@ -187,22 +195,16 @@ get_device_info_from_fd (int  fd, | ||||
|                          int *out_major, | ||||
|                          int *out_minor) | ||||
| { | ||||
|   gboolean ret = FALSE; | ||||
|   int r; | ||||
|   struct stat st; | ||||
|  | ||||
|   r = fstat (fd, &st); | ||||
|   if (r < 0) | ||||
|     goto out; | ||||
|   if (!S_ISCHR (st.st_mode)) | ||||
|     goto out; | ||||
|   if (r < 0 || !S_ISCHR (st.st_mode)) | ||||
|     return FALSE; | ||||
|  | ||||
|   *out_major = major (st.st_rdev); | ||||
|   *out_minor = minor (st.st_rdev); | ||||
|   ret = TRUE; | ||||
|  | ||||
|  out: | ||||
|   return ret; | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static int | ||||
| @@ -241,7 +243,7 @@ on_evdev_device_close (int      fd, | ||||
|   if (!get_device_info_from_fd (fd, &major, &minor)) | ||||
|     { | ||||
|       g_warning ("Could not get device info for fd %d: %m", fd); | ||||
|       return; | ||||
|       goto out; | ||||
|     } | ||||
|  | ||||
|   if (!login1_session_call_release_device_sync (self->session_proxy, | ||||
| @@ -250,6 +252,9 @@ on_evdev_device_close (int      fd, | ||||
|     { | ||||
|       g_warning ("Could not release device %d,%d: %s", major, minor, error->message); | ||||
|     } | ||||
|  | ||||
| out: | ||||
|   close (fd); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -277,25 +282,111 @@ on_active_changed (Login1Session *session, | ||||
|   sync_active (self); | ||||
| } | ||||
|  | ||||
| static gchar * | ||||
| get_primary_gpu_path (const gchar *seat_name) | ||||
| { | ||||
|   const gchar *subsystems[] = {"drm", NULL}; | ||||
|   gchar *path = NULL; | ||||
|   GList *devices, *tmp; | ||||
|  | ||||
|   g_autoptr (GUdevClient) gudev_client = g_udev_client_new (subsystems); | ||||
|   g_autoptr (GUdevEnumerator) enumerator = g_udev_enumerator_new (gudev_client); | ||||
|  | ||||
|   g_udev_enumerator_add_match_name (enumerator, "card*"); | ||||
|   g_udev_enumerator_add_match_tag (enumerator, "seat"); | ||||
|  | ||||
|   devices = g_udev_enumerator_execute (enumerator); | ||||
|   if (!devices) | ||||
|     goto out; | ||||
|  | ||||
|   for (tmp = devices; tmp != NULL; tmp = tmp->next) | ||||
|     { | ||||
|       g_autoptr (GUdevDevice) platform_device = NULL; | ||||
|       g_autoptr (GUdevDevice) pci_device = NULL; | ||||
|       GUdevDevice *dev = tmp->data; | ||||
|       gint boot_vga; | ||||
|       const gchar *device_seat; | ||||
|  | ||||
|       /* filter out devices that are not character device, like card0-VGA-1 */ | ||||
|       if (g_udev_device_get_device_type (dev) != G_UDEV_DEVICE_TYPE_CHAR) | ||||
|         continue; | ||||
|  | ||||
|       device_seat = g_udev_device_get_property (dev, "ID_SEAT"); | ||||
|       if (!device_seat) | ||||
|         { | ||||
|           /* when ID_SEAT is not set, it means seat0 */ | ||||
|           device_seat = "seat0"; | ||||
|         } | ||||
|       else if (g_strcmp0 (device_seat, "seat0") != 0) | ||||
|         { | ||||
|           /* if the device has been explicitly assigned other seat | ||||
|            * than seat0, it is probably the right device to use */ | ||||
|           path = g_strdup (g_udev_device_get_device_file (dev)); | ||||
|           break; | ||||
|         } | ||||
|  | ||||
|       /* skip devices that do not belong to our seat */ | ||||
|       if (g_strcmp0 (seat_name, device_seat)) | ||||
|         continue; | ||||
|  | ||||
|       platform_device = g_udev_device_get_parent_with_subsystem (dev, "platform", NULL); | ||||
|       if (platform_device != NULL) | ||||
|         { | ||||
|           path = g_strdup (g_udev_device_get_device_file (dev)); | ||||
|           break; | ||||
|         } | ||||
|  | ||||
|       pci_device = g_udev_device_get_parent_with_subsystem (dev, "pci", NULL); | ||||
|       if (pci_device != NULL) | ||||
|         { | ||||
|           /* get value of boot_vga attribute or 0 if the device has no boot_vga */ | ||||
|           boot_vga = g_udev_device_get_sysfs_attr_as_int (pci_device, "boot_vga"); | ||||
|           if (boot_vga == 1) | ||||
|             { | ||||
|               /* found the boot_vga device */ | ||||
|               path = g_strdup (g_udev_device_get_device_file (dev)); | ||||
|               break; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   g_list_free_full (devices, g_object_unref); | ||||
|  | ||||
| out: | ||||
|   return path; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| get_kms_fd (Login1Session *session_proxy, | ||||
|             int *fd_out) | ||||
|             const gchar   *seat_id, | ||||
|             int           *fd_out, | ||||
|             GError       **error) | ||||
| { | ||||
|   int major, minor; | ||||
|   int fd; | ||||
|   GError *error = NULL; | ||||
|  | ||||
|   /* XXX -- use udev to find the DRM master device */ | ||||
|   if (!get_device_info_from_path ("/dev/dri/card0", &major, &minor)) | ||||
|   g_autofree gchar *path = get_primary_gpu_path (seat_id); | ||||
|   if (!path) | ||||
|     { | ||||
|       g_warning ("Could not stat /dev/dri/card0: %m"); | ||||
|       g_set_error (error, | ||||
|                    G_IO_ERROR, | ||||
|                    G_IO_ERROR_NOT_FOUND, | ||||
|                    "could not find drm kms device"); | ||||
|       return FALSE; | ||||
|     } | ||||
|  | ||||
|   if (!take_device (session_proxy, major, minor, &fd, NULL, &error)) | ||||
|   if (!get_device_info_from_path (path, &major, &minor)) | ||||
|     { | ||||
|       g_warning ("Could not open DRM device: %s\n", error->message); | ||||
|       g_error_free (error); | ||||
|       g_set_error (error, | ||||
|                    G_IO_ERROR, | ||||
|                    G_IO_ERROR_NOT_FOUND, | ||||
|                    "Could not get device info for path %s: %m", path); | ||||
|       return FALSE; | ||||
|     } | ||||
|  | ||||
|   if (!take_device (session_proxy, major, minor, &fd, NULL, error)) | ||||
|     { | ||||
|       g_prefix_error (error, "Could not open DRM device: "); | ||||
|       return FALSE; | ||||
|     } | ||||
|  | ||||
| @@ -304,28 +395,72 @@ get_kms_fd (Login1Session *session_proxy, | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| MetaLauncher * | ||||
| meta_launcher_new (void) | ||||
| static gchar * | ||||
| get_seat_id (GError **error) | ||||
| { | ||||
|   MetaLauncher *self; | ||||
|   Login1Session *session_proxy; | ||||
|   GError *error = NULL; | ||||
|   int kms_fd; | ||||
|   g_autofree char *session_id = NULL; | ||||
|   char *seat_id = NULL; | ||||
|   int r; | ||||
|  | ||||
|   session_proxy = get_session_proxy (NULL); | ||||
|   if (!login1_session_call_take_control_sync (session_proxy, FALSE, NULL, &error)) | ||||
|   r = sd_pid_get_session (0, &session_id); | ||||
|   if (r < 0) | ||||
|     { | ||||
|       g_warning ("Could not take control: %s", error->message); | ||||
|       g_error_free (error); | ||||
|       g_set_error (error, | ||||
|                    G_IO_ERROR, | ||||
|                    G_IO_ERROR_NOT_FOUND, | ||||
|                    "Could not get session for PID: %s", g_strerror (-r)); | ||||
|       return NULL; | ||||
|     } | ||||
|  | ||||
|   if (!get_kms_fd (session_proxy, &kms_fd)) | ||||
|     return NULL; | ||||
|   r = sd_session_get_seat (session_id, &seat_id); | ||||
|   if (r < 0) | ||||
|     { | ||||
|       g_set_error (error, | ||||
|                    G_IO_ERROR, | ||||
|                    G_IO_ERROR_NOT_FOUND, | ||||
|                    "Could not get seat for session: %s", g_strerror (-r)); | ||||
|       return NULL; | ||||
|     } | ||||
|  | ||||
|   return seat_id; | ||||
| } | ||||
|  | ||||
| MetaLauncher * | ||||
| meta_launcher_new (GError **error) | ||||
| { | ||||
|   MetaLauncher *self = NULL; | ||||
|   g_autoptr (Login1Session) session_proxy = NULL; | ||||
|   g_autoptr (Login1Seat) seat_proxy = NULL; | ||||
|   g_autofree char *seat_id = NULL; | ||||
|   gboolean have_control = FALSE; | ||||
|   int kms_fd; | ||||
|  | ||||
|   session_proxy = get_session_proxy (NULL, error); | ||||
|   if (!session_proxy) | ||||
|     goto fail; | ||||
|  | ||||
|   if (!login1_session_call_take_control_sync (session_proxy, FALSE, NULL, error)) | ||||
|     { | ||||
|       g_prefix_error (error, "Could not take control: "); | ||||
|       goto fail; | ||||
|     } | ||||
|  | ||||
|   have_control = TRUE; | ||||
|  | ||||
|   seat_id = get_seat_id (error); | ||||
|   if (!seat_id) | ||||
|     goto fail; | ||||
|  | ||||
|   seat_proxy = get_seat_proxy (NULL, error); | ||||
|   if (!seat_proxy) | ||||
|     goto fail; | ||||
|  | ||||
|   if (!get_kms_fd (session_proxy, seat_id, &kms_fd, error)) | ||||
|     goto fail; | ||||
|  | ||||
|   self = g_slice_new0 (MetaLauncher); | ||||
|   self->session_proxy = session_proxy; | ||||
|   self->seat_proxy = get_seat_proxy (NULL); | ||||
|   self->session_proxy = g_object_ref (session_proxy); | ||||
|   self->seat_proxy = g_object_ref (seat_proxy); | ||||
|  | ||||
|   self->session_active = TRUE; | ||||
|  | ||||
| @@ -335,8 +470,12 @@ meta_launcher_new (void) | ||||
|                                       self); | ||||
|  | ||||
|   g_signal_connect (self->session_proxy, "notify::active", G_CALLBACK (on_active_changed), self); | ||||
|  | ||||
|   return self; | ||||
|  | ||||
|  fail: | ||||
|   if (have_control) | ||||
|     login1_session_call_release_control_sync (session_proxy, NULL, NULL); | ||||
|   return NULL; | ||||
| } | ||||
|  | ||||
| void | ||||
|   | ||||
| @@ -24,7 +24,7 @@ | ||||
|  | ||||
| typedef struct _MetaLauncher MetaLauncher; | ||||
|  | ||||
| MetaLauncher     *meta_launcher_new                     (void); | ||||
| MetaLauncher     *meta_launcher_new                     (GError       **error); | ||||
| void              meta_launcher_free                    (MetaLauncher  *self); | ||||
|  | ||||
| gboolean          meta_launcher_activate_session        (MetaLauncher  *self, | ||||
|   | ||||
| @@ -24,6 +24,7 @@ | ||||
| #include "config.h" | ||||
|  | ||||
| #include "meta-monitor-manager-kms.h" | ||||
| #include "meta-monitor-config.h" | ||||
|  | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
| @@ -38,7 +39,10 @@ | ||||
|  | ||||
| #include <meta/main.h> | ||||
| #include <meta/errors.h> | ||||
| #include "edid.h" | ||||
|  | ||||
| #include <gudev/gudev.h> | ||||
|  | ||||
| #define ALL_TRANSFORMS (META_MONITOR_TRANSFORM_FLIPPED_270 + 1) | ||||
|  | ||||
| typedef struct { | ||||
|   drmModeConnector *connector; | ||||
| @@ -53,8 +57,22 @@ typedef struct { | ||||
|  | ||||
|   uint32_t dpms_prop_id; | ||||
|   uint32_t edid_blob_id; | ||||
|   uint32_t tile_blob_id; | ||||
|  | ||||
|   int suggested_x; | ||||
|   int suggested_y; | ||||
|   uint32_t hotplug_mode_update; | ||||
| } MetaOutputKms; | ||||
|  | ||||
| typedef struct { | ||||
|   uint32_t underscan_prop_id; | ||||
|   uint32_t underscan_hborder_prop_id; | ||||
|   uint32_t underscan_vborder_prop_id; | ||||
|   uint32_t primary_plane_id; | ||||
|   uint32_t rotation_prop_id; | ||||
|   uint32_t rotation_map[ALL_TRANSFORMS]; | ||||
| } MetaCRTCKms; | ||||
|  | ||||
| struct _MetaMonitorManagerKms | ||||
| { | ||||
|   MetaMonitorManager parent_instance; | ||||
| @@ -64,10 +82,9 @@ struct _MetaMonitorManagerKms | ||||
|   drmModeConnector **connectors; | ||||
|   unsigned int       n_connectors; | ||||
|  | ||||
|   drmModeEncoder   **encoders; | ||||
|   unsigned int       n_encoders; | ||||
|   GUdevClient *udev; | ||||
|  | ||||
|   drmModeEncoder    *current_encoder; | ||||
|   GSettings *desktop_settings; | ||||
| }; | ||||
|  | ||||
| struct _MetaMonitorManagerKmsClass | ||||
| @@ -82,12 +99,9 @@ free_resources (MetaMonitorManagerKms *manager_kms) | ||||
| { | ||||
|   unsigned i; | ||||
|  | ||||
|   for (i = 0; i < manager_kms->n_encoders; i++) | ||||
|     drmModeFreeEncoder (manager_kms->encoders[i]); | ||||
|   for (i = 0; i < manager_kms->n_connectors; i++) | ||||
|     drmModeFreeConnector (manager_kms->connectors[i]); | ||||
|  | ||||
|   g_free (manager_kms->encoders); | ||||
|   g_free (manager_kms->connectors); | ||||
| } | ||||
|  | ||||
| @@ -106,7 +120,7 @@ make_output_name (drmModeConnector *connector) | ||||
|   static const char * const connector_type_names[] = { | ||||
|     "unknown", "VGA", "DVII", "DVID", "DVID", "Composite", | ||||
|     "SVIDEO", "LVDS", "Component", "9PinDIN", "DisplayPort", | ||||
|     "HDMIA", "HDMIB", "TV", "eDP" | ||||
|     "HDMIA", "HDMIB", "TV", "eDP", "Virtual", "DSI" | ||||
|   }; | ||||
|   const char *connector_type_name; | ||||
|  | ||||
| @@ -139,6 +153,12 @@ meta_monitor_mode_destroy_notify (MetaMonitorMode *output) | ||||
|   g_slice_free (drmModeModeInfo, output->driver_private); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_crtc_destroy_notify (MetaCRTC *crtc) | ||||
| { | ||||
|   g_free (crtc->driver_private); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| drm_mode_equal (gconstpointer one, | ||||
|                 gconstpointer two) | ||||
| @@ -183,26 +203,69 @@ drm_mode_hash (gconstpointer ptr) | ||||
| } | ||||
|  | ||||
| static void | ||||
| find_properties (MetaMonitorManagerKms *manager_kms, | ||||
|                  MetaOutputKms         *output_kms) | ||||
| find_connector_properties (MetaMonitorManagerKms *manager_kms, | ||||
|                            MetaOutputKms         *output_kms) | ||||
| { | ||||
|   drmModePropertyPtr prop; | ||||
|   int i; | ||||
|  | ||||
|   output_kms->hotplug_mode_update = 0; | ||||
|   output_kms->suggested_x = -1; | ||||
|   output_kms->suggested_y = -1; | ||||
|   for (i = 0; i < output_kms->connector->count_props; i++) | ||||
|     { | ||||
|       prop = drmModeGetProperty (manager_kms->fd, output_kms->connector->props[i]); | ||||
|       drmModePropertyPtr prop = drmModeGetProperty (manager_kms->fd, output_kms->connector->props[i]); | ||||
|       if (!prop) | ||||
|         continue; | ||||
|  | ||||
|       if ((prop->flags & DRM_MODE_PROP_ENUM) && | ||||
|           strcmp(prop->name, "DPMS") == 0) | ||||
|       if ((prop->flags & DRM_MODE_PROP_ENUM) && strcmp (prop->name, "DPMS") == 0) | ||||
|         output_kms->dpms_prop_id = prop->prop_id; | ||||
|       else if ((prop->flags & DRM_MODE_PROP_BLOB) && | ||||
|                strcmp (prop->name, "EDID") == 0) | ||||
|       else if ((prop->flags & DRM_MODE_PROP_BLOB) && strcmp (prop->name, "EDID") == 0) | ||||
|         output_kms->edid_blob_id = output_kms->connector->prop_values[i]; | ||||
|       else if ((prop->flags & DRM_MODE_PROP_BLOB) && | ||||
|                strcmp (prop->name, "TILE") == 0) | ||||
|         output_kms->tile_blob_id = output_kms->connector->prop_values[i]; | ||||
|       else if ((prop->flags & DRM_MODE_PROP_RANGE) && | ||||
|                strcmp (prop->name, "suggested X") == 0) | ||||
|         output_kms->suggested_x = output_kms->connector->prop_values[i]; | ||||
|       else if ((prop->flags & DRM_MODE_PROP_RANGE) && | ||||
|                strcmp (prop->name, "suggested Y") == 0) | ||||
|         output_kms->suggested_y = output_kms->connector->prop_values[i]; | ||||
|       else if ((prop->flags & DRM_MODE_PROP_RANGE) && | ||||
|                strcmp (prop->name, "hotplug_mode_update") == 0) | ||||
|         output_kms->hotplug_mode_update = output_kms->connector->prop_values[i]; | ||||
|        | ||||
|       drmModeFreeProperty (prop); | ||||
|     } | ||||
| } | ||||
|  | ||||
|       drmModeFreeProperty(prop); | ||||
| static void | ||||
| find_crtc_properties (MetaMonitorManagerKms *manager_kms, | ||||
|                       MetaCRTC *meta_crtc) | ||||
| { | ||||
|   MetaCRTCKms *crtc_kms; | ||||
|   drmModeObjectPropertiesPtr props; | ||||
|   size_t i; | ||||
|  | ||||
|   crtc_kms = meta_crtc->driver_private; | ||||
|  | ||||
|   props = drmModeObjectGetProperties (manager_kms->fd, meta_crtc->crtc_id, DRM_MODE_OBJECT_CRTC); | ||||
|   if (!props) | ||||
|     return; | ||||
|  | ||||
|   for (i = 0; i < props->count_props; i++) | ||||
|     { | ||||
|       drmModePropertyPtr prop = drmModeGetProperty (manager_kms->fd, props->props[i]); | ||||
|       if (!prop) | ||||
|         continue; | ||||
|  | ||||
|       if ((prop->flags & DRM_MODE_PROP_ENUM) && strcmp (prop->name, "underscan") == 0) | ||||
|         crtc_kms->underscan_prop_id = prop->prop_id; | ||||
|       else if ((prop->flags & DRM_MODE_PROP_RANGE) && strcmp (prop->name, "underscan hborder") == 0) | ||||
|         crtc_kms->underscan_hborder_prop_id = prop->prop_id; | ||||
|       else if ((prop->flags & DRM_MODE_PROP_RANGE) && strcmp (prop->name, "underscan vborder") == 0) | ||||
|         crtc_kms->underscan_vborder_prop_id = prop->prop_id; | ||||
|  | ||||
|       drmModeFreeProperty (prop); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -224,8 +287,10 @@ read_output_edid (MetaMonitorManagerKms *manager_kms, | ||||
|     } | ||||
|  | ||||
|   if (edid_blob->length > 0) | ||||
|     return g_bytes_new_with_free_func (edid_blob->data, edid_blob->length, | ||||
|                                        (GDestroyNotify)drmModeFreePropertyBlob, edid_blob); | ||||
|     { | ||||
|       return g_bytes_new_with_free_func (edid_blob->data, edid_blob->length, | ||||
|                                          (GDestroyNotify)drmModeFreePropertyBlob, edid_blob); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       drmModeFreePropertyBlob (edid_blob); | ||||
| @@ -233,6 +298,47 @@ read_output_edid (MetaMonitorManagerKms *manager_kms, | ||||
|     } | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| output_get_tile_info (MetaMonitorManagerKms *manager_kms, | ||||
|                       MetaOutput            *output) | ||||
| { | ||||
|   MetaOutputKms *output_kms = output->driver_private; | ||||
|   drmModePropertyBlobPtr tile_blob = NULL; | ||||
|   int ret; | ||||
|  | ||||
|   if (output_kms->tile_blob_id == 0) | ||||
|     return FALSE; | ||||
|  | ||||
|   tile_blob = drmModeGetPropertyBlob (manager_kms->fd, output_kms->tile_blob_id); | ||||
|   if (!tile_blob) | ||||
|     { | ||||
|       meta_warning ("Failed to read TILE of output %s: %s\n", output->name, strerror(errno)); | ||||
|       return FALSE; | ||||
|     } | ||||
|  | ||||
|   if (tile_blob->length > 0) | ||||
|     { | ||||
|       ret = sscanf ((char *)tile_blob->data, "%d:%d:%d:%d:%d:%d:%d:%d", | ||||
|                     &output->tile_info.group_id, | ||||
|                     &output->tile_info.flags, | ||||
|                     &output->tile_info.max_h_tiles, | ||||
|                     &output->tile_info.max_v_tiles, | ||||
|                     &output->tile_info.loc_h_tile, | ||||
|                     &output->tile_info.loc_v_tile, | ||||
|                     &output->tile_info.tile_w, | ||||
|                     &output->tile_info.tile_h); | ||||
|  | ||||
|       if (ret != 8) | ||||
|         return FALSE; | ||||
|       return TRUE; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       drmModeFreePropertyBlob (tile_blob); | ||||
|       return FALSE; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static MetaMonitorMode * | ||||
| find_meta_mode (MetaMonitorManager    *manager, | ||||
|                 const drmModeModeInfo *drm_mode) | ||||
| @@ -263,11 +369,208 @@ find_output_by_id (MetaOutput *outputs, | ||||
|   return NULL; | ||||
| } | ||||
|  | ||||
| /* The minimum resolution at which we turn on a window-scale of 2 */ | ||||
| #define HIDPI_LIMIT 192 | ||||
|  | ||||
| /* The minimum screen height at which we turn on a window-scale of 2; | ||||
|  * below this there just isn't enough vertical real estate for GNOME | ||||
|  * apps to work, and it's better to just be tiny */ | ||||
| #define HIDPI_MIN_HEIGHT 1200 | ||||
|  | ||||
| /* From http://en.wikipedia.org/wiki/4K_resolution#Resolutions_of_common_formats */ | ||||
| #define SMALLEST_4K_WIDTH 3656 | ||||
|  | ||||
| /* Based on code from gnome-settings-daemon */ | ||||
| static int | ||||
| compute_scale (MetaOutput *output) | ||||
| { | ||||
|   int scale = 1; | ||||
|  | ||||
|   if (!output->crtc) | ||||
|     goto out; | ||||
|  | ||||
|   /* Scaling makes no sense */ | ||||
|   if (output->crtc->rect.width < HIDPI_MIN_HEIGHT) | ||||
|     goto out; | ||||
|  | ||||
|   /* 4K TV */ | ||||
|   if (output->name != NULL && strstr(output->name, "HDMI") != NULL && | ||||
|       output->crtc->rect.width >= SMALLEST_4K_WIDTH) | ||||
|     goto out; | ||||
|  | ||||
|   /* Somebody encoded the aspect ratio (16/9 or 16/10) | ||||
|    * instead of the physical size */ | ||||
|   if ((output->width_mm == 160 && output->height_mm == 90) || | ||||
|       (output->width_mm == 160 && output->height_mm == 100) || | ||||
|       (output->width_mm == 16 && output->height_mm == 9) || | ||||
|       (output->width_mm == 16 && output->height_mm == 10)) | ||||
|     goto out; | ||||
|  | ||||
|   if (output->width_mm > 0 && output->height_mm > 0) | ||||
|     { | ||||
|       double dpi_x, dpi_y; | ||||
|       dpi_x = (double)output->crtc->rect.width / (output->width_mm / 25.4); | ||||
|       dpi_y = (double)output->crtc->rect.height / (output->height_mm / 25.4); | ||||
|       /* We don't completely trust these values so both | ||||
|          must be high, and never pick higher ratio than | ||||
|          2 automatically */ | ||||
|       if (dpi_x > HIDPI_LIMIT && dpi_y > HIDPI_LIMIT) | ||||
|         scale = 2; | ||||
|     } | ||||
|  | ||||
| out: | ||||
|   return scale; | ||||
| } | ||||
|  | ||||
| static int | ||||
| get_output_scale (MetaMonitorManager *manager, | ||||
|                   MetaOutput         *output) | ||||
| { | ||||
|   MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager); | ||||
|   int scale = g_settings_get_uint (manager_kms->desktop_settings, "scaling-factor"); | ||||
|   if (scale > 0) | ||||
|     return scale; | ||||
|   else | ||||
|     return compute_scale (output); | ||||
| } | ||||
|  | ||||
| static int | ||||
| find_property_index (MetaMonitorManager         *manager, | ||||
|                      drmModeObjectPropertiesPtr  props, | ||||
|                      const gchar                *prop_name, | ||||
|                      drmModePropertyPtr         *found) | ||||
| { | ||||
|   MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager); | ||||
|   unsigned int i; | ||||
|  | ||||
|   for (i = 0; i < props->count_props; i++) | ||||
|     { | ||||
|       drmModePropertyPtr prop; | ||||
|  | ||||
|       prop = drmModeGetProperty (manager_kms->fd, props->props[i]); | ||||
|       if (!prop) | ||||
|         continue; | ||||
|  | ||||
|       if (strcmp (prop->name, prop_name) == 0) | ||||
|         { | ||||
|           *found = prop; | ||||
|           return i; | ||||
|         } | ||||
|  | ||||
|       drmModeFreeProperty (prop); | ||||
|     } | ||||
|  | ||||
|   return -1; | ||||
| } | ||||
|  | ||||
| static void | ||||
| parse_transforms (MetaMonitorManager *manager, | ||||
|                   drmModePropertyPtr  prop, | ||||
|                   MetaCRTC           *crtc) | ||||
| { | ||||
|   MetaCRTCKms *crtc_kms = crtc->driver_private; | ||||
|   int i; | ||||
|  | ||||
|   for (i = 0; i < prop->count_enums; i++) | ||||
|     { | ||||
|       int cur = -1; | ||||
|  | ||||
|       if (strcmp (prop->enums[i].name, "rotate-0") == 0) | ||||
|         cur = META_MONITOR_TRANSFORM_NORMAL; | ||||
|       else if (strcmp (prop->enums[i].name, "rotate-90") == 0) | ||||
|         cur = META_MONITOR_TRANSFORM_90; | ||||
|       else if (strcmp (prop->enums[i].name, "rotate-180") == 0) | ||||
|         cur = META_MONITOR_TRANSFORM_180; | ||||
|       else if (strcmp (prop->enums[i].name, "rotate-270") == 0) | ||||
|         cur = META_MONITOR_TRANSFORM_270; | ||||
|  | ||||
|       if (cur != -1) | ||||
|         { | ||||
|           crtc->all_transforms |= 1 << cur; | ||||
|           crtc_kms->rotation_map[cur] = 1 << prop->enums[i].value; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| is_primary_plane (MetaMonitorManager         *manager, | ||||
|                   drmModeObjectPropertiesPtr  props) | ||||
| { | ||||
|   drmModePropertyPtr prop; | ||||
|   int idx; | ||||
|  | ||||
|   idx = find_property_index (manager, props, "type", &prop); | ||||
|   if (idx < 0) | ||||
|     return FALSE; | ||||
|  | ||||
|   drmModeFreeProperty (prop); | ||||
|   return props->prop_values[idx] == DRM_PLANE_TYPE_PRIMARY; | ||||
| } | ||||
|  | ||||
| static void | ||||
| init_crtc_rotations (MetaMonitorManager *manager, | ||||
|                      MetaCRTC           *crtc, | ||||
|                      unsigned int        idx) | ||||
| { | ||||
|   MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager); | ||||
|   drmModeObjectPropertiesPtr props; | ||||
|   drmModePlaneRes *planes; | ||||
|   drmModePlane *drm_plane; | ||||
|   MetaCRTCKms *crtc_kms; | ||||
|   unsigned int i; | ||||
|  | ||||
|   crtc_kms = crtc->driver_private; | ||||
|  | ||||
|   planes = drmModeGetPlaneResources(manager_kms->fd); | ||||
|   if (planes == NULL) | ||||
|     return; | ||||
|  | ||||
|   for (i = 0; i < planes->count_planes; i++) | ||||
|     { | ||||
|       drmModePropertyPtr prop; | ||||
|  | ||||
|       drm_plane = drmModeGetPlane (manager_kms->fd, planes->planes[i]); | ||||
|  | ||||
|       if (!drm_plane) | ||||
|         continue; | ||||
|  | ||||
|       if ((drm_plane->possible_crtcs & (1 << idx))) | ||||
|         { | ||||
|           props = drmModeObjectGetProperties (manager_kms->fd, | ||||
|                                               drm_plane->plane_id, | ||||
|                                               DRM_MODE_OBJECT_PLANE); | ||||
|  | ||||
|           if (props && is_primary_plane (manager, props)) | ||||
|             { | ||||
|               int rotation_idx; | ||||
|  | ||||
|               crtc_kms->primary_plane_id = drm_plane->plane_id; | ||||
|               rotation_idx = find_property_index (manager, props, "rotation", &prop); | ||||
|  | ||||
|               if (rotation_idx >= 0) | ||||
|                 { | ||||
|                   crtc_kms->rotation_prop_id = props->props[rotation_idx]; | ||||
|                   parse_transforms (manager, prop, crtc); | ||||
|                   drmModeFreeProperty (prop); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|           if (props) | ||||
|             drmModeFreeObjectProperties (props); | ||||
|         } | ||||
|  | ||||
|       drmModeFreePlane (drm_plane); | ||||
|     } | ||||
|  | ||||
|   drmModeFreePlaneResources (planes); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_monitor_manager_kms_read_current (MetaMonitorManager *manager) | ||||
| { | ||||
|   MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager); | ||||
|   drmModeRes *resources; | ||||
|   drmModeEncoder **encoders; | ||||
|   GHashTable *modes; | ||||
|   GHashTableIter iter; | ||||
|   drmModeModeInfo *mode; | ||||
| @@ -303,7 +606,7 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager) | ||||
|       connector = drmModeGetConnector (manager_kms->fd, resources->connectors[i]); | ||||
|       manager_kms->connectors[i] = connector; | ||||
|  | ||||
|       if (connector->connection == DRM_MODE_CONNECTED) | ||||
|       if (connector && connector->connection == DRM_MODE_CONNECTED) | ||||
|         { | ||||
|           /* Collect all modes for this connector */ | ||||
|           for (j = 0; j < (unsigned)connector->count_modes; j++) | ||||
| @@ -311,13 +614,9 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   manager_kms->n_encoders = resources->count_encoders; | ||||
|   manager_kms->encoders = g_new (drmModeEncoder *, manager_kms->n_encoders); | ||||
|   for (i = 0; i < manager_kms->n_encoders; i++) | ||||
|     { | ||||
|       manager_kms->encoders[i] = drmModeGetEncoder (manager_kms->fd, | ||||
|                                                     resources->encoders[i]); | ||||
|     } | ||||
|   encoders = g_new (drmModeEncoder *, resources->count_encoders); | ||||
|   for (i = 0; i < (unsigned)resources->count_encoders; i++) | ||||
|     encoders[i] = drmModeGetEncoder (manager_kms->fd, resources->encoders[i]); | ||||
|  | ||||
|   manager->n_modes = g_hash_table_size (modes); | ||||
|   manager->modes = g_new0 (MetaMonitorMode, manager->n_modes); | ||||
| @@ -333,8 +632,18 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager) | ||||
|       meta_mode->name = g_strndup (mode->name, DRM_DISPLAY_MODE_LEN); | ||||
|       meta_mode->width = mode->hdisplay; | ||||
|       meta_mode->height = mode->vdisplay; | ||||
|       meta_mode->refresh_rate = (1000 * mode->clock / | ||||
|                                  ((float)mode->htotal * mode->vtotal)); | ||||
|  | ||||
|       /* Calculate refresh rate in milliHz first for extra precision. */ | ||||
|       meta_mode->refresh_rate = (mode->clock * 1000000LL) / mode->htotal; | ||||
|       meta_mode->refresh_rate += (mode->vtotal / 2); | ||||
|       meta_mode->refresh_rate /= mode->vtotal; | ||||
|       if (mode->flags & DRM_MODE_FLAG_INTERLACE) | ||||
| 	meta_mode->refresh_rate *= 2; | ||||
|       if (mode->flags & DRM_MODE_FLAG_DBLSCAN) | ||||
|         meta_mode->refresh_rate /= 2; | ||||
|       if (mode->vscan > 1) | ||||
|         meta_mode->refresh_rate /= mode->vscan; | ||||
|       meta_mode->refresh_rate /= 1000.0; | ||||
|  | ||||
|       meta_mode->driver_private = g_slice_dup (drmModeModeInfo, mode); | ||||
|       meta_mode->driver_notify = (GDestroyNotify)meta_monitor_mode_destroy_notify; | ||||
| @@ -380,6 +689,11 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager) | ||||
|           height = MAX (height, meta_crtc->rect.y + meta_crtc->rect.height); | ||||
|         } | ||||
|  | ||||
|       meta_crtc->driver_private = g_new0 (MetaCRTCKms, 1); | ||||
|       meta_crtc->driver_notify = (GDestroyNotify) meta_crtc_destroy_notify; | ||||
|       find_crtc_properties (manager_kms, meta_crtc); | ||||
|       init_crtc_rotations (manager, meta_crtc, i); | ||||
|  | ||||
|       drmModeFreeCrtc (crtc); | ||||
|     } | ||||
|  | ||||
| @@ -401,7 +715,7 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager) | ||||
|       connector = manager_kms->connectors[i]; | ||||
|       meta_output = &manager->outputs[n_actual_outputs]; | ||||
|  | ||||
|       if (connector->connection == DRM_MODE_CONNECTED) | ||||
|       if (connector && connector->connection == DRM_MODE_CONNECTED) | ||||
| 	{ | ||||
|           meta_output->driver_private = output_kms = g_slice_new0 (MetaOutputKms); | ||||
|           meta_output->driver_notify = (GDestroyNotify)meta_output_destroy_notify; | ||||
| @@ -434,11 +748,17 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager) | ||||
|               break; | ||||
|             } | ||||
|  | ||||
| 	  meta_output->preferred_mode = NULL; | ||||
| 	  meta_output->n_modes = connector->count_modes; | ||||
| 	  meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes); | ||||
| 	  for (j = 0; j < meta_output->n_modes; j++) | ||||
| 	  for (j = 0; j < meta_output->n_modes; j++) { | ||||
|             meta_output->modes[j] = find_meta_mode (manager, &connector->modes[j]); | ||||
| 	  meta_output->preferred_mode = meta_output->modes[0]; | ||||
|             if (connector->modes[j].type & DRM_MODE_TYPE_PREFERRED) | ||||
|               meta_output->preferred_mode = meta_output->modes[j]; | ||||
|           } | ||||
|  | ||||
|           if (!meta_output->preferred_mode) | ||||
|             meta_output->preferred_mode = meta_output->modes[0]; | ||||
|  | ||||
|           output_kms->connector = connector; | ||||
|           output_kms->n_encoders = connector->count_encoders; | ||||
| @@ -448,6 +768,8 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager) | ||||
| 	  for (j = 0; j < output_kms->n_encoders; j++) | ||||
| 	    { | ||||
|               output_kms->encoders[j] = drmModeGetEncoder (manager_kms->fd, connector->encoders[j]); | ||||
|               if (!output_kms->encoders[j]) | ||||
|                 continue; | ||||
|  | ||||
|               /* We only list CRTCs as supported if they are supported by all encoders | ||||
|                  for this connectors. | ||||
| @@ -501,32 +823,21 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager) | ||||
|               meta_output->is_presentation = FALSE; | ||||
|             } | ||||
|  | ||||
|           find_properties (manager_kms, output_kms); | ||||
|  | ||||
|           find_connector_properties (manager_kms, output_kms); | ||||
|           meta_output->suggested_x = output_kms->suggested_x; | ||||
|           meta_output->suggested_y = output_kms->suggested_y; | ||||
|           meta_output->hotplug_mode_update = output_kms->hotplug_mode_update; | ||||
|            | ||||
|           edid = read_output_edid (manager_kms, meta_output); | ||||
|           if (edid) | ||||
|             { | ||||
|               MonitorInfo *parsed_edid; | ||||
|               gsize len; | ||||
|           meta_output_parse_edid (meta_output, edid); | ||||
|           g_bytes_unref (edid); | ||||
|  | ||||
|               parsed_edid = decode_edid (g_bytes_get_data (edid, &len)); | ||||
|               if (parsed_edid) | ||||
|                 { | ||||
|                   meta_output->vendor = g_strndup (parsed_edid->manufacturer_code, 4); | ||||
|                   meta_output->product = g_strndup (parsed_edid->dsc_product_name, 14); | ||||
|                   meta_output->serial = g_strndup (parsed_edid->dsc_serial_number, 14); | ||||
|           /* MetaConnectorType matches DRM's connector types */ | ||||
|           meta_output->connector_type = (MetaConnectorType) connector->connector_type; | ||||
|  | ||||
|                   g_free (parsed_edid); | ||||
|                 } | ||||
|           meta_output->scale = get_output_scale (manager, meta_output); | ||||
|  | ||||
|               g_bytes_unref (edid); | ||||
|             } | ||||
|           if (!meta_output->vendor) | ||||
|             { | ||||
|               meta_output->vendor = g_strdup ("unknown"); | ||||
|               meta_output->product = g_strdup ("unknown"); | ||||
|               meta_output->serial = g_strdup ("unknown"); | ||||
|             } | ||||
|           output_get_tile_info (manager_kms, meta_output); | ||||
|  | ||||
|           /* FIXME: backlight is a very driver specific thing unfortunately, | ||||
|              every DDX does its own thing, and the dumb KMS API does not include it. | ||||
| @@ -569,9 +880,10 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager) | ||||
|  | ||||
|       for (j = 0; j < output_kms->n_encoders; j++) | ||||
| 	{ | ||||
| 	  for (k = 0; k < manager_kms->n_encoders; k++) | ||||
| 	  for (k = 0; k < (unsigned)resources->count_encoders; k++) | ||||
| 	    { | ||||
| 	      if (output_kms->encoders[j]->encoder_id == manager_kms->encoders[k]->encoder_id) | ||||
|               if (output_kms->encoders[j] && encoders[k] && | ||||
|                   output_kms->encoders[j]->encoder_id == encoders[k]->encoder_id) | ||||
| 		{ | ||||
|                   output_kms->encoder_mask |= (1 << k); | ||||
| 		  break; | ||||
| @@ -618,6 +930,10 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   for (i = 0; i < (unsigned)resources->count_encoders; i++) | ||||
|     drmModeFreeEncoder (encoders[i]); | ||||
|   g_free (encoders); | ||||
|  | ||||
|   drmModeFreeResources (resources); | ||||
| } | ||||
|  | ||||
| @@ -635,6 +951,9 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager, | ||||
|                                               MetaPowerSave       mode) | ||||
| { | ||||
|   MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager); | ||||
|   ClutterBackend *backend; | ||||
|   CoglContext *cogl_context; | ||||
|   CoglDisplay *cogl_display; | ||||
|   uint64_t state; | ||||
|   unsigned i; | ||||
|  | ||||
| @@ -665,14 +984,23 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager, | ||||
|  | ||||
|       if (output_kms->dpms_prop_id != 0) | ||||
|         { | ||||
|           int ok = drmModeConnectorSetProperty(manager_kms->fd, meta_output->winsys_id, | ||||
|                                                output_kms->dpms_prop_id, state); | ||||
|           int ok = drmModeObjectSetProperty (manager_kms->fd, meta_output->winsys_id, | ||||
|                                              DRM_MODE_OBJECT_CONNECTOR, | ||||
|                                              output_kms->dpms_prop_id, state); | ||||
|  | ||||
|           if (ok < 0) | ||||
|             meta_warning ("Failed to set power save mode for output %s: %s\n", | ||||
|                           meta_output->name, strerror (errno)); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   backend = clutter_get_default_backend (); | ||||
|   cogl_context = clutter_backend_get_cogl_context (backend); | ||||
|   cogl_display = cogl_context_get_display (cogl_context); | ||||
|  | ||||
|   for (i = 0; i < manager->n_crtcs; i++) | ||||
|     cogl_kms_display_set_ignore_crtc (cogl_display, manager->crtcs[i].crtc_id, | ||||
|                                       mode != META_POWER_SAVE_ON); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -682,6 +1010,48 @@ crtc_free (CoglKmsCrtc *crtc) | ||||
|   g_slice_free (CoglKmsCrtc, crtc); | ||||
| } | ||||
|  | ||||
| static void | ||||
| set_underscan (MetaMonitorManagerKms *manager_kms, | ||||
|                MetaOutput *output) | ||||
| { | ||||
|   if (!output->crtc) | ||||
|     return; | ||||
|  | ||||
|   MetaCRTC *crtc = output->crtc; | ||||
|   MetaCRTCKms *crtc_kms = crtc->driver_private; | ||||
|   if (!crtc_kms->underscan_prop_id) | ||||
|     return; | ||||
|  | ||||
|   if (output->is_underscanning) | ||||
|     { | ||||
|       drmModeObjectSetProperty (manager_kms->fd, crtc->crtc_id, | ||||
|                                 DRM_MODE_OBJECT_CRTC, | ||||
|                                 crtc_kms->underscan_prop_id, (uint64_t) 1); | ||||
|  | ||||
|       if (crtc_kms->underscan_hborder_prop_id) | ||||
|         { | ||||
|           uint64_t value = crtc->current_mode->width * 0.05; | ||||
|           drmModeObjectSetProperty (manager_kms->fd, crtc->crtc_id, | ||||
|                                     DRM_MODE_OBJECT_CRTC, | ||||
|                                     crtc_kms->underscan_hborder_prop_id, value); | ||||
|         } | ||||
|       if (crtc_kms->underscan_vborder_prop_id) | ||||
|         { | ||||
|           uint64_t value = crtc->current_mode->height * 0.05; | ||||
|           drmModeObjectSetProperty (manager_kms->fd, crtc->crtc_id, | ||||
|                                     DRM_MODE_OBJECT_CRTC, | ||||
|                                     crtc_kms->underscan_vborder_prop_id, value); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       drmModeObjectSetProperty (manager_kms->fd, crtc->crtc_id, | ||||
|                                 DRM_MODE_OBJECT_CRTC, | ||||
|                                 crtc_kms->underscan_prop_id, (uint64_t) 0); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager, | ||||
|                                               MetaCRTCInfo       **crtcs, | ||||
| @@ -689,6 +1059,7 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager, | ||||
|                                               MetaOutputInfo     **outputs, | ||||
|                                               unsigned int         n_outputs) | ||||
| { | ||||
|   MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager); | ||||
|   ClutterBackend *backend; | ||||
|   CoglContext *cogl_context; | ||||
|   CoglDisplay *cogl_display; | ||||
| @@ -704,6 +1075,7 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager, | ||||
|     { | ||||
|       MetaCRTCInfo *crtc_info = crtcs[i]; | ||||
|       MetaCRTC *crtc = crtc_info->crtc; | ||||
|       MetaCRTCKms *crtc_kms = crtc->driver_private; | ||||
|       CoglKmsCrtc *cogl_crtc; | ||||
|  | ||||
|       crtc->is_dirty = TRUE; | ||||
| @@ -776,6 +1148,13 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager, | ||||
|           crtc->current_mode = mode; | ||||
|           crtc->transform = crtc_info->transform; | ||||
|         } | ||||
|  | ||||
|       if (crtc->all_transforms & (1 << crtc->transform)) | ||||
|         drmModeObjectSetProperty (manager_kms->fd, | ||||
|                                   crtc_kms->primary_plane_id, | ||||
|                                   DRM_MODE_OBJECT_PLANE, | ||||
|                                   crtc_kms->rotation_prop_id, | ||||
|                                   crtc_kms->rotation_map[crtc->transform]); | ||||
|     } | ||||
|  | ||||
|   /* Disable CRTCs not mentioned in the list (they have is_dirty == FALSE, | ||||
| @@ -834,6 +1213,9 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager, | ||||
|  | ||||
|       output->is_primary = output_info->is_primary; | ||||
|       output->is_presentation = output_info->is_presentation; | ||||
|       output->is_underscanning = output_info->is_underscanning; | ||||
|  | ||||
|       set_underscan (manager_kms, output); | ||||
|     } | ||||
|  | ||||
|   /* Disable outputs not mentioned in the list */ | ||||
| @@ -893,6 +1275,23 @@ meta_monitor_manager_kms_set_crtc_gamma (MetaMonitorManager *manager, | ||||
|   drmModeCrtcSetGamma (manager_kms->fd, crtc->crtc_id, size, red, green, blue); | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_uevent (GUdevClient *client, | ||||
|            const char  *action, | ||||
|            GUdevDevice *device, | ||||
|            gpointer     user_data) | ||||
| { | ||||
|   MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (user_data); | ||||
|   MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms); | ||||
|  | ||||
|   if (!g_udev_device_get_property_as_boolean (device, "HOTPLUG")) | ||||
|     return; | ||||
|  | ||||
|   meta_monitor_manager_read_current_config (manager); | ||||
|  | ||||
|   meta_monitor_manager_on_hotplug (manager); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_monitor_manager_kms_init (MetaMonitorManagerKms *manager_kms) | ||||
| { | ||||
| @@ -907,6 +1306,26 @@ meta_monitor_manager_kms_init (MetaMonitorManagerKms *manager_kms) | ||||
|   cogl_renderer = cogl_display_get_renderer (cogl_display); | ||||
|  | ||||
|   manager_kms->fd = cogl_kms_renderer_get_kms_fd (cogl_renderer); | ||||
|  | ||||
|   drmSetClientCap (manager_kms->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); | ||||
|  | ||||
|   const char *subsystems[2] = { "drm", NULL }; | ||||
|   manager_kms->udev = g_udev_client_new (subsystems); | ||||
|   g_signal_connect (manager_kms->udev, "uevent", | ||||
|                     G_CALLBACK (on_uevent), manager_kms); | ||||
|  | ||||
|   manager_kms->desktop_settings = g_settings_new ("org.gnome.desktop.interface"); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_monitor_manager_kms_dispose (GObject *object) | ||||
| { | ||||
|   MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (object); | ||||
|  | ||||
|   g_clear_object (&manager_kms->udev); | ||||
|   g_clear_object (&manager_kms->desktop_settings); | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_monitor_manager_kms_parent_class)->dispose (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -925,6 +1344,7 @@ meta_monitor_manager_kms_class_init (MetaMonitorManagerKmsClass *klass) | ||||
|   MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass); | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|  | ||||
|   object_class->dispose = meta_monitor_manager_kms_dispose; | ||||
|   object_class->finalize = meta_monitor_manager_kms_finalize; | ||||
|  | ||||
|   manager_class->read_current = meta_monitor_manager_kms_read_current; | ||||
|   | ||||
| @@ -23,7 +23,7 @@ | ||||
| #ifndef META_MONITOR_MANAGER_KMS_H | ||||
| #define META_MONITOR_MANAGER_KMS_H | ||||
|  | ||||
| #include "meta-monitor-manager.h" | ||||
| #include "meta-monitor-manager-private.h" | ||||
|  | ||||
| #define META_TYPE_MONITOR_MANAGER_KMS            (meta_monitor_manager_kms_get_type ()) | ||||
| #define META_MONITOR_MANAGER_KMS(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKms)) | ||||
|   | ||||
| @@ -40,12 +40,24 @@ | ||||
| #include "meta-idle-monitor-xsync.h" | ||||
| #include "meta-monitor-manager-xrandr.h" | ||||
| #include "backends/meta-monitor-manager-dummy.h" | ||||
| #include "backends/x11/nested/meta-cursor-renderer-x11-nested.h" | ||||
| #include "meta-cursor-renderer-x11.h" | ||||
| #ifdef HAVE_WAYLAND | ||||
| #include "wayland/meta-wayland.h" | ||||
| #endif | ||||
|  | ||||
| #include <meta/util.h> | ||||
| #include "display-private.h" | ||||
| #include "compositor/compositor-private.h" | ||||
|  | ||||
| typedef enum { | ||||
|   /* We're a traditional CM running under the host. */ | ||||
|   META_BACKEND_X11_MODE_COMPOSITOR, | ||||
|  | ||||
|   /* We're a nested X11 client */ | ||||
|   META_BACKEND_X11_MODE_NESTED, | ||||
| } MetaBackendX11Mode; | ||||
|  | ||||
| struct _MetaBackendX11Private | ||||
| { | ||||
|   /* The host X11 display */ | ||||
| @@ -53,6 +65,8 @@ struct _MetaBackendX11Private | ||||
|   xcb_connection_t *xcb; | ||||
|   GSource *source; | ||||
|  | ||||
|   MetaBackendX11Mode mode; | ||||
|  | ||||
|   int xsync_event_base; | ||||
|   int xsync_error_base; | ||||
|  | ||||
| @@ -68,6 +82,7 @@ struct _MetaBackendX11Private | ||||
|   gchar *keymap_layouts; | ||||
|   gchar *keymap_variants; | ||||
|   gchar *keymap_options; | ||||
|   int locked_group; | ||||
| }; | ||||
| typedef struct _MetaBackendX11Private MetaBackendX11Private; | ||||
|  | ||||
| @@ -79,11 +94,15 @@ static void | ||||
| handle_alarm_notify (MetaBackend *backend, | ||||
|                      XEvent      *event) | ||||
| { | ||||
|   int i; | ||||
|   GHashTableIter iter; | ||||
|   gpointer value; | ||||
|  | ||||
|   for (i = 0; i <= backend->device_id_max; i++) | ||||
|     if (backend->device_monitors[i]) | ||||
|       meta_idle_monitor_xsync_handle_xevent (backend->device_monitors[i], (XSyncAlarmNotifyEvent*) event); | ||||
|   g_hash_table_iter_init (&iter, backend->device_monitors); | ||||
|   while (g_hash_table_iter_next (&iter, NULL, &value)) | ||||
|     { | ||||
|       MetaIdleMonitor *device_monitor = META_IDLE_MONITOR (value); | ||||
|       meta_idle_monitor_xsync_handle_xevent (device_monitor, (XSyncAlarmNotifyEvent*) event); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -98,7 +117,7 @@ translate_device_event (MetaBackendX11 *x11, | ||||
|       /* This codepath should only ever trigger as an X11 compositor, | ||||
|        * and never under nested, as under nested all backend events | ||||
|        * should be reported with respect to the stage window. */ | ||||
|       g_assert (!meta_is_wayland_compositor ()); | ||||
|       g_assert (priv->mode == META_BACKEND_X11_MODE_COMPOSITOR); | ||||
|  | ||||
|       device_event->event = stage_window; | ||||
|  | ||||
| @@ -125,6 +144,48 @@ translate_device_event (MetaBackendX11 *x11, | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| translate_crossing_event (MetaBackendX11 *x11, | ||||
|                           XIEnterEvent   *enter_event) | ||||
| { | ||||
|   MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); | ||||
|  | ||||
|   /* Throw out weird events generated by grabs. */ | ||||
|   if (enter_event->mode == XINotifyGrab || | ||||
|       enter_event->mode == XINotifyUngrab) | ||||
|     { | ||||
|       enter_event->event = None; | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   Window stage_window = meta_backend_x11_get_xwindow (x11); | ||||
|   if (enter_event->event != stage_window && | ||||
|       priv->mode == META_BACKEND_X11_MODE_COMPOSITOR) | ||||
|     { | ||||
|       enter_event->event = meta_backend_x11_get_xwindow (x11); | ||||
|       enter_event->event_x = enter_event->root_x; | ||||
|       enter_event->event_y = enter_event->root_y; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| handle_device_change (MetaBackendX11 *x11, | ||||
|                       XIEvent        *event) | ||||
| { | ||||
|   XIDeviceChangedEvent *device_changed; | ||||
|  | ||||
|   if (event->evtype != XI_DeviceChanged) | ||||
|     return; | ||||
|  | ||||
|   device_changed = (XIDeviceChangedEvent *) event; | ||||
|  | ||||
|   if (device_changed->reason != XISlaveSwitch) | ||||
|     return; | ||||
|  | ||||
|   meta_backend_update_last_device (META_BACKEND (x11), | ||||
|                                    device_changed->sourceid); | ||||
| } | ||||
|  | ||||
| /* Clutter makes the assumption that there is only one X window | ||||
|  * per stage, which is a valid assumption to make for a generic | ||||
|  * application toolkit. As such, it will ignore any events sent | ||||
| @@ -136,7 +197,32 @@ translate_device_event (MetaBackendX11 *x11, | ||||
|  */ | ||||
| static void | ||||
| maybe_spoof_event_as_stage_event (MetaBackendX11 *x11, | ||||
|                                   XEvent         *event) | ||||
|                                   XIEvent        *input_event) | ||||
| { | ||||
|   switch (input_event->evtype) | ||||
|     { | ||||
|     case XI_Motion: | ||||
|     case XI_ButtonPress: | ||||
|     case XI_ButtonRelease: | ||||
|     case XI_KeyPress: | ||||
|     case XI_KeyRelease: | ||||
|     case XI_TouchBegin: | ||||
|     case XI_TouchUpdate: | ||||
|     case XI_TouchEnd: | ||||
|       translate_device_event (x11, (XIDeviceEvent *) input_event); | ||||
|       break; | ||||
|     case XI_Enter: | ||||
|     case XI_Leave: | ||||
|       translate_crossing_event (x11, (XIEnterEvent *) input_event); | ||||
|       break; | ||||
|     default: | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| handle_input_event (MetaBackendX11 *x11, | ||||
|                     XEvent         *event) | ||||
| { | ||||
|   MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); | ||||
|  | ||||
| @@ -145,21 +231,10 @@ maybe_spoof_event_as_stage_event (MetaBackendX11 *x11, | ||||
|     { | ||||
|       XIEvent *input_event = (XIEvent *) event->xcookie.data; | ||||
|  | ||||
|       switch (input_event->evtype) | ||||
|         { | ||||
|         case XI_Motion: | ||||
|         case XI_ButtonPress: | ||||
|         case XI_ButtonRelease: | ||||
|         case XI_KeyPress: | ||||
|         case XI_KeyRelease: | ||||
|         case XI_TouchBegin: | ||||
|         case XI_TouchUpdate: | ||||
|         case XI_TouchEnd: | ||||
|           translate_device_event (x11, (XIDeviceEvent *) input_event); | ||||
|           break; | ||||
|         default: | ||||
|           break; | ||||
|         } | ||||
|       if (input_event->evtype == XI_DeviceChanged) | ||||
|         handle_device_change (x11, input_event); | ||||
|       else | ||||
|         maybe_spoof_event_as_stage_event (x11, input_event); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -199,20 +274,47 @@ handle_host_xevent (MetaBackend *backend, | ||||
|       } | ||||
|   } | ||||
|  | ||||
|   if (priv->mode == META_BACKEND_X11_MODE_NESTED && event->type == FocusIn) | ||||
|     { | ||||
| #ifdef HAVE_WAYLAND | ||||
|       Window xwin = meta_backend_x11_get_xwindow(x11); | ||||
|       XEvent xev; | ||||
|  | ||||
|       if (event->xfocus.window == xwin) | ||||
|         { | ||||
|           /* Since we've selected for KeymapStateMask, every FocusIn is followed immediately | ||||
|            * by a KeymapNotify event */ | ||||
|           XMaskEvent(priv->xdisplay, KeymapStateMask, &xev); | ||||
|           MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); | ||||
|           meta_wayland_compositor_update_key_state (compositor, xev.xkeymap.key_vector, 32, 8); | ||||
|         } | ||||
| #else | ||||
|       g_assert_not_reached (); | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|   if (event->type == (priv->xsync_event_base + XSyncAlarmNotify)) | ||||
|     handle_alarm_notify (backend, event); | ||||
|  | ||||
|   if (event->type == priv->xkb_event_base) | ||||
|     { | ||||
|       XkbAnyEvent *xkb_ev = (XkbAnyEvent *) event; | ||||
|       XkbEvent *xkb_ev = (XkbEvent *) event; | ||||
|  | ||||
|       if (xkb_ev->device == META_VIRTUAL_CORE_KEYBOARD_ID) | ||||
|       if (xkb_ev->any.device == META_VIRTUAL_CORE_KEYBOARD_ID) | ||||
|         { | ||||
|           switch (xkb_ev->xkb_type) | ||||
|           switch (xkb_ev->any.xkb_type) | ||||
|             { | ||||
|             case XkbNewKeyboardNotify: | ||||
|             case XkbMapNotify: | ||||
|               keymap_changed (backend); | ||||
|               break; | ||||
|             case XkbStateNotify: | ||||
|               if (xkb_ev->state.changed & XkbGroupLockMask) | ||||
|                 { | ||||
|                   if (priv->locked_group != xkb_ev->state.locked_group) | ||||
|                     XkbLockGroup (priv->xdisplay, XkbUseCoreKbd, priv->locked_group); | ||||
|                 } | ||||
|               break; | ||||
|             default: | ||||
|               break; | ||||
|             } | ||||
| @@ -228,7 +330,7 @@ handle_host_xevent (MetaBackend *backend, | ||||
|  | ||||
|   if (!bypass_clutter) | ||||
|     { | ||||
|       maybe_spoof_event_as_stage_event (x11, event); | ||||
|       handle_input_event (x11, event); | ||||
|       clutter_x11_handle_event (event); | ||||
|     } | ||||
|  | ||||
| @@ -348,6 +450,7 @@ meta_backend_x11_post_init (MetaBackend *backend) | ||||
|   MetaBackendX11 *x11 = META_BACKEND_X11 (backend); | ||||
|   MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); | ||||
|   int major, minor; | ||||
|   gboolean has_xi = FALSE; | ||||
|  | ||||
|   priv->xdisplay = clutter_x11_get_default_display (); | ||||
|  | ||||
| @@ -357,29 +460,27 @@ meta_backend_x11_post_init (MetaBackend *backend) | ||||
|       !XSyncInitialize (priv->xdisplay, &major, &minor)) | ||||
|     meta_fatal ("Could not initialize XSync"); | ||||
|  | ||||
|   { | ||||
|     int major = 2, minor = 3; | ||||
|     gboolean has_xi = FALSE; | ||||
|   if (XQueryExtension (priv->xdisplay, | ||||
|                        "XInputExtension", | ||||
|                        &priv->xinput_opcode, | ||||
|                        &priv->xinput_error_base, | ||||
|                        &priv->xinput_event_base)) | ||||
|     { | ||||
|       major = 2; minor = 3; | ||||
|       if (XIQueryVersion (priv->xdisplay, &major, &minor) == Success) | ||||
|         { | ||||
|           int version = (major * 10) + minor; | ||||
|           if (version >= 22) | ||||
|             has_xi = TRUE; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (XQueryExtension (priv->xdisplay, | ||||
|                          "XInputExtension", | ||||
|                          &priv->xinput_opcode, | ||||
|                          &priv->xinput_error_base, | ||||
|                          &priv->xinput_event_base)) | ||||
|       { | ||||
|         if (XIQueryVersion (priv->xdisplay, &major, &minor) == Success) | ||||
|           { | ||||
|             int version = (major * 10) + minor; | ||||
|             if (version >= 22) | ||||
|               has_xi = TRUE; | ||||
|           } | ||||
|       } | ||||
|   if (!has_xi) | ||||
|     meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer\n"); | ||||
|  | ||||
|     if (!has_xi) | ||||
|       meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer\n"); | ||||
|   } | ||||
|  | ||||
|   take_touch_grab (backend); | ||||
|   /* We only take the passive touch grab if we are a X11 compositor */ | ||||
|   if (priv->mode == META_BACKEND_X11_MODE_COMPOSITOR) | ||||
|     take_touch_grab (backend); | ||||
|  | ||||
|   priv->xcb = XGetXCBConnection (priv->xdisplay); | ||||
|   if (!xkb_x11_setup_xkb_extension (priv->xcb, | ||||
| @@ -410,19 +511,37 @@ meta_backend_x11_create_idle_monitor (MetaBackend *backend, | ||||
| static MetaMonitorManager * | ||||
| meta_backend_x11_create_monitor_manager (MetaBackend *backend) | ||||
| { | ||||
|   /* If we're a Wayland compositor using the X11 backend, | ||||
|    * we're a nested configuration, so return the dummy | ||||
|    * monitor setup. */ | ||||
|   if (meta_is_wayland_compositor ()) | ||||
|     return g_object_new (META_TYPE_MONITOR_MANAGER_DUMMY, NULL); | ||||
|   MetaBackendX11 *x11 = META_BACKEND_X11 (backend); | ||||
|   MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); | ||||
|  | ||||
|   return g_object_new (META_TYPE_MONITOR_MANAGER_XRANDR, NULL); | ||||
|   switch (priv->mode) | ||||
|     { | ||||
|     case META_BACKEND_X11_MODE_COMPOSITOR: | ||||
|       return g_object_new (META_TYPE_MONITOR_MANAGER_XRANDR, NULL); | ||||
|     case META_BACKEND_X11_MODE_NESTED: | ||||
|       return g_object_new (META_TYPE_MONITOR_MANAGER_DUMMY, NULL); | ||||
|     default: | ||||
|       g_assert_not_reached (); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static MetaCursorRenderer * | ||||
| meta_backend_x11_create_cursor_renderer (MetaBackend *backend) | ||||
| { | ||||
|   return g_object_new (META_TYPE_CURSOR_RENDERER_X11, NULL); | ||||
|   MetaBackendX11 *x11 = META_BACKEND_X11 (backend); | ||||
|   MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); | ||||
|  | ||||
|   switch (priv->mode) | ||||
|     { | ||||
|     case META_BACKEND_X11_MODE_COMPOSITOR: | ||||
|       return g_object_new (META_TYPE_CURSOR_RENDERER_X11, NULL); | ||||
|       break; | ||||
|     case META_BACKEND_X11_MODE_NESTED: | ||||
|       return g_object_new (META_TYPE_CURSOR_RENDERER_X11_NESTED, NULL); | ||||
|       break; | ||||
|     default: | ||||
|       g_assert_not_reached (); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| @@ -650,6 +769,9 @@ meta_backend_x11_get_keymap (MetaBackend *backend) | ||||
|                                                      priv->xcb, | ||||
|                                                      xkb_x11_get_core_keyboard_device_id (priv->xcb), | ||||
|                                                      XKB_KEYMAP_COMPILE_NO_FLAGS); | ||||
|       if (priv->keymap == NULL) | ||||
|         priv->keymap = xkb_keymap_new_from_names (context, NULL, XKB_KEYMAP_COMPILE_NO_FLAGS); | ||||
|  | ||||
|       xkb_context_unref (context); | ||||
|     } | ||||
|  | ||||
| @@ -663,6 +785,7 @@ meta_backend_x11_lock_layout_group (MetaBackend *backend, | ||||
|   MetaBackendX11 *x11 = META_BACKEND_X11 (backend); | ||||
|   MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); | ||||
|  | ||||
|   priv->locked_group = idx; | ||||
|   XkbLockGroup (priv->xdisplay, XkbUseCoreKbd, idx); | ||||
| } | ||||
|  | ||||
| @@ -670,7 +793,10 @@ static void | ||||
| meta_backend_x11_update_screen_size (MetaBackend *backend, | ||||
|                                      int width, int height) | ||||
| { | ||||
|   if (meta_is_wayland_compositor ()) | ||||
|   MetaBackendX11 *x11 = META_BACKEND_X11 (backend); | ||||
|   MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); | ||||
|  | ||||
|   if (priv->mode == META_BACKEND_X11_MODE_NESTED) | ||||
|     { | ||||
|       /* For a nested wayland session, we want to go through Clutter to update the | ||||
|        * toplevel window size, rather than doing it directly. | ||||
| @@ -679,8 +805,6 @@ meta_backend_x11_update_screen_size (MetaBackend *backend, | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       MetaBackendX11 *x11 = META_BACKEND_X11 (backend); | ||||
|       MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); | ||||
|       Window xwin = meta_backend_x11_get_xwindow (x11); | ||||
|       XResizeWindow (priv->xdisplay, xwin, width, height); | ||||
|     } | ||||
| @@ -704,10 +828,36 @@ meta_backend_x11_select_stage_events (MetaBackend *backend) | ||||
|   XISetMask (mask.mask, XI_FocusIn); | ||||
|   XISetMask (mask.mask, XI_FocusOut); | ||||
|   XISetMask (mask.mask, XI_Motion); | ||||
|   XIClearMask (mask.mask, XI_TouchBegin); | ||||
|   XIClearMask (mask.mask, XI_TouchEnd); | ||||
|   XIClearMask (mask.mask, XI_TouchUpdate); | ||||
|  | ||||
|   if (priv->mode == META_BACKEND_X11_MODE_NESTED) | ||||
|     { | ||||
|       /* When we're an X11 compositor, we can't take these events or else | ||||
|        * replaying events from our passive root window grab will cause | ||||
|        * them to come back to us. | ||||
|        * | ||||
|        * When we're a nested application, we want to behave like any other | ||||
|        * application, so select these events like normal apps do. | ||||
|        */ | ||||
|       XISetMask (mask.mask, XI_TouchBegin); | ||||
|       XISetMask (mask.mask, XI_TouchEnd); | ||||
|       XISetMask (mask.mask, XI_TouchUpdate); | ||||
|     } | ||||
|  | ||||
|   XISelectEvents (priv->xdisplay, xwin, &mask, 1); | ||||
|  | ||||
|   if (priv->mode == META_BACKEND_X11_MODE_NESTED) | ||||
|     { | ||||
|       /* We have no way of tracking key changes when the stage doesn't have | ||||
|        * focus, so we select for KeymapStateMask so that we get a complete | ||||
|        * dump of the keyboard state in a KeymapNotify event that immediately | ||||
|        * follows each FocusIn (and EnterNotify, but we ignore that.) | ||||
|        */ | ||||
|       XWindowAttributes xwa; | ||||
|  | ||||
|       XGetWindowAttributes(priv->xdisplay, xwin, &xwa); | ||||
|       XSelectInput(priv->xdisplay, xwin, | ||||
|                    xwa.your_event_mask | FocusChangeMask | KeymapStateMask); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -732,8 +882,15 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass) | ||||
| static void | ||||
| meta_backend_x11_init (MetaBackendX11 *x11) | ||||
| { | ||||
|   MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); | ||||
|  | ||||
|   /* We do X11 event retrieval ourselves */ | ||||
|   clutter_x11_disable_event_retrieval (); | ||||
|  | ||||
|   if (meta_is_wayland_compositor ()) | ||||
|     priv->mode = META_BACKEND_X11_MODE_NESTED; | ||||
|   else | ||||
|     priv->mode = META_BACKEND_X11_MODE_COMPOSITOR; | ||||
| } | ||||
|  | ||||
| Display * | ||||
|   | ||||
							
								
								
									
										219
									
								
								src/backends/x11/meta-barrier-x11.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										219
									
								
								src/backends/x11/meta-barrier-x11.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,219 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2014-2015 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Jasper St. Pierre <jstpierre@mecheye.net> | ||||
|  *     Jonas Ådahl <jadahl@gmail.com> | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * SECTION:barrier-x11 | ||||
|  * @Title: MetaBarrierImplX11 | ||||
|  * @Short_Description: Pointer barriers implementation for X11 | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #ifdef HAVE_XI23 | ||||
|  | ||||
| #include <glib-object.h> | ||||
|  | ||||
| #include <X11/extensions/XInput2.h> | ||||
| #include <X11/extensions/Xfixes.h> | ||||
| #include <meta/barrier.h> | ||||
| #include "backends/x11/meta-barrier-x11.h" | ||||
| #include "display-private.h" | ||||
|  | ||||
| struct _MetaBarrierImplX11Private | ||||
| { | ||||
|   MetaBarrier *barrier; | ||||
|   PointerBarrier xbarrier; | ||||
| }; | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_PRIVATE (MetaBarrierImplX11, meta_barrier_impl_x11, | ||||
|                             META_TYPE_BARRIER_IMPL) | ||||
|  | ||||
| static gboolean | ||||
| _meta_barrier_impl_x11_is_active (MetaBarrierImpl *impl) | ||||
| { | ||||
|   MetaBarrierImplX11 *self = META_BARRIER_IMPL_X11 (impl); | ||||
|   MetaBarrierImplX11Private *priv = | ||||
|     meta_barrier_impl_x11_get_instance_private (self); | ||||
|  | ||||
|   return priv->xbarrier != 0; | ||||
| } | ||||
|  | ||||
| static void | ||||
| _meta_barrier_impl_x11_release (MetaBarrierImpl  *impl, | ||||
|                                 MetaBarrierEvent *event) | ||||
| { | ||||
|   MetaBarrierImplX11 *self = META_BARRIER_IMPL_X11 (impl); | ||||
|   MetaBarrierImplX11Private *priv = | ||||
|     meta_barrier_impl_x11_get_instance_private (self); | ||||
|   MetaDisplay *display = priv->barrier->priv->display; | ||||
|  | ||||
|   if (META_DISPLAY_HAS_XINPUT_23 (display)) | ||||
|     { | ||||
|       XIBarrierReleasePointer (display->xdisplay, | ||||
|                                META_VIRTUAL_CORE_POINTER_ID, | ||||
|                                priv->xbarrier, event->event_id); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| _meta_barrier_impl_x11_destroy (MetaBarrierImpl *impl) | ||||
| { | ||||
|   MetaBarrierImplX11 *self = META_BARRIER_IMPL_X11 (impl); | ||||
|   MetaBarrierImplX11Private *priv = | ||||
|     meta_barrier_impl_x11_get_instance_private (self); | ||||
|   MetaDisplay *display = priv->barrier->priv->display; | ||||
|   Display *dpy; | ||||
|  | ||||
|   if (display == NULL) | ||||
|     return; | ||||
|  | ||||
|   dpy = display->xdisplay; | ||||
|  | ||||
|   if (!meta_barrier_is_active (priv->barrier)) | ||||
|     return; | ||||
|  | ||||
|   XFixesDestroyPointerBarrier (dpy, priv->xbarrier); | ||||
|   g_hash_table_remove (display->xids, &priv->xbarrier); | ||||
|   priv->xbarrier = 0; | ||||
| } | ||||
|  | ||||
| MetaBarrierImpl * | ||||
| meta_barrier_impl_x11_new (MetaBarrier *barrier) | ||||
| { | ||||
|   MetaBarrierImplX11 *self; | ||||
|   MetaBarrierImplX11Private *priv; | ||||
|   MetaDisplay *display = barrier->priv->display; | ||||
|   Display *dpy; | ||||
|   Window root; | ||||
|   unsigned int allowed_motion_dirs; | ||||
|  | ||||
|   if (display == NULL) | ||||
|     { | ||||
|       g_warning ("A display must be provided when constructing a barrier."); | ||||
|       return NULL; | ||||
|     } | ||||
|  | ||||
|   self = g_object_new (META_TYPE_BARRIER_IMPL_X11, NULL); | ||||
|   priv = meta_barrier_impl_x11_get_instance_private (self); | ||||
|   priv->barrier = barrier; | ||||
|  | ||||
|   dpy = display->xdisplay; | ||||
|   root = DefaultRootWindow (dpy); | ||||
|  | ||||
|   allowed_motion_dirs = | ||||
|     meta_border_get_allows_directions (&barrier->priv->border); | ||||
|   priv->xbarrier = XFixesCreatePointerBarrier (dpy, root, | ||||
|                                                barrier->priv->border.line.a.x, | ||||
|                                                barrier->priv->border.line.a.y, | ||||
|                                                barrier->priv->border.line.b.x, | ||||
|                                                barrier->priv->border.line.b.y, | ||||
|                                                allowed_motion_dirs, | ||||
|                                                0, NULL); | ||||
|  | ||||
|   g_hash_table_insert (display->xids, &priv->xbarrier, barrier); | ||||
|  | ||||
|   return META_BARRIER_IMPL (self); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_barrier_fire_xevent (MetaBarrier    *barrier, | ||||
|                           XIBarrierEvent *xevent) | ||||
| { | ||||
|   MetaBarrierEvent *event = g_slice_new0 (MetaBarrierEvent); | ||||
|  | ||||
|   event->ref_count = 1; | ||||
|   event->event_id = xevent->eventid; | ||||
|   event->time = xevent->time; | ||||
|   event->dt = xevent->dtime; | ||||
|  | ||||
|   event->x = xevent->root_x; | ||||
|   event->y = xevent->root_y; | ||||
|   event->dx = xevent->dx; | ||||
|   event->dy = xevent->dy; | ||||
|  | ||||
|   event->released = (xevent->flags & XIBarrierPointerReleased) != 0; | ||||
|   event->grabbed = (xevent->flags & XIBarrierDeviceIsGrabbed) != 0; | ||||
|  | ||||
|   switch (xevent->evtype) | ||||
|     { | ||||
|     case XI_BarrierHit: | ||||
|       _meta_barrier_emit_hit_signal (barrier, event); | ||||
|       break; | ||||
|     case XI_BarrierLeave: | ||||
|       _meta_barrier_emit_left_signal (barrier, event); | ||||
|       break; | ||||
|     default: | ||||
|       g_assert_not_reached (); | ||||
|     } | ||||
|  | ||||
|   meta_barrier_event_unref (event); | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_display_process_barrier_xevent (MetaDisplay *display, | ||||
|                                      XIEvent     *event) | ||||
| { | ||||
|   MetaBarrier *barrier; | ||||
|   XIBarrierEvent *xev; | ||||
|  | ||||
|   if (event == NULL) | ||||
|     return FALSE; | ||||
|  | ||||
|   switch (event->evtype) | ||||
|     { | ||||
|     case XI_BarrierHit: | ||||
|     case XI_BarrierLeave: | ||||
|       break; | ||||
|     default: | ||||
|       return FALSE; | ||||
|     } | ||||
|  | ||||
|   xev = (XIBarrierEvent *) event; | ||||
|   barrier = g_hash_table_lookup (display->xids, &xev->barrier); | ||||
|   if (barrier != NULL) | ||||
|     { | ||||
|       meta_barrier_fire_xevent (barrier, xev); | ||||
|       return TRUE; | ||||
|     } | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_barrier_impl_x11_class_init (MetaBarrierImplX11Class *klass) | ||||
| { | ||||
|   MetaBarrierImplClass *impl_class = META_BARRIER_IMPL_CLASS (klass); | ||||
|  | ||||
|   impl_class->is_active = _meta_barrier_impl_x11_is_active; | ||||
|   impl_class->release = _meta_barrier_impl_x11_release; | ||||
|   impl_class->destroy = _meta_barrier_impl_x11_destroy; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_barrier_impl_x11_init (MetaBarrierImplX11 *self) | ||||
| { | ||||
| } | ||||
|  | ||||
| #endif /* HAVE_XI23 */ | ||||
							
								
								
									
										59
									
								
								src/backends/x11/meta-barrier-x11.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/backends/x11/meta-barrier-x11.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2015 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Jonas Ådahl <jadahl@gmail.com> | ||||
|  */ | ||||
|  | ||||
| #ifndef META_BARRIER_X11_H | ||||
| #define META_BARRIER_X11_H | ||||
|  | ||||
| #include "backends/meta-barrier-private.h" | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define META_TYPE_BARRIER_IMPL_X11            (meta_barrier_impl_x11_get_type ()) | ||||
| #define META_BARRIER_IMPL_X11(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BARRIER_IMPL_X11, MetaBarrierImplX11)) | ||||
| #define META_BARRIER_IMPL_X11_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_BARRIER_IMPL_X11, MetaBarrierImplX11Class)) | ||||
| #define META_IS_BARRIER_IMPL_X11(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_BARRIER_IMPL_X11)) | ||||
| #define META_IS_BARRIER_IMPL_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_BARRIER_IMPL_X11)) | ||||
| #define META_BARRIER_IMPL_X11_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_BARRIER_IMPL_X11, MetaBarrierImplX11Class)) | ||||
|  | ||||
| typedef struct _MetaBarrierImplX11        MetaBarrierImplX11; | ||||
| typedef struct _MetaBarrierImplX11Class   MetaBarrierImplX11Class; | ||||
| typedef struct _MetaBarrierImplX11Private MetaBarrierImplX11Private; | ||||
|  | ||||
| struct _MetaBarrierImplX11 | ||||
| { | ||||
|   MetaBarrierImpl parent; | ||||
| }; | ||||
|  | ||||
| struct _MetaBarrierImplX11Class | ||||
| { | ||||
|   MetaBarrierImplClass parent_class; | ||||
| }; | ||||
|  | ||||
| GType meta_barrier_impl_x11_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| MetaBarrierImpl *meta_barrier_impl_x11_new (MetaBarrier *barrier); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* META_BARRIER_X11_H1 */ | ||||
| @@ -26,6 +26,8 @@ | ||||
|  | ||||
| #include "meta-cursor-renderer-x11.h" | ||||
|  | ||||
| #include <X11/extensions/Xfixes.h> | ||||
|  | ||||
| #include "meta-backend-x11.h" | ||||
| #include "meta-stage.h" | ||||
|  | ||||
| @@ -38,25 +40,29 @@ typedef struct _MetaCursorRendererX11Private MetaCursorRendererX11Private; | ||||
| G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRendererX11, meta_cursor_renderer_x11, META_TYPE_CURSOR_RENDERER); | ||||
|  | ||||
| static gboolean | ||||
| meta_cursor_renderer_x11_update_cursor (MetaCursorRenderer *renderer) | ||||
| meta_cursor_renderer_x11_update_cursor (MetaCursorRenderer *renderer, | ||||
|                                         MetaCursorSprite   *cursor_sprite) | ||||
| { | ||||
|   MetaCursorRendererX11 *x11 = META_CURSOR_RENDERER_X11 (renderer); | ||||
|   MetaCursorRendererX11Private *priv = meta_cursor_renderer_x11_get_instance_private (x11); | ||||
|  | ||||
|   MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ()); | ||||
|   Window xwindow = meta_backend_x11_get_xwindow (backend); | ||||
|  | ||||
|   if (xwindow == None) | ||||
|     return FALSE; | ||||
|  | ||||
|   Display *xdisplay = meta_backend_x11_get_xdisplay (backend); | ||||
|  | ||||
|   MetaCursorReference *cursor_ref = meta_cursor_renderer_get_cursor (renderer); | ||||
|   if (xwindow == None) | ||||
|     { | ||||
|       if (cursor_sprite) | ||||
|         meta_cursor_sprite_realize_texture (cursor_sprite); | ||||
|       return FALSE; | ||||
|     } | ||||
|  | ||||
|   gboolean has_server_cursor = FALSE; | ||||
|  | ||||
|   if (cursor_ref) | ||||
|   if (cursor_sprite) | ||||
|     { | ||||
|       MetaCursor cursor = meta_cursor_reference_get_meta_cursor (cursor_ref); | ||||
|       MetaCursor cursor = meta_cursor_sprite_get_meta_cursor (cursor_sprite); | ||||
|  | ||||
|       if (cursor != META_CURSOR_NONE) | ||||
|         { | ||||
|           Cursor xcursor = meta_cursor_create_x_cursor (xdisplay, cursor); | ||||
| @@ -78,6 +84,9 @@ meta_cursor_renderer_x11_update_cursor (MetaCursorRenderer *renderer) | ||||
|       priv->server_cursor_visible = has_server_cursor; | ||||
|     } | ||||
|  | ||||
|   if (!priv->server_cursor_visible && cursor_sprite) | ||||
|     meta_cursor_sprite_realize_texture (cursor_sprite); | ||||
|  | ||||
|   return priv->server_cursor_visible; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -107,20 +107,6 @@ set_alarm_enabled (Display    *dpy, | ||||
|   XSyncChangeAlarm (dpy, alarm, XSyncCAEvents, &attr); | ||||
| } | ||||
|  | ||||
| static void | ||||
| check_x11_watch (gpointer data, | ||||
|                  gpointer user_data) | ||||
| { | ||||
|   MetaIdleMonitorWatchXSync *watch_xsync = data; | ||||
|   MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_xsync; | ||||
|   XSyncAlarm alarm = (XSyncAlarm) user_data; | ||||
|  | ||||
|   if (watch_xsync->xalarm != alarm) | ||||
|     return; | ||||
|  | ||||
|   _meta_idle_monitor_watch_fire (watch); | ||||
| } | ||||
|  | ||||
| static char * | ||||
| counter_name_for_device (int device_id) | ||||
| { | ||||
| @@ -327,13 +313,38 @@ meta_idle_monitor_xsync_init (MetaIdleMonitorXSync *monitor_xsync) | ||||
|   monitor_xsync->alarms = g_hash_table_new (NULL, NULL); | ||||
| } | ||||
|  | ||||
| static void | ||||
| check_x11_watches (MetaIdleMonitor *monitor, | ||||
|                    XSyncAlarm       alarm) | ||||
| { | ||||
|   GList *node, *watch_ids; | ||||
|  | ||||
|   /* we get the keys and do explicit look ups in case | ||||
|    * an early iteration of the loop ends up leading | ||||
|    * to watches from later iterations getting invalidated | ||||
|    */ | ||||
|   watch_ids = g_hash_table_get_keys (monitor->watches); | ||||
|  | ||||
|   for (node = watch_ids; node != NULL; node = node->next) | ||||
|     { | ||||
|       guint watch_id = GPOINTER_TO_UINT (node->data); | ||||
|       MetaIdleMonitorWatchXSync *watch; | ||||
|  | ||||
|       watch = g_hash_table_lookup (monitor->watches, GUINT_TO_POINTER (watch_id)); | ||||
|  | ||||
|       if (watch && watch->xalarm == alarm) | ||||
|         _meta_idle_monitor_watch_fire ((MetaIdleMonitorWatch *) watch); | ||||
|     } | ||||
|  | ||||
|   g_list_free (watch_ids); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_idle_monitor_xsync_handle_xevent (MetaIdleMonitor       *monitor, | ||||
|                                        XSyncAlarmNotifyEvent *alarm_event) | ||||
| { | ||||
|   MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (monitor); | ||||
|   XSyncAlarm alarm; | ||||
|   GList *watches; | ||||
|   gboolean has_alarm; | ||||
|  | ||||
|   if (alarm_event->state != XSyncAlarmActive) | ||||
| @@ -358,10 +369,5 @@ meta_idle_monitor_xsync_handle_xevent (MetaIdleMonitor       *monitor, | ||||
|     } | ||||
|  | ||||
|   if (has_alarm) | ||||
|     { | ||||
|       watches = g_hash_table_get_values (monitor->watches); | ||||
|  | ||||
|       g_list_foreach (watches, check_x11_watch, (gpointer) alarm); | ||||
|       g_list_free (watches); | ||||
|     } | ||||
|     check_x11_watches (monitor, alarm); | ||||
| } | ||||
|   | ||||
							
								
								
									
										328
									
								
								src/backends/x11/meta-input-settings-x11.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										328
									
								
								src/backends/x11/meta-input-settings-x11.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,328 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2014 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Author: Carlos Garnacho <carlosg@gnome.org> | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include "meta-backend-x11.h" | ||||
| #include "meta-input-settings-x11.h" | ||||
|  | ||||
| #include <string.h> | ||||
| #include <gdk/gdkx.h> | ||||
| #include <X11/Xatom.h> | ||||
| #include <X11/extensions/XInput2.h> | ||||
| #include <X11/XKBlib.h> | ||||
|  | ||||
| #include <meta/errors.h> | ||||
|  | ||||
| G_DEFINE_TYPE (MetaInputSettingsX11, meta_input_settings_x11, META_TYPE_INPUT_SETTINGS) | ||||
|  | ||||
| static void * | ||||
| get_property (ClutterInputDevice *device, | ||||
|               const gchar        *property, | ||||
|               Atom                type, | ||||
|               int                 format, | ||||
|               gulong              nitems) | ||||
| { | ||||
|   MetaBackend *backend = meta_get_backend (); | ||||
|   Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); | ||||
|   gulong nitems_ret, bytes_after_ret; | ||||
|   int rc, device_id, format_ret; | ||||
|   Atom property_atom, type_ret; | ||||
|   guchar *data_ret = NULL; | ||||
|  | ||||
|   property_atom = XInternAtom (xdisplay, property, True); | ||||
|   if (!property_atom) | ||||
|     return NULL; | ||||
|  | ||||
|   device_id = clutter_input_device_get_device_id (device); | ||||
|  | ||||
|   rc = XIGetProperty (xdisplay, device_id, property_atom, | ||||
|                       0, 10, False, type, &type_ret, &format_ret, | ||||
|                       &nitems_ret, &bytes_after_ret, &data_ret); | ||||
|   if (rc == Success && type_ret == type && format_ret == format && nitems_ret >= nitems) | ||||
|     { | ||||
|       if (nitems_ret > nitems) | ||||
|         g_warning ("Property '%s' for device '%s' returned %lu items, expected %lu", | ||||
|                    property, clutter_input_device_get_device_name (device), nitems_ret, nitems); | ||||
|       return data_ret; | ||||
|     } | ||||
|  | ||||
|   meta_XFree (data_ret); | ||||
|   return NULL; | ||||
| } | ||||
|  | ||||
| static void | ||||
| change_property (ClutterInputDevice *device, | ||||
|                  const gchar        *property, | ||||
|                  Atom                type, | ||||
|                  int                 format, | ||||
|                  void               *data, | ||||
|                  gulong              nitems) | ||||
| { | ||||
|   MetaBackend *backend = meta_get_backend (); | ||||
|   Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); | ||||
|   int device_id; | ||||
|   Atom property_atom; | ||||
|   guchar *data_ret; | ||||
|  | ||||
|   property_atom = XInternAtom (xdisplay, property, True); | ||||
|   if (!property_atom) | ||||
|     return; | ||||
|  | ||||
|   device_id = clutter_input_device_get_device_id (device); | ||||
|  | ||||
|   data_ret = get_property (device, property, type, format, nitems); | ||||
|   if (!data_ret) | ||||
|     return; | ||||
|  | ||||
|   XIChangeProperty (xdisplay, device_id, property_atom, type, | ||||
|                     format, XIPropModeReplace, data, nitems); | ||||
|   meta_XFree (data_ret); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_settings_x11_set_send_events (MetaInputSettings        *settings, | ||||
|                                          ClutterInputDevice       *device, | ||||
|                                          GDesktopDeviceSendEvents  mode) | ||||
| { | ||||
|   guchar values[2] = { 0 }; /* disabled, disabled-on-external-mouse */ | ||||
|   guchar *available; | ||||
|  | ||||
|   available = get_property (device, "libinput Send Events Modes Available", | ||||
|                             XA_INTEGER, 8, 2); | ||||
|   if (!available) | ||||
|     return; | ||||
|  | ||||
|   switch (mode) | ||||
|     { | ||||
|     case G_DESKTOP_DEVICE_SEND_EVENTS_DISABLED: | ||||
|       values[0] = 1; | ||||
|       break; | ||||
|     case G_DESKTOP_DEVICE_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE: | ||||
|       values[1] = 1; | ||||
|       break; | ||||
|     default: | ||||
|       break; | ||||
|     } | ||||
|  | ||||
|   if ((values[0] && !available[0]) || (values[1] && !available[1])) | ||||
|     g_warning ("Device '%s' does not support sendevents mode %d\n", | ||||
|                clutter_input_device_get_device_name (device), mode); | ||||
|   else | ||||
|     change_property (device, "libinput Send Events Mode Enabled", | ||||
|                      XA_INTEGER, 8, &values, 2); | ||||
|  | ||||
|   meta_XFree (available); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_settings_x11_set_matrix (MetaInputSettings  *settings, | ||||
|                                     ClutterInputDevice *device, | ||||
|                                     gfloat              matrix[6]) | ||||
| { | ||||
|   MetaBackend *backend = meta_get_backend (); | ||||
|   Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); | ||||
|   gfloat full_matrix[9] = { matrix[0], matrix[1], matrix[2], | ||||
|                             matrix[3], matrix[4], matrix[5], | ||||
|                             0, 0, 1 }; | ||||
|  | ||||
|   change_property (device, "Coordinate Transformation Matrix", | ||||
|                    XInternAtom (xdisplay, "FLOAT", False), | ||||
|                    32, &full_matrix, 9); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_settings_x11_set_speed (MetaInputSettings  *settings, | ||||
|                                    ClutterInputDevice *device, | ||||
|                                    gdouble             speed) | ||||
| { | ||||
|   MetaBackend *backend = meta_get_backend (); | ||||
|   Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); | ||||
|   gfloat value = speed; | ||||
|  | ||||
|   change_property (device, "libinput Accel Speed", | ||||
|                    XInternAtom (xdisplay, "FLOAT", False), | ||||
|                    32, &value, 1); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_settings_x11_set_left_handed (MetaInputSettings  *settings, | ||||
|                                          ClutterInputDevice *device, | ||||
|                                          gboolean            enabled) | ||||
| { | ||||
|   guchar value = (enabled) ? 1 : 0; | ||||
|  | ||||
|   change_property (device, "libinput Left Handed Enabled", | ||||
|                    XA_INTEGER, 8, &value, 1); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_settings_x11_set_tap_enabled (MetaInputSettings  *settings, | ||||
|                                          ClutterInputDevice *device, | ||||
|                                          gboolean            enabled) | ||||
| { | ||||
|   guchar value = (enabled) ? 1 : 0; | ||||
|  | ||||
|   change_property (device, "libinput Tapping Enabled", | ||||
|                    XA_INTEGER, 8, &value, 1); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_settings_x11_set_invert_scroll (MetaInputSettings  *settings, | ||||
|                                            ClutterInputDevice *device, | ||||
|                                            gboolean            inverted) | ||||
| { | ||||
|   guchar value = (inverted) ? 1 : 0; | ||||
|  | ||||
|   change_property (device, "libinput Natural Scrolling Enabled", | ||||
|                    XA_INTEGER, 8, &value, 1); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_settings_x11_set_edge_scroll (MetaInputSettings            *settings, | ||||
|                                          ClutterInputDevice           *device, | ||||
|                                          gboolean                      edge_scroll_enabled) | ||||
| { | ||||
|   guchar values[3] = { 0 }; /* 2fg, edge, button. The last value is unused */ | ||||
|   guchar *available; | ||||
|  | ||||
|   available = get_property (device, "libinput Scroll Methods Available", | ||||
|                             XA_INTEGER, 8, 3); | ||||
|   if (!available) | ||||
|     return; | ||||
|  | ||||
|   if (available[0]) | ||||
|     { | ||||
|       values[0] = 1; | ||||
|     } | ||||
|   else if (available[1] && edge_scroll_enabled) | ||||
|     { | ||||
|       values[1] = 1; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       /* Disabled */ | ||||
|     } | ||||
|  | ||||
|   change_property (device, "libinput Scroll Method Enabled", | ||||
|                    XA_INTEGER, 8, &values, 3); | ||||
|  | ||||
|   meta_XFree (available); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_settings_x11_set_scroll_button (MetaInputSettings  *settings, | ||||
|                                            ClutterInputDevice *device, | ||||
|                                            guint               button) | ||||
| { | ||||
|   change_property (device, "libinput Button Scrolling Button", | ||||
|                    XA_INTEGER, 32, &button, 1); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_settings_x11_set_click_method (MetaInputSettings           *settings, | ||||
|                                           ClutterInputDevice          *device, | ||||
|                                           GDesktopTouchpadClickMethod  mode) | ||||
| { | ||||
|   guchar values[2] = { 0 }; /* buttonareas, clickfinger */ | ||||
|   guchar *defaults, *available; | ||||
|  | ||||
|   available = get_property (device, "libinput Click Methods Available", | ||||
|                             XA_INTEGER, 8, 2); | ||||
|   if (!available) | ||||
|     return; | ||||
|  | ||||
|   switch (mode) | ||||
|     { | ||||
|     case G_DESKTOP_TOUCHPAD_CLICK_METHOD_DEFAULT: | ||||
|       defaults = get_property (device, "libinput Click Method Enabled Default", | ||||
|                                XA_INTEGER, 8, 2); | ||||
|       if (!defaults) | ||||
|         break; | ||||
|       memcpy (values, defaults, 2); | ||||
|       meta_XFree (defaults); | ||||
|       break; | ||||
|     case G_DESKTOP_TOUCHPAD_CLICK_METHOD_NONE: | ||||
|       break; | ||||
|     case G_DESKTOP_TOUCHPAD_CLICK_METHOD_AREAS: | ||||
|       values[0] = 1; | ||||
|       break; | ||||
|     case G_DESKTOP_TOUCHPAD_CLICK_METHOD_FINGERS: | ||||
|       values[1] = 1; | ||||
|       break; | ||||
|     default: | ||||
|       g_assert_not_reached (); | ||||
|       return; | ||||
|   } | ||||
|  | ||||
|   if ((values[0] && !available[0]) || (values[1] && !available[1])) | ||||
|     g_warning ("Device '%s' does not support click method %d\n", | ||||
|                clutter_input_device_get_device_name (device), mode); | ||||
|   else | ||||
|     change_property (device, "libinput Click Method Enabled", | ||||
|                      XA_INTEGER, 8, &values, 2); | ||||
|  | ||||
|   meta_XFree(available); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_settings_x11_set_keyboard_repeat (MetaInputSettings *settings, | ||||
|                                              gboolean           enabled, | ||||
|                                              guint              delay, | ||||
|                                              guint              interval) | ||||
| { | ||||
|   MetaBackend *backend = meta_get_backend (); | ||||
|   Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); | ||||
|  | ||||
|   if (enabled) | ||||
|     { | ||||
|       XAutoRepeatOn (xdisplay); | ||||
|       XkbSetAutoRepeatRate (xdisplay, XkbUseCoreKbd, delay, interval); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       XAutoRepeatOff (xdisplay); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_settings_x11_class_init (MetaInputSettingsX11Class *klass) | ||||
| { | ||||
|   MetaInputSettingsClass *input_settings_class = META_INPUT_SETTINGS_CLASS (klass); | ||||
|  | ||||
|   input_settings_class->set_send_events = meta_input_settings_x11_set_send_events; | ||||
|   input_settings_class->set_matrix = meta_input_settings_x11_set_matrix; | ||||
|   input_settings_class->set_speed = meta_input_settings_x11_set_speed; | ||||
|   input_settings_class->set_left_handed = meta_input_settings_x11_set_left_handed; | ||||
|   input_settings_class->set_tap_enabled = meta_input_settings_x11_set_tap_enabled; | ||||
|   input_settings_class->set_invert_scroll = meta_input_settings_x11_set_invert_scroll; | ||||
|   input_settings_class->set_edge_scroll = meta_input_settings_x11_set_edge_scroll; | ||||
|   input_settings_class->set_scroll_button = meta_input_settings_x11_set_scroll_button; | ||||
|   input_settings_class->set_click_method = meta_input_settings_x11_set_click_method; | ||||
|   input_settings_class->set_keyboard_repeat = meta_input_settings_x11_set_keyboard_repeat; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_input_settings_x11_init (MetaInputSettingsX11 *settings) | ||||
| { | ||||
| } | ||||
							
								
								
									
										49
									
								
								src/backends/x11/meta-input-settings-x11.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/backends/x11/meta-input-settings-x11.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright 2014 Red Hat, Inc. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * Author: Carlos Garnacho <carlosg@gnome.org> | ||||
|  */ | ||||
|  | ||||
| #ifndef META_INPUT_SETTINGS_X11_H | ||||
| #define META_INPUT_SETTINGS_X11_H | ||||
|  | ||||
| #include "meta-input-settings-private.h" | ||||
|  | ||||
| #define META_TYPE_INPUT_SETTINGS_X11             (meta_input_settings_x11_get_type ()) | ||||
| #define META_INPUT_SETTINGS_X11(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_INPUT_SETTINGS_X11, MetaInputSettingsX11)) | ||||
| #define META_INPUT_SETTINGS_X11_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_INPUT_SETTINGS_X11, MetaInputSettingsX11Class)) | ||||
| #define META_IS_INPUT_SETTINGS_X11(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_INPUT_SETTINGS_X11)) | ||||
| #define META_IS_INPUT_SETTINGS_X11_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_INPUT_SETTINGS_X11)) | ||||
| #define META_INPUT_SETTINGS_X11_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_INPUT_SETTINGS_X11, MetaInputSettingsX11Class)) | ||||
|  | ||||
| typedef struct _MetaInputSettingsX11 MetaInputSettingsX11; | ||||
| typedef struct _MetaInputSettingsX11Class MetaInputSettingsX11Class; | ||||
|  | ||||
| struct _MetaInputSettingsX11 | ||||
| { | ||||
|   MetaInputSettings parent_instance; | ||||
| }; | ||||
|  | ||||
| struct _MetaInputSettingsX11Class | ||||
| { | ||||
|   MetaInputSettingsClass parent_class; | ||||
| }; | ||||
|  | ||||
| GType meta_input_settings_x11_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| #endif /* META_INPUT_SETTINGS_X11_H */ | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user