Compare commits
432 Commits
wip/xtogls
...
wip/dnd-su
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7947bcb0b0 | ||
![]() |
308cccc72c | ||
![]() |
074946ac0b | ||
![]() |
9688a0d7bc | ||
![]() |
604d2155ba | ||
![]() |
e7727d698f | ||
![]() |
a3f75f401c | ||
![]() |
d342f7c429 | ||
![]() |
bb2b26ca44 | ||
![]() |
2f9840a51c | ||
![]() |
09aefdba43 | ||
![]() |
4c8a408afc | ||
![]() |
4c08d9a53b | ||
![]() |
b091cbf361 | ||
![]() |
a6fcda69ac | ||
![]() |
9063e4568c | ||
![]() |
3d37b5d696 | ||
![]() |
3a8bad1e6f | ||
![]() |
e822e51752 | ||
![]() |
f9818f890b | ||
![]() |
6526118d9f | ||
![]() |
c15b3b4a09 | ||
![]() |
e1acb69cf1 | ||
![]() |
8f757c7b80 | ||
![]() |
01a47c7d6d | ||
![]() |
3ee09c6251 | ||
![]() |
bb54f91dd1 | ||
![]() |
41a79530e9 | ||
![]() |
31f5a916f4 | ||
![]() |
5657a671c1 | ||
![]() |
ecc254c659 | ||
![]() |
9cb1c95e49 | ||
![]() |
e73c46ce03 | ||
![]() |
952e9c52bc | ||
![]() |
b879af46b3 | ||
![]() |
9feb9d6bca | ||
![]() |
dc0437a5b5 | ||
![]() |
55331a0678 | ||
![]() |
f5580f61f9 | ||
![]() |
30953cf2d7 | ||
![]() |
c7fa446ee7 | ||
![]() |
9ecbac365b | ||
![]() |
80f6fb6329 | ||
![]() |
1b596a114d | ||
![]() |
265c00235b | ||
![]() |
fae37222a7 | ||
![]() |
d41449b578 | ||
![]() |
34979c3fe8 | ||
![]() |
711f0c0c50 | ||
![]() |
933d05a565 | ||
![]() |
8a0da1cb07 | ||
![]() |
1445903a34 | ||
![]() |
5d9386df0c | ||
![]() |
6fd1de226b | ||
![]() |
ac099343da | ||
![]() |
bce5f3f108 | ||
![]() |
35e0982e35 | ||
![]() |
767455e8d8 | ||
![]() |
6b8dda0d00 | ||
![]() |
277df44cfb | ||
![]() |
2dded1e510 | ||
![]() |
a7b1b1da80 | ||
![]() |
de69678085 | ||
![]() |
5f7b81eb95 | ||
![]() |
f4f70afe31 | ||
![]() |
116957b339 | ||
![]() |
1af0033368 | ||
![]() |
3645c63c08 | ||
![]() |
04ddfe0a6f | ||
![]() |
ec3dc4a607 | ||
![]() |
0b98fbab0a | ||
![]() |
5b8dc37c31 | ||
![]() |
f42258327b | ||
![]() |
7d1ef3f447 | ||
![]() |
652fe57cdd | ||
![]() |
20a6243c85 | ||
![]() |
679edac9c3 | ||
![]() |
bb59b8c249 | ||
![]() |
c5c6b2257f | ||
![]() |
6acf7b06f4 | ||
![]() |
d0c004c93c | ||
![]() |
53876d2b62 | ||
![]() |
2b63b17327 | ||
![]() |
226a09b38c | ||
![]() |
527c53a2a0 | ||
![]() |
19795c1681 | ||
![]() |
1999fcaa8f | ||
![]() |
6b5ff8fd74 | ||
![]() |
821d946a72 | ||
![]() |
5f7c901727 | ||
![]() |
7b8ee4ee1e | ||
![]() |
32cf4afb04 | ||
![]() |
e0c92befd5 | ||
![]() |
827e0341ab | ||
![]() |
8627b65f8d | ||
![]() |
9c62a907c5 | ||
![]() |
a119ea96a3 | ||
![]() |
06d55bf019 | ||
![]() |
320f38de47 | ||
![]() |
7adfaceccf | ||
![]() |
67be4e2bf3 | ||
![]() |
c3e87ee896 | ||
![]() |
f2283ec634 | ||
![]() |
d06e4beb7f | ||
![]() |
e24863d175 | ||
![]() |
2de2241690 | ||
![]() |
977de8c5d4 | ||
![]() |
fb6438cdd4 | ||
![]() |
517e8f6fbd | ||
![]() |
0e758a9e65 | ||
![]() |
64a915a68d | ||
![]() |
d233238c64 | ||
![]() |
71a4fe746e | ||
![]() |
f28c7835a1 | ||
![]() |
cecf7f4bf0 | ||
![]() |
c687cf9db6 | ||
![]() |
54d2218ac2 | ||
![]() |
471e6b9e13 | ||
![]() |
f8dcea3975 | ||
![]() |
d931af33c4 | ||
![]() |
a0e3c05428 | ||
![]() |
b8c13cc426 | ||
![]() |
38253a9f73 | ||
![]() |
cbc92b847f | ||
![]() |
a5f993f269 | ||
![]() |
31361e464a | ||
![]() |
bb977c00ca | ||
![]() |
39f65f9f86 | ||
![]() |
bda2d6d1ac | ||
![]() |
1e225ecdaf | ||
![]() |
cfb85d9a9a | ||
![]() |
f88c20f335 | ||
![]() |
c98824bc9e | ||
![]() |
69a35bb85f | ||
![]() |
a3bb6c12e5 | ||
![]() |
586f118279 | ||
![]() |
31081e5dac | ||
![]() |
ef363e9d2e | ||
![]() |
9fa77acb8c | ||
![]() |
1e30db64d1 | ||
![]() |
e830b66604 | ||
![]() |
5f0fab2156 | ||
![]() |
467465c99c | ||
![]() |
e935b52e51 | ||
![]() |
879407c10c | ||
![]() |
e76be14dbb | ||
![]() |
7fa15c74b4 | ||
![]() |
c3950699bf | ||
![]() |
e6b950e31b | ||
![]() |
9440bdb1aa | ||
![]() |
e320b06aaa | ||
![]() |
b284126d3b | ||
![]() |
6858cb261f | ||
![]() |
2d6954186e | ||
![]() |
d72bf0cd5d | ||
![]() |
584460deec | ||
![]() |
e3d5969282 | ||
![]() |
249468bbea | ||
![]() |
f0f4c31d96 | ||
![]() |
27f012ffad | ||
![]() |
7d54631ebf | ||
![]() |
513628e4ad | ||
![]() |
101b215d6b | ||
![]() |
6af48de0b8 | ||
![]() |
e5c4fedd55 | ||
![]() |
2ce23072d3 | ||
![]() |
97f4eb6b75 | ||
![]() |
75cbf3d730 | ||
![]() |
bf9fdf448d | ||
![]() |
63c627ec18 | ||
![]() |
dadbd793be | ||
![]() |
75b6e917ad | ||
![]() |
ab53c0e943 | ||
![]() |
c2fe6a18ad | ||
![]() |
b7119c55a6 | ||
![]() |
d0f2c6be6d | ||
![]() |
3a535b6722 | ||
![]() |
f9a77aec3f | ||
![]() |
bee6d2b240 | ||
![]() |
9a6a189e36 | ||
![]() |
505eabb78c | ||
![]() |
b0ba325f0e | ||
![]() |
6fbd21001b | ||
![]() |
626e4965b1 | ||
![]() |
a15042b7e5 | ||
![]() |
e56f963574 | ||
![]() |
65a8f9100c | ||
![]() |
6954d23444 | ||
![]() |
6c624e1c26 | ||
![]() |
cc839029b9 | ||
![]() |
25f8eaf1ac | ||
![]() |
8fdd226b8b | ||
![]() |
6c5595fa9c | ||
![]() |
e6558f838e | ||
![]() |
57037a45b8 | ||
![]() |
c844611052 | ||
![]() |
b60e02956d | ||
![]() |
4fe66ce0a9 | ||
![]() |
4b5a503cee | ||
![]() |
817995d97f | ||
![]() |
0e7221c361 | ||
![]() |
938fb8e6c8 | ||
![]() |
fd8c49ff0a | ||
![]() |
cd84317346 | ||
![]() |
4f55e16fe9 | ||
![]() |
c30ef668de | ||
![]() |
62e0c42803 | ||
![]() |
70aee2d95e | ||
![]() |
63c7591698 | ||
![]() |
930361b988 | ||
![]() |
baadb75a5e | ||
![]() |
f28f5dc0b6 | ||
![]() |
41fdc4ac2e | ||
![]() |
177ec27cca | ||
![]() |
37652ca2cf | ||
![]() |
6c22759d29 | ||
![]() |
25b6a40ad4 | ||
![]() |
fbea59b326 | ||
![]() |
38e4906f72 | ||
![]() |
029d69919b | ||
![]() |
5e395fb676 | ||
![]() |
ac448bd42b | ||
![]() |
f55737ec06 | ||
![]() |
80de15face | ||
![]() |
32565e096d | ||
![]() |
1d8e4bdd6d | ||
![]() |
1677a068ce | ||
![]() |
a02b8441b1 | ||
![]() |
dfe1c106f2 | ||
![]() |
e49bbe2ed8 | ||
![]() |
6ee5a1437c | ||
![]() |
93a3383e60 | ||
![]() |
c9a2a561f8 | ||
![]() |
ac0b2fdc6f | ||
![]() |
46b9984414 | ||
![]() |
f9743e2174 | ||
![]() |
a3c55c2692 | ||
![]() |
692eb4d957 | ||
![]() |
826751429b | ||
![]() |
5621d3c0c7 | ||
![]() |
b5f46c9171 | ||
![]() |
166b8c042c | ||
![]() |
d34ece6f1a | ||
![]() |
679844f791 | ||
![]() |
9316256e10 | ||
![]() |
90d7737fc1 | ||
![]() |
567ca15610 | ||
![]() |
558b323485 | ||
![]() |
1a05da8296 | ||
![]() |
5df59f75cd | ||
![]() |
029673d0ee | ||
![]() |
3a57f843d5 | ||
![]() |
182a267f69 | ||
![]() |
3de40434fa | ||
![]() |
bc8328d7c2 | ||
![]() |
12c1a06e60 | ||
![]() |
b11405570a | ||
![]() |
3b85e4b2b9 | ||
![]() |
c5abf5ddbb | ||
![]() |
2a3d4b62a7 | ||
![]() |
8ff81bcc37 | ||
![]() |
7159d3bc35 | ||
![]() |
941d202938 | ||
![]() |
5ea0cf8bab | ||
![]() |
df9a5f867f | ||
![]() |
06e4778072 | ||
![]() |
92388892b3 | ||
![]() |
5d124ac00a | ||
![]() |
a57c3ae105 | ||
![]() |
55354f5c38 | ||
![]() |
379bb0a77d | ||
![]() |
39357fc242 | ||
![]() |
799de4f0f4 | ||
![]() |
c34b5c1cf0 | ||
![]() |
46361c3e28 | ||
![]() |
f9d33b2efc | ||
![]() |
2185904fcb | ||
![]() |
eb952819c2 | ||
![]() |
d7d8c92a9a | ||
![]() |
88a7790d44 | ||
![]() |
806dabe2d7 | ||
![]() |
740e7ddd69 | ||
![]() |
bee97ab6a7 | ||
![]() |
59fc17c355 | ||
![]() |
5f25ca0c3a | ||
![]() |
41b4a079c7 | ||
![]() |
e4235376d8 | ||
![]() |
043a201f90 | ||
![]() |
d1a588a94f | ||
![]() |
01b6d9bfe2 | ||
![]() |
9711d95996 | ||
![]() |
b87db00fdb | ||
![]() |
6190b65056 | ||
![]() |
10fe91d704 | ||
![]() |
36bb05b10e | ||
![]() |
a7b7213017 | ||
![]() |
031154a400 | ||
![]() |
463b50e746 | ||
![]() |
1749a85e96 | ||
![]() |
1af9e92e91 | ||
![]() |
12d0c98fb5 | ||
![]() |
817c6986a0 | ||
![]() |
7c68aaea4c | ||
![]() |
6fea46e0cf | ||
![]() |
59fa74fed1 | ||
![]() |
581335fbea | ||
![]() |
9b5d6cc008 | ||
![]() |
d0f98ec1ba | ||
![]() |
a977fcf3d0 | ||
![]() |
664f6ef420 | ||
![]() |
06a31992e3 | ||
![]() |
4e2092d593 | ||
![]() |
9755f308e5 | ||
![]() |
09610daea1 | ||
![]() |
13b7fa4eba | ||
![]() |
909a46087f | ||
![]() |
c10c8649f5 | ||
![]() |
82dce6758a | ||
![]() |
024652bfb4 | ||
![]() |
789608b637 | ||
![]() |
d05b750b8d | ||
![]() |
704cae1de3 | ||
![]() |
23b074481a | ||
![]() |
5dc8fa6690 | ||
![]() |
a9ba98686f | ||
![]() |
59382bace2 | ||
![]() |
2edf822bc6 | ||
![]() |
355621b0ab | ||
![]() |
a307e13a63 | ||
![]() |
f807207b65 | ||
![]() |
30b54aae34 | ||
![]() |
79e682bcd0 | ||
![]() |
a05ae8654c | ||
![]() |
0db172edbf | ||
![]() |
7b0930f798 | ||
![]() |
0919b37c34 | ||
![]() |
faf55c4627 | ||
![]() |
f351c5d304 | ||
![]() |
63bca17ab6 | ||
![]() |
c2abe43ee7 | ||
![]() |
1de2fd7122 | ||
![]() |
e377e82cfd | ||
![]() |
fa8174a200 | ||
![]() |
d22448731c | ||
![]() |
ef95133b1c | ||
![]() |
c068c2122d | ||
![]() |
d8c47b0abd | ||
![]() |
66eb4bc34c | ||
![]() |
bce812ecbc | ||
![]() |
02220ed6c7 | ||
![]() |
8d08851f28 | ||
![]() |
af135c0b0b | ||
![]() |
42c972735e | ||
![]() |
110c79d10e | ||
![]() |
b9d867cb86 | ||
![]() |
ea3b961e43 | ||
![]() |
bc510378b3 | ||
![]() |
0a47d135ac | ||
![]() |
ec8ed1dbb0 | ||
![]() |
203e5335ab | ||
![]() |
f1d8428650 | ||
![]() |
8d29d22e99 | ||
![]() |
9c6e527d4b | ||
![]() |
077606c057 | ||
![]() |
a615f93060 | ||
![]() |
c562657f1e | ||
![]() |
7b3922f8e9 | ||
![]() |
c14382181f | ||
![]() |
b2183dfda7 | ||
![]() |
bb92054c86 | ||
![]() |
4e4a6eb5d7 | ||
![]() |
692acbd986 | ||
![]() |
901901825c | ||
![]() |
97f2de37e1 | ||
![]() |
967b6c33df | ||
![]() |
00c7a27732 | ||
![]() |
048ba353c4 | ||
![]() |
555e2f6de2 | ||
![]() |
ff8d5281f0 | ||
![]() |
4f9b994e73 | ||
![]() |
b8b0dc5c78 | ||
![]() |
d0cafab836 | ||
![]() |
24d7c5ebe3 | ||
![]() |
dc6decefb5 | ||
![]() |
25d7e48077 | ||
![]() |
b0b8f37240 | ||
![]() |
188e4e1b92 | ||
![]() |
9d5273bb15 | ||
![]() |
3c0fae74f1 | ||
![]() |
86dae6d4c7 | ||
![]() |
d06600aeb0 | ||
![]() |
895a3d1f39 | ||
![]() |
381ef5c683 | ||
![]() |
62097897be | ||
![]() |
2d2c47ba49 | ||
![]() |
89cdfc9194 | ||
![]() |
ad60ea9e0e | ||
![]() |
a7350475e8 | ||
![]() |
f3d7c9cff9 | ||
![]() |
906cbeed61 | ||
![]() |
0fccb0fc86 | ||
![]() |
8100cefd4c | ||
![]() |
d7e99a3f86 | ||
![]() |
6af944fe2c | ||
![]() |
12fc394b92 | ||
![]() |
53814fefc1 | ||
![]() |
e87a01c80b | ||
![]() |
21d7c1a850 | ||
![]() |
e33c58297d | ||
![]() |
5350120db4 | ||
![]() |
0997cf7fee | ||
![]() |
af3aae7295 | ||
![]() |
98e219da4b | ||
![]() |
fba022cc06 | ||
![]() |
3f6c6f1dd9 | ||
![]() |
ebc2e7221b | ||
![]() |
7cb30ced23 | ||
![]() |
7b449ac56c | ||
![]() |
724953101d | ||
![]() |
8734477d52 | ||
![]() |
ec8ba4b5f9 | ||
![]() |
2250865eb6 | ||
![]() |
847a3bbee3 | ||
![]() |
410a002ddd | ||
![]() |
8766db2593 | ||
![]() |
e362227514 | ||
![]() |
da311f266d | ||
![]() |
f5a4e996a8 | ||
![]() |
a7f083897f | ||
![]() |
e2105dc721 | ||
![]() |
b64548ee1f | ||
![]() |
53425fa721 |
35
.cvsignore
35
.cvsignore
@@ -1,35 +0,0 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
confdefs.h
|
||||
config.cache
|
||||
config.guess
|
||||
config.h
|
||||
config.log
|
||||
config.status
|
||||
config.sub
|
||||
configure
|
||||
configure.scan
|
||||
libtool
|
||||
ltconfig
|
||||
ltmain.sh
|
||||
stamp-h
|
||||
stamp-h.in
|
||||
stamp-h1
|
||||
stamp.h
|
||||
version.h
|
||||
config.h.in
|
||||
install-sh
|
||||
missing
|
||||
mkinstalldirs
|
||||
INSTALL
|
||||
intl
|
||||
ABOUT-NLS
|
||||
COPYING
|
||||
intltool-*
|
||||
metacity.spec
|
||||
autom4te.cache
|
||||
compile
|
||||
depcomp
|
||||
omf.make
|
||||
xmldocs.make
|
32
.gitignore
vendored
32
.gitignore
vendored
@@ -3,6 +3,7 @@ Makefile.in
|
||||
Makefile.in.in
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
build-aux
|
||||
compile
|
||||
config.guess
|
||||
config.h
|
||||
@@ -19,11 +20,11 @@ libtool
|
||||
ltmain.sh
|
||||
missing
|
||||
.deps
|
||||
src/50-mutter-navigation.xml
|
||||
src/50-mutter-system.xml
|
||||
src/50-mutter-windows.xml
|
||||
src/mutter.desktop
|
||||
src/mutter-wayland.desktop
|
||||
50-mutter-navigation.xml
|
||||
50-mutter-system.xml
|
||||
50-mutter-windows.xml
|
||||
mutter.desktop
|
||||
mutter-wayland.desktop
|
||||
*.o
|
||||
*.a
|
||||
*.lo
|
||||
@@ -32,10 +33,6 @@ src/mutter-wayland.desktop
|
||||
*.swp
|
||||
*.gir
|
||||
*.typelib
|
||||
tidy-enum-types.[ch]
|
||||
tidy-marshal.[ch]
|
||||
stamp-tidy-enum-types.h
|
||||
stamp-tidy-marshal.h
|
||||
stamp-h1
|
||||
*.gmo
|
||||
*.make
|
||||
@@ -44,10 +41,9 @@ stamp-it
|
||||
.intltool-merge-cache
|
||||
POTFILES
|
||||
po/*.pot
|
||||
50-metacity-desktop-key.xml
|
||||
50-metacity-key.xml
|
||||
libmutter.pc
|
||||
mutter
|
||||
mutter-restart-helper
|
||||
org.gnome.mutter.gschema.valid
|
||||
org.gnome.mutter.gschema.xml
|
||||
org.gnome.mutter.wayland.gschema.valid
|
||||
@@ -56,19 +52,6 @@ testasyncgetprop
|
||||
testboxes
|
||||
testgradient
|
||||
m4/*
|
||||
mutter-grayscale
|
||||
mutter-mag
|
||||
mutter-message
|
||||
mutter-window-demo
|
||||
focus-window
|
||||
test-attached
|
||||
test-focus
|
||||
test-gravity
|
||||
test-resizing
|
||||
test-size-hints
|
||||
# We can't say just "wm-tester" here or it will ignore the directory
|
||||
# rather than the binary
|
||||
src/wm-tester/wm-tester
|
||||
INSTALL
|
||||
mkinstalldirs
|
||||
src/mutter-enum-types.[ch]
|
||||
@@ -84,6 +67,7 @@ src/xdg-shell-protocol.c
|
||||
src/xdg-shell-server-protocol.h
|
||||
src/xserver-protocol.c
|
||||
src/xserver-server-protocol.h
|
||||
src/meta/meta-version.h
|
||||
doc/reference/*.args
|
||||
doc/reference/*.bak
|
||||
doc/reference/*.hierarchy
|
||||
|
11
Makefile.am
11
Makefile.am
@@ -1,10 +1,13 @@
|
||||
|
||||
SUBDIRS=src po doc
|
||||
SUBDIRS = data src po doc
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
|
||||
|
||||
DISTCLEANFILES = intltool-extract intltool-merge intltool-update po/stamp-it po/.intltool-merge-cache
|
||||
DISTCLEANFILES = \
|
||||
intltool-extract \
|
||||
intltool-merge \
|
||||
intltool-update \
|
||||
po/stamp-it \
|
||||
po/.intltool-merge-cache
|
||||
|
||||
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
|
||||
|
59
NEWS
59
NEWS
@@ -1,3 +1,62 @@
|
||||
3.13.90
|
||||
=======
|
||||
* Only call XSync() once per frame [Rui; #728464]
|
||||
* Update capabilities on device list changes [Carlos; #733563]
|
||||
* Make use of GLSL optional [Adel; #733623]
|
||||
* Handle gestures and touch events on wayland [Carlos; #733631]
|
||||
* Add support for unminimize compositor effects [Cosimo; #733789]
|
||||
* Always set the frame background to None [Giovanni; #734054]
|
||||
* Add backend methods to handle keymaps [Rui; #734301]
|
||||
* Actually mark revalidated MetaTextureTower levels as valid [Owen; #734400]
|
||||
* Rely on explicit -backward switcher keybindings instead of <shift>-magic
|
||||
[Christophe; #732295, #732385]
|
||||
* Misc. bug fixes and cleanups [Rui, Adel, Christophe; #727178, #734852,
|
||||
#734960]
|
||||
|
||||
Contributors:
|
||||
Emmanuele Bassi, Giovanni Campagna, Cosimo Cecchi, Piotr Drąg,
|
||||
Christophe Fergeau, Adel Gadllah, Carlos Garnacho, Rui Matos,
|
||||
Florian Müllner, Jasper St. Pierre, Rico Tzschichholz, Olav Vitters,
|
||||
Owen W. Taylor
|
||||
|
||||
Translations:
|
||||
Kjartan Maraas [nb], Inaki Larranaga Murgoitio [eu], Lasse Liehu [fi],
|
||||
ngoswami [as], Daniel Mustieles [es]
|
||||
|
||||
3.13.4
|
||||
======
|
||||
* Fix move/resize operations for wayland clients [Marek; #731237]
|
||||
* Add ::first-frame signal to MetaWindowActor [Owen; #732343]
|
||||
* Handle keysyms without the XF86 prefix [Owen; #727993]
|
||||
* Add touch gesture support [Carlos]
|
||||
* Fix a deadlock when exiting [Owen; #733068]
|
||||
* Add framework for restarting the compositor with nice visuals
|
||||
[Owen; #733026]
|
||||
* Toggle seat capabilities on VT switch [Carlos; #733563]
|
||||
* Misc bug fixes [Florian, Owen; #732695, #732350]
|
||||
|
||||
Contributors:
|
||||
Tom Beckmann, Giovanni Campagna, Marek Chalupa, Adel Gadllah,
|
||||
Carlos Garnacho, Florian Müllner, Jasper St. Pierre, Rico Tzschichholz,
|
||||
Owen W. Taylor
|
||||
|
||||
Translations:
|
||||
Yuri Myasoedov [ru], Fran Diéguez [gl], Aurimas Černius [lt], MarMav [el],
|
||||
Enrico Nicoletto [pt_BR]
|
||||
|
||||
3.13.3
|
||||
======
|
||||
* Improve behavior of window buttons with compositor menus [Florian; #731058]
|
||||
* Implement touch support on wayland [Carlos; #724442]
|
||||
* Update window shadows [Nikita; #731866]
|
||||
* Keep windows on the preferred output [Florian; #731760]
|
||||
* Misc bug fixes [Jonas, Florian, Jasper; #729601, #730681, #731353, #731332,
|
||||
#730527, #662962]
|
||||
|
||||
Contributors:
|
||||
Jonas Ådahl, Nikita Churaev, Carlos Garnacho, Florian Müllner,
|
||||
Jasper St. Pierre, Rico Tzschichholz
|
||||
|
||||
3.13.2
|
||||
======
|
||||
* Add basic HiDPI support on wayland [Adel; #728902]
|
||||
|
@@ -5,7 +5,7 @@ srcdir=`dirname $0`
|
||||
test -z "$srcdir" && srcdir=.
|
||||
|
||||
PKG_NAME="mutter"
|
||||
REQUIRED_AUTOMAKE_VERSION=1.10
|
||||
REQUIRED_AUTOMAKE_VERSION=1.11
|
||||
|
||||
(test -f $srcdir/configure.ac \
|
||||
&& test -d $srcdir/src) || {
|
||||
|
99
configure.ac
99
configure.ac
@@ -1,9 +1,8 @@
|
||||
AC_PREREQ(2.50)
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_PREREQ(2.62)
|
||||
|
||||
m4_define([mutter_major_version], [3])
|
||||
m4_define([mutter_minor_version], [13])
|
||||
m4_define([mutter_micro_version], [2])
|
||||
m4_define([mutter_micro_version], [90])
|
||||
|
||||
m4_define([mutter_version],
|
||||
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
||||
@@ -14,6 +13,7 @@ AC_INIT([mutter], [mutter_version],
|
||||
[http://bugzilla.gnome.org/enter_bug.cgi?product=mutter])
|
||||
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_SRCDIR(src/core/display.c)
|
||||
AC_CONFIG_HEADERS(config.h)
|
||||
|
||||
@@ -40,12 +40,14 @@ GETTEXT_PACKAGE=mutter
|
||||
AC_SUBST(GETTEXT_PACKAGE)
|
||||
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[Name of default gettext domain])
|
||||
|
||||
IT_PROG_INTLTOOL([0.34.90])
|
||||
LT_PREREQ([2.2.6])
|
||||
LT_INIT([disable-static])
|
||||
IT_PROG_INTLTOOL([0.41])
|
||||
AC_PROG_CC
|
||||
AC_ISC_POSIX
|
||||
AC_PROG_CC_C_O
|
||||
AC_PROG_INSTALL
|
||||
AC_HEADER_STDC
|
||||
AC_LIBTOOL_WIN32_DLL
|
||||
AM_PROG_LIBTOOL
|
||||
PKG_PROG_PKG_CONFIG([0.21])
|
||||
|
||||
# Sets GLIB_GENMARSHAL and GLIB_MKENUMS
|
||||
AM_PATH_GLIB_2_0()
|
||||
@@ -70,15 +72,28 @@ CLUTTER_PACKAGE=clutter-1.0
|
||||
|
||||
MUTTER_PC_MODULES="
|
||||
gtk+-3.0 >= 3.9.11
|
||||
gio-2.0 >= 2.25.10
|
||||
gio-unix-2.0 >= 2.25.10
|
||||
pango >= 1.2.0
|
||||
cairo >= 1.10.0
|
||||
gsettings-desktop-schemas >= 3.7.3
|
||||
xcomposite >= 0.2 xfixes xext xdamage xi >= 1.6.0
|
||||
$CLUTTER_PACKAGE >= 1.17.5
|
||||
$CLUTTER_PACKAGE >= 1.19.5
|
||||
clutter-egl-1.0
|
||||
cogl-1.0 >= 1.17.1
|
||||
gbm
|
||||
upower-glib >= 0.99.0
|
||||
gnome-desktop-3.0
|
||||
xcomposite >= 0.2
|
||||
xcursor
|
||||
xdamage
|
||||
xext
|
||||
xfixes
|
||||
xi >= 1.6.0
|
||||
xkbfile
|
||||
xkeyboard-config
|
||||
xkbcommon >= 0.4.3
|
||||
xkbcommon-x11
|
||||
x11-xcb
|
||||
xcb-randr
|
||||
"
|
||||
|
||||
GLIB_GSETTINGS
|
||||
@@ -107,26 +122,12 @@ AC_ARG_WITH(libcanberra,
|
||||
[disable the use of libcanberra for playing sounds]),,
|
||||
with_libcanberra=auto)
|
||||
|
||||
AC_ARG_ENABLE(xsync,
|
||||
AC_HELP_STRING([--disable-xsync],
|
||||
[disable mutter's use of the XSync extension]),,
|
||||
enable_xsync=auto)
|
||||
|
||||
AC_ARG_ENABLE(shape,
|
||||
AC_HELP_STRING([--disable-shape],
|
||||
[disable mutter's use of the shaped window extension]),,
|
||||
enable_shape=auto)
|
||||
|
||||
AC_ARG_WITH([xwayland-path],
|
||||
[AS_HELP_STRING([--with-xwayland-path], [Absolute path for an X Wayland server])],
|
||||
[XWAYLAND_PATH="$withval"],
|
||||
[XWAYLAND_PATH="$bindir/Xwayland"])
|
||||
|
||||
AM_GLIB_GNU_GETTEXT
|
||||
|
||||
## here we get the flags we'll actually use
|
||||
# GRegex requires Glib-2.14.0
|
||||
PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.14.0)
|
||||
|
||||
# Unconditionally use this dir to avoid a circular dep with gnomecc
|
||||
GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings"
|
||||
@@ -191,23 +192,27 @@ if test x$found_introspection != xno; then
|
||||
AC_SUBST(META_GIR)
|
||||
fi
|
||||
|
||||
MUTTER_PC_MODULES="$MUTTER_PC_MODULES xcursor"
|
||||
|
||||
AC_PATH_PROG([WAYLAND_SCANNER],[wayland-scanner],[no])
|
||||
AS_IF([test "x$WAYLAND_SCANNER" = "xno"],
|
||||
AC_MSG_ERROR([Could not find wayland-scanner in your PATH, required for parsing wayland extension protocols]))
|
||||
AC_SUBST([WAYLAND_SCANNER])
|
||||
AC_SUBST(XWAYLAND_PATH)
|
||||
|
||||
MUTTER_PC_MODULES="$MUTTER_PC_MODULES clutter-wayland-1.0 clutter-wayland-compositor-1.0 clutter-egl-1.0 wayland-server >= 1.4.93"
|
||||
PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES)
|
||||
|
||||
PKG_CHECK_MODULES(MUTTER_NATIVE_BACKEND, [libdrm libsystemd], [have_native_backend=yes], [have_native_backend=no])
|
||||
PKG_CHECK_MODULES(MUTTER_NATIVE_BACKEND, [libdrm libsystemd libinput], [have_native_backend=yes], [have_native_backend=no])
|
||||
if test $have_native_backend = yes; then
|
||||
AC_DEFINE([HAVE_NATIVE_BACKEND],[1],[Define if you want to enable the native (KMS) backend based on systemd])
|
||||
fi
|
||||
AM_CONDITIONAL([HAVE_NATIVE_BACKEND],[test $have_native_backend = yes])
|
||||
|
||||
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_DEFINE([HAVE_WAYLAND],[1],[Define if you want to enable Wayland support])
|
||||
fi
|
||||
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]))
|
||||
|
||||
@@ -244,16 +249,8 @@ if test x$have_xinerama = xno; then
|
||||
AC_MSG_ERROR([Xinerama extension was not found])
|
||||
fi
|
||||
|
||||
found_xkb=no
|
||||
AC_CHECK_LIB(X11, XkbQueryExtension,
|
||||
[AC_CHECK_HEADER(X11/XKBlib.h,
|
||||
found_xkb=yes)],
|
||||
, $ALL_X_LIBS)
|
||||
|
||||
if test "x$found_xkb" = "xyes"; then
|
||||
AC_DEFINE(HAVE_XKB, , [Have keyboard extension library])
|
||||
fi
|
||||
|
||||
AC_DEFINE_UNQUOTED([XKB_BASE], ["`$PKG_CONFIG --variable xkb_base xkeyboard-config`"],
|
||||
[XKB base dir])
|
||||
|
||||
RANDR_LIBS=
|
||||
found_randr=no
|
||||
@@ -299,17 +296,6 @@ fi
|
||||
|
||||
AM_CONDITIONAL(HAVE_SM, test "$found_sm" = "yes")
|
||||
|
||||
HOST_ALIAS=$host_alias
|
||||
AC_SUBST(HOST_ALIAS)
|
||||
|
||||
AC_PATH_PROG(GDK_PIXBUF_CSOURCE, gdk-pixbuf-csource, no)
|
||||
|
||||
if test x"$GDK_PIXBUF_CSOURCE" = xno; then
|
||||
AC_MSG_ERROR([gdk-pixbuf-csource executable not found in your path - should be installed with GTK])
|
||||
fi
|
||||
|
||||
AC_SUBST(GDK_PIXBUF_CSOURCE)
|
||||
|
||||
AC_PATH_PROG(ZENITY, zenity, no)
|
||||
if test x"$ZENITY" = xno; then
|
||||
AC_MSG_ERROR([zenity not found in your path - needed for dialogs])
|
||||
@@ -324,11 +310,6 @@ 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)
|
||||
|
||||
# Stay command-line compatible with the gnome-common configure option. Here
|
||||
@@ -397,6 +378,7 @@ changequote([,])dnl
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
data/Makefile
|
||||
doc/Makefile
|
||||
doc/man/Makefile
|
||||
doc/reference/Makefile
|
||||
@@ -404,6 +386,7 @@ doc/reference/meta-docs.sgml
|
||||
src/Makefile
|
||||
src/libmutter.pc
|
||||
src/compositor/plugins/Makefile
|
||||
src/meta/meta-version.h
|
||||
po/Makefile.in
|
||||
])
|
||||
|
||||
|
@@ -45,26 +45,68 @@
|
||||
_description="Move window one monitor down" />
|
||||
|
||||
<KeyListEntry name="switch-applications"
|
||||
reverse-entry="switch-applications-backward"
|
||||
_description="Switch applications"/>
|
||||
|
||||
<KeyListEntry name="switch-applications-backward"
|
||||
reverse-entry="switch-applications"
|
||||
hidden="true"
|
||||
_description="Switch to previous application"/>
|
||||
|
||||
<KeyListEntry name="switch-windows"
|
||||
reverse-entry="switch-windows-backward"
|
||||
_description="Switch windows"/>
|
||||
|
||||
<KeyListEntry name="switch-windows-backward"
|
||||
reverse-entry="switch-windows"
|
||||
hidden="true"
|
||||
_description="Switch to previous window"/>
|
||||
|
||||
<KeyListEntry name="switch-group"
|
||||
reverse-entry="switch-group-backward"
|
||||
_description="Switch windows of an application"/>
|
||||
|
||||
<KeyListEntry name="switch-group-backward"
|
||||
reverse-entry="switch-group"
|
||||
hidden="true"
|
||||
_description="Switch to previous window of an application"/>
|
||||
|
||||
<KeyListEntry name="switch-panels"
|
||||
reverse-entry="switch-panels-backward"
|
||||
_description="Switch system controls"/>
|
||||
|
||||
<KeyListEntry name="switch-panels-backward"
|
||||
reverse-entry="switch-panels"
|
||||
hidden="true"
|
||||
_description="Switch to previous system control"/>
|
||||
|
||||
<KeyListEntry name="cycle-windows"
|
||||
reverse-entry="cycle-windows-backward"
|
||||
_description="Switch windows directly"/>
|
||||
|
||||
<KeyListEntry name="cycle-windows-backward"
|
||||
reverse-entry="cycle-windows"
|
||||
hidden="true"
|
||||
_description="Switch directly to previous window"/>
|
||||
|
||||
<KeyListEntry name="cycle-group"
|
||||
reverse-entry="cycle-group-backward"
|
||||
_description="Switch windows of an app directly"/>
|
||||
|
||||
<KeyListEntry name="cycle-group-backward"
|
||||
reverse-entry="cycle-group"
|
||||
hidden="true"
|
||||
_description="Switch directly to previous window of an app"/>
|
||||
|
||||
<KeyListEntry name="cycle-panels"
|
||||
reverse-entry="cycle-panels-backward"
|
||||
_description="Switch system controls directly"/>
|
||||
|
||||
<KeyListEntry name="cycle-panels-backward"
|
||||
reverse-entry="cycle-panels"
|
||||
hidden="true"
|
||||
_description="Switch directly to previous system control"/>
|
||||
|
||||
<KeyListEntry name="show-desktop"
|
||||
_description="Hide all normal windows"/>
|
||||
|
@@ -1,3 +1,36 @@
|
||||
defaultcursordir = $(datadir)/mutter/cursors
|
||||
desktopfiles_in_files = \
|
||||
mutter.desktop.in \
|
||||
mutter-wayland.desktop.in
|
||||
desktopfilesdir = $(datadir)/applications
|
||||
desktopfiles_DATA = $(desktopfiles_in_files:.desktop.in=.desktop)
|
||||
|
||||
dist_defaultcursor_DATA = left_ptr.png
|
||||
@INTLTOOL_DESKTOP_RULE@
|
||||
|
||||
xml_in_files = \
|
||||
50-mutter-navigation.xml.in \
|
||||
50-mutter-system.xml.in \
|
||||
50-mutter-windows.xml.in
|
||||
xmldir = $(GNOME_KEYBINDINGS_KEYSDIR)
|
||||
xml_DATA = $(xml_in_files:.xml.in=.xml)
|
||||
|
||||
gschema_in_files = \
|
||||
org.gnome.mutter.gschema.xml.in \
|
||||
org.gnome.mutter.wayland.gschema.xml.in
|
||||
gsettings_SCHEMAS = $(gschema_in_files:.xml.in=.xml)
|
||||
|
||||
@INTLTOOL_XML_NOMERGE_RULE@
|
||||
@GSETTINGS_RULES@
|
||||
|
||||
convertdir = $(datadir)/GConf/gsettings
|
||||
convert_DATA = mutter-schemas.convert
|
||||
|
||||
CLEANFILES = \
|
||||
$(desktopfiles_DATA) \
|
||||
$(gsettings_SCHEMAS) \
|
||||
$(xml_DATA)
|
||||
|
||||
EXTRA_DIST = \
|
||||
$(convert_DATA) \
|
||||
$(desktopfiles_in_files) \
|
||||
$(gschema_in_files) \
|
||||
$(xml_in_files)
|
||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -300,6 +300,7 @@ 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
|
||||
@@ -555,7 +556,7 @@ meta_window_is_monitor_sized
|
||||
meta_window_is_override_redirect
|
||||
meta_window_is_skip_taskbar
|
||||
meta_window_get_rect
|
||||
meta_window_get_input_rect
|
||||
meta_window_get_buffer_rect
|
||||
meta_window_get_frame_rect
|
||||
meta_window_get_outer_rect
|
||||
meta_window_client_rect_to_frame_rect
|
||||
|
@@ -23,7 +23,8 @@ environment.</description>
|
||||
<download-page rdf:resource="http://download.gnome.org/sources/mutter/" />
|
||||
<bug-database rdf:resource="http://bugzilla.gnome.org/browse.cgi?product=mutter" />
|
||||
|
||||
<category rdf:resource="http://api.gnome.org/doap-extensions#desktop" />
|
||||
<category rdf:resource="http://api.gnome.org/doap-extensions#core" />
|
||||
<programming-language>C</programming-language>
|
||||
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
|
@@ -1,8 +1,11 @@
|
||||
# List of source files containing translatable strings.
|
||||
# Please keep this file sorted alphabetically.
|
||||
src/50-mutter-navigation.xml.in
|
||||
src/50-mutter-system.xml.in
|
||||
src/50-mutter-windows.xml.in
|
||||
data/50-mutter-navigation.xml.in
|
||||
data/50-mutter-system.xml.in
|
||||
data/50-mutter-windows.xml.in
|
||||
data/mutter.desktop.in
|
||||
data/org.gnome.mutter.gschema.xml.in
|
||||
data/org.gnome.mutter.wayland.gschema.xml.in
|
||||
src/backends/meta-monitor-manager.c
|
||||
src/compositor/compositor.c
|
||||
src/compositor/meta-background.c
|
||||
@@ -18,9 +21,6 @@ src/core/prefs.c
|
||||
src/core/screen.c
|
||||
src/core/util.c
|
||||
src/core/window.c
|
||||
src/mutter.desktop.in
|
||||
src/org.gnome.mutter.gschema.xml.in
|
||||
src/org.gnome.mutter.wayland.gschema.xml.in
|
||||
src/ui/frames.c
|
||||
src/ui/resizepopup.c
|
||||
src/ui/theme.c
|
||||
|
@@ -1,2 +1 @@
|
||||
src/metacity.schemas.in
|
||||
src/mutter-wayland.desktop.in
|
||||
data/mutter-wayland.desktop.in
|
||||
|
1308
po/pt_BR.po
1308
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
1267
po/zh_HK.po
1267
po/zh_HK.po
File diff suppressed because it is too large
Load Diff
1295
po/zh_TW.po
1295
po/zh_TW.po
File diff suppressed because it is too large
Load Diff
113
src/Makefile.am
113
src/Makefile.am
@@ -5,44 +5,46 @@ lib_LTLIBRARIES = libmutter.la
|
||||
|
||||
SUBDIRS=compositor/plugins
|
||||
|
||||
INCLUDES= \
|
||||
AM_CPPFLAGS = \
|
||||
-DCLUTTER_ENABLE_COMPOSITOR_API \
|
||||
-DCLUTTER_ENABLE_EXPERIMENTAL_API \
|
||||
-DCOGL_ENABLE_EXPERIMENTAL_API \
|
||||
-DCOGL_ENABLE_EXPERIMENTAL_2_0_API \
|
||||
-DCLUTTER_DISABLE_DEPRECATION_WARNINGS \
|
||||
-DCOGL_DISABLE_DEPRECATION_WARNINGS \
|
||||
$(MUTTER_CFLAGS) \
|
||||
$(MUTTER_NATIVE_BACKEND_CFLAGS) \
|
||||
-I$(builddir) \
|
||||
-I$(srcdir) \
|
||||
-I$(srcdir)/backends \
|
||||
-I$(srcdir)/core \
|
||||
-I$(srcdir)/ui \
|
||||
-I$(srcdir)/compositor \
|
||||
-DMUTTER_LIBEXECDIR=\"$(libexecdir)\" \
|
||||
-DHOST_ALIAS=\"@HOST_ALIAS@\" \
|
||||
-DMUTTER_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\" \
|
||||
-DMUTTER_LOCALEDIR=\"$(localedir)\" \
|
||||
-DMUTTER_PKGDATADIR=\"$(pkgdatadir)\" \
|
||||
-DMUTTER_DATADIR=\"$(datadir)\" \
|
||||
-DG_LOG_DOMAIN=\"mutter\" \
|
||||
-DSN_API_NOT_YET_FROZEN=1 \
|
||||
-DMUTTER_MAJOR_VERSION=$(MUTTER_MAJOR_VERSION) \
|
||||
-DMUTTER_MINOR_VERSION=$(MUTTER_MINOR_VERSION) \
|
||||
-DMUTTER_MICRO_VERSION=$(MUTTER_MICRO_VERSION) \
|
||||
-DMUTTER_PLUGIN_API_VERSION=$(MUTTER_PLUGIN_API_VERSION) \
|
||||
-DMUTTER_PKGLIBDIR=\"$(pkglibdir)\" \
|
||||
-DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\" \
|
||||
-DMUTTER_PLUGIN_DIR=\"$(MUTTER_PLUGIN_DIR)\" \
|
||||
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \
|
||||
-DXWAYLAND_PATH='"@XWAYLAND_PATH@"'
|
||||
-DXWAYLAND_PATH=\"$(XWAYLAND_PATH)\"
|
||||
|
||||
mutter_built_sources = \
|
||||
$(dbus_idle_built_sources) \
|
||||
$(dbus_display_config_built_sources) \
|
||||
$(dbus_login1_built_sources) \
|
||||
mutter-enum-types.h \
|
||||
mutter-enum-types.c \
|
||||
mutter-enum-types.c
|
||||
|
||||
if HAVE_WAYLAND
|
||||
mutter_built_sources += \
|
||||
gtk-shell-protocol.c \
|
||||
gtk-shell-server-protocol.h \
|
||||
xdg-shell-protocol.c \
|
||||
xdg-shell-server-protocol.h
|
||||
endif
|
||||
|
||||
wayland_protocols = \
|
||||
wayland/protocol/gtk-shell.xml \
|
||||
@@ -50,7 +52,7 @@ wayland_protocols = \
|
||||
|
||||
libmutter_la_SOURCES = \
|
||||
backends/meta-backend.c \
|
||||
backends/meta-backend.h \
|
||||
meta/meta-backend.h \
|
||||
backends/meta-backend-private.h \
|
||||
backends/meta-cursor.c \
|
||||
backends/meta-cursor.h \
|
||||
@@ -70,6 +72,8 @@ libmutter_la_SOURCES = \
|
||||
backends/meta-monitor-manager.h \
|
||||
backends/meta-monitor-manager-dummy.c \
|
||||
backends/meta-monitor-manager-dummy.h \
|
||||
backends/meta-stage.h \
|
||||
backends/meta-stage.c \
|
||||
backends/edid-parse.c \
|
||||
backends/edid.h \
|
||||
backends/x11/meta-backend-x11.c \
|
||||
@@ -114,12 +118,6 @@ libmutter_la_SOURCES = \
|
||||
compositor/meta-surface-actor.h \
|
||||
compositor/meta-surface-actor-x11.c \
|
||||
compositor/meta-surface-actor-x11.h \
|
||||
compositor/meta-surface-actor-wayland.c \
|
||||
compositor/meta-surface-actor-wayland.h \
|
||||
compositor/meta-stage.h \
|
||||
compositor/meta-stage.c \
|
||||
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 \
|
||||
@@ -157,6 +155,8 @@ libmutter_la_SOURCES = \
|
||||
core/frame.h \
|
||||
ui/gradient.c \
|
||||
meta/gradient.h \
|
||||
core/meta-gesture-tracker.c \
|
||||
core/meta-gesture-tracker-private.h \
|
||||
core/keybindings.c \
|
||||
core/keybindings-private.h \
|
||||
core/main.c \
|
||||
@@ -168,6 +168,7 @@ libmutter_la_SOURCES = \
|
||||
core/screen-private.h \
|
||||
meta/screen.h \
|
||||
meta/types.h \
|
||||
core/restart.c \
|
||||
core/stack.c \
|
||||
core/stack.h \
|
||||
core/stack-tracker.c \
|
||||
@@ -196,6 +197,8 @@ libmutter_la_SOURCES = \
|
||||
x11/iconcache.h \
|
||||
x11/async-getprop.c \
|
||||
x11/async-getprop.h \
|
||||
x11/events.c \
|
||||
x11/events.h \
|
||||
x11/group-private.h \
|
||||
x11/group-props.c \
|
||||
x11/group-props.h \
|
||||
@@ -210,7 +213,12 @@ libmutter_la_SOURCES = \
|
||||
x11/window-x11-private.h \
|
||||
x11/xprops.c \
|
||||
x11/xprops.h \
|
||||
x11/mutter-Xatomtype.h \
|
||||
x11/mutter-Xatomtype.h
|
||||
|
||||
if HAVE_WAYLAND
|
||||
libmutter_la_SOURCES += \
|
||||
compositor/meta-surface-actor-wayland.c \
|
||||
compositor/meta-surface-actor-wayland.h \
|
||||
wayland/meta-wayland.c \
|
||||
wayland/meta-wayland.h \
|
||||
wayland/meta-wayland-private.h \
|
||||
@@ -225,6 +233,8 @@ libmutter_la_SOURCES = \
|
||||
wayland/meta-wayland-pointer.h \
|
||||
wayland/meta-wayland-seat.c \
|
||||
wayland/meta-wayland-seat.h \
|
||||
wayland/meta-wayland-touch.c \
|
||||
wayland/meta-wayland-touch.h \
|
||||
wayland/meta-wayland-surface.c \
|
||||
wayland/meta-wayland-surface.h \
|
||||
wayland/meta-wayland-types.h \
|
||||
@@ -233,6 +243,7 @@ libmutter_la_SOURCES = \
|
||||
wayland/meta-wayland-outputs.h \
|
||||
wayland/window-wayland.c \
|
||||
wayland/window-wayland.h
|
||||
endif
|
||||
|
||||
if HAVE_NATIVE_BACKEND
|
||||
libmutter_la_SOURCES += \
|
||||
@@ -258,7 +269,7 @@ libmutter_la_LIBADD = $(MUTTER_LIBS) $(MUTTER_NATIVE_BACKEND_LIBS)
|
||||
|
||||
# Headers installed for plugins; introspected information will
|
||||
# be extracted into Mutter-<version>.gir
|
||||
libmutterinclude_base_headers = \
|
||||
libmutterinclude_headers = \
|
||||
meta/barrier.h \
|
||||
meta/boxes.h \
|
||||
meta/common.h \
|
||||
@@ -270,6 +281,7 @@ libmutterinclude_base_headers = \
|
||||
meta/group.h \
|
||||
meta/keybindings.h \
|
||||
meta/main.h \
|
||||
meta/meta-backend.h \
|
||||
meta/meta-background-actor.h \
|
||||
meta/meta-background-group.h \
|
||||
meta/meta-background.h \
|
||||
@@ -287,6 +299,13 @@ libmutterinclude_base_headers = \
|
||||
meta/window.h \
|
||||
meta/workspace.h
|
||||
|
||||
libmutterinclude_built_headers = \
|
||||
meta/meta-version.h
|
||||
|
||||
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 = \
|
||||
@@ -295,14 +314,21 @@ libmutterinclude_extra_headers = \
|
||||
libmutterincludedir = $(includedir)/mutter/meta
|
||||
|
||||
libmutterinclude_HEADERS = \
|
||||
$(libmutterinclude_base_headers) \
|
||||
$(libmutterinclude_headers) \
|
||||
$(libmutterinclude_extra_headers)
|
||||
|
||||
nodist_libmutterinclude_HEADERS = \
|
||||
$(libmutterinclude_built_headers)
|
||||
|
||||
bin_PROGRAMS=mutter
|
||||
|
||||
mutter_SOURCES = core/mutter.c
|
||||
mutter_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
|
||||
libexec_PROGRAMS = mutter-restart-helper
|
||||
mutter_restart_helper_SOURCES = core/restart-helper.c
|
||||
mutter_restart_helper_LDADD = $(MUTTER_LIBS)
|
||||
|
||||
if HAVE_INTROSPECTION
|
||||
include $(INTROSPECTION_MAKEFILE)
|
||||
|
||||
@@ -326,7 +352,7 @@ INTROSPECTION_GIRS = Meta-$(api_version).gir
|
||||
Meta-$(api_version).gir: libmutter.la
|
||||
@META_GIR@_INCLUDES = GObject-2.0 GDesktopEnums-3.0 Gdk-3.0 Gtk-3.0 Clutter-1.0 xlib-2.0 xfixes-4.0 Cogl-1.0
|
||||
@META_GIR@_EXPORT_PACKAGES = libmutter
|
||||
@META_GIR@_CFLAGS = $(INCLUDES)
|
||||
@META_GIR@_CFLAGS = $(AM_CPPFLAGS)
|
||||
@META_GIR@_LIBS = libmutter.la
|
||||
@META_GIR@_FILES = \
|
||||
mutter-enum-types.h \
|
||||
@@ -346,53 +372,21 @@ testboxes_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
testgradient_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
|
||||
@INTLTOOL_DESKTOP_RULE@
|
||||
|
||||
desktopfilesdir=$(datadir)/applications
|
||||
desktopfiles_in_files=mutter.desktop.in
|
||||
desktopfiles_files=$(desktopfiles_in_files:.desktop.in=.desktop)
|
||||
desktopfiles_DATA = $(desktopfiles_files)
|
||||
|
||||
xmldir = @GNOME_KEYBINDINGS_KEYSDIR@
|
||||
xml_in_files = \
|
||||
50-mutter-navigation.xml.in \
|
||||
50-mutter-system.xml.in \
|
||||
50-mutter-windows.xml.in
|
||||
xml_DATA = $(xml_in_files:.xml.in=.xml)
|
||||
|
||||
dbus_idle_built_sources = meta-dbus-idle-monitor.c meta-dbus-idle-monitor.h
|
||||
|
||||
gsettings_SCHEMAS = org.gnome.mutter.gschema.xml org.gnome.mutter.wayland.gschema.xml
|
||||
@INTLTOOL_XML_NOMERGE_RULE@
|
||||
@GSETTINGS_RULES@
|
||||
|
||||
convertdir = $(datadir)/GConf/gsettings
|
||||
convert_DATA = mutter-schemas.convert
|
||||
|
||||
CLEANFILES = \
|
||||
mutter.desktop \
|
||||
mutter-wm.desktop \
|
||||
org.gnome.mutter.gschema.xml \
|
||||
org.gnome.mutter.wayland.gschema.xml \
|
||||
$(xml_DATA) \
|
||||
$(mutter_built_sources) \
|
||||
$(typelib_DATA) \
|
||||
$(gir_DATA)
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
DISTCLEANFILES = \
|
||||
$(libmutterinclude_built_headers)
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = libmutter.pc
|
||||
|
||||
EXTRA_DIST=$(desktopfiles_files) \
|
||||
$(wmproperties_files) \
|
||||
$(IMAGES) \
|
||||
$(desktopfiles_in_files) \
|
||||
$(wmproperties_in_files) \
|
||||
$(xml_in_files) \
|
||||
EXTRA_DIST = \
|
||||
$(wayland_protocols) \
|
||||
org.gnome.mutter.gschema.xml.in \
|
||||
org.gnome.mutter.wayland.gschema.xml.in \
|
||||
mutter-schemas.convert \
|
||||
libmutter.pc.in \
|
||||
mutter-enum-types.h.in \
|
||||
mutter-enum-types.c.in \
|
||||
@@ -400,7 +394,10 @@ EXTRA_DIST=$(desktopfiles_files) \
|
||||
org.gnome.Mutter.DisplayConfig.xml \
|
||||
org.gnome.Mutter.IdleMonitor.xml
|
||||
|
||||
BUILT_SOURCES = $(mutter_built_sources)
|
||||
BUILT_SOURCES = \
|
||||
$(mutter_built_sources) \
|
||||
$(libmutterinclude_built_headers)
|
||||
|
||||
MUTTER_STAMP_FILES = stamp-mutter-enum-types.h
|
||||
CLEANFILES += $(MUTTER_STAMP_FILES)
|
||||
|
||||
|
@@ -28,7 +28,15 @@
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "meta-backend.h"
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
#include <meta/meta-backend.h>
|
||||
#include <meta/meta-idle-monitor.h>
|
||||
#include "meta-cursor-renderer.h"
|
||||
#include "meta-monitor-manager.h"
|
||||
|
||||
#define DEFAULT_XKB_RULES_FILE "evdev"
|
||||
#define DEFAULT_XKB_MODEL "pc105+inet"
|
||||
|
||||
#define META_TYPE_BACKEND (meta_backend_get_type ())
|
||||
#define META_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BACKEND, MetaBackend))
|
||||
@@ -66,6 +74,37 @@ struct _MetaBackendClass
|
||||
void (* warp_pointer) (MetaBackend *backend,
|
||||
int x,
|
||||
int y);
|
||||
|
||||
void (* set_keymap) (MetaBackend *backend,
|
||||
const char *layouts,
|
||||
const char *variants,
|
||||
const char *options);
|
||||
|
||||
struct xkb_keymap * (* get_keymap) (MetaBackend *backend);
|
||||
|
||||
void (* lock_layout_group) (MetaBackend *backend,
|
||||
guint idx);
|
||||
|
||||
void (* update_screen_size) (MetaBackend *backend, int width, int height);
|
||||
void (* select_stage_events) (MetaBackend *backend);
|
||||
};
|
||||
|
||||
MetaIdleMonitor * meta_backend_get_idle_monitor (MetaBackend *backend,
|
||||
int device_id);
|
||||
MetaMonitorManager * meta_backend_get_monitor_manager (MetaBackend *backend);
|
||||
MetaCursorRenderer * meta_backend_get_cursor_renderer (MetaBackend *backend);
|
||||
|
||||
gboolean meta_backend_grab_device (MetaBackend *backend,
|
||||
int device_id,
|
||||
uint32_t timestamp);
|
||||
gboolean meta_backend_ungrab_device (MetaBackend *backend,
|
||||
int device_id,
|
||||
uint32_t timestamp);
|
||||
|
||||
void meta_backend_warp_pointer (MetaBackend *backend,
|
||||
int x,
|
||||
int y);
|
||||
|
||||
struct xkb_keymap * meta_backend_get_keymap (MetaBackend *backend);
|
||||
|
||||
#endif /* META_BACKEND_PRIVATE_H */
|
||||
|
@@ -24,12 +24,11 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "meta-backend.h"
|
||||
#include <meta/meta-backend.h>
|
||||
#include "meta-backend-private.h"
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include "backends/x11/meta-backend-x11.h"
|
||||
#include "meta-stage.h"
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
#include "backends/native/meta-backend-native.h"
|
||||
@@ -37,6 +36,13 @@
|
||||
|
||||
static MetaBackend *_backend;
|
||||
|
||||
/**
|
||||
* meta_get_backend:
|
||||
*
|
||||
* Accessor for the singleton MetaBackend.
|
||||
*
|
||||
* Returns: (transfer none): The only #MetaBackend there is.
|
||||
*/
|
||||
MetaBackend *
|
||||
meta_get_backend (void)
|
||||
{
|
||||
@@ -47,6 +53,8 @@ struct _MetaBackendPrivate
|
||||
{
|
||||
MetaMonitorManager *monitor_manager;
|
||||
MetaCursorRenderer *cursor_renderer;
|
||||
|
||||
ClutterActor *stage;
|
||||
};
|
||||
typedef struct _MetaBackendPrivate MetaBackendPrivate;
|
||||
|
||||
@@ -70,12 +78,40 @@ meta_backend_finalize (GObject *object)
|
||||
G_OBJECT_CLASS (meta_backend_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_sync_screen_size (MetaBackend *backend)
|
||||
{
|
||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||
int width, height;
|
||||
|
||||
meta_monitor_manager_get_screen_size (priv->monitor_manager, &width, &height);
|
||||
|
||||
META_BACKEND_GET_CLASS (backend)->update_screen_size (backend, width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
on_monitors_changed (MetaMonitorManager *monitors,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaBackend *backend = META_BACKEND (user_data);
|
||||
meta_backend_sync_screen_size (backend);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_real_post_init (MetaBackend *backend)
|
||||
{
|
||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||
|
||||
priv->stage = meta_stage_new ();
|
||||
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);
|
||||
|
||||
g_signal_connect (priv->monitor_manager, "monitors-changed",
|
||||
G_CALLBACK (on_monitors_changed), backend);
|
||||
meta_backend_sync_screen_size (backend);
|
||||
|
||||
priv->cursor_renderer = META_BACKEND_GET_CLASS (backend)->create_cursor_renderer (backend);
|
||||
}
|
||||
|
||||
@@ -104,9 +140,16 @@ meta_backend_real_ungrab_device (MetaBackend *backend,
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_real_warp_pointer (MetaBackend *backend,
|
||||
int x,
|
||||
int y)
|
||||
meta_backend_real_update_screen_size (MetaBackend *backend,
|
||||
int width, int height)
|
||||
{
|
||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||
|
||||
clutter_actor_set_size (priv->stage, width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_real_select_stage_events (MetaBackend *backend)
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
@@ -122,7 +165,15 @@ meta_backend_class_init (MetaBackendClass *klass)
|
||||
klass->create_cursor_renderer = meta_backend_real_create_cursor_renderer;
|
||||
klass->grab_device = meta_backend_real_grab_device;
|
||||
klass->ungrab_device = meta_backend_real_ungrab_device;
|
||||
klass->warp_pointer = meta_backend_real_warp_pointer;
|
||||
klass->update_screen_size = meta_backend_real_update_screen_size;
|
||||
klass->select_stage_events = meta_backend_real_select_stage_events;
|
||||
|
||||
g_signal_new ("keymap-changed",
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -154,6 +205,9 @@ meta_backend_post_init (MetaBackend *backend)
|
||||
META_BACKEND_GET_CLASS (backend)->post_init (backend);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_backend_get_idle_monitor: (skip)
|
||||
*/
|
||||
MetaIdleMonitor *
|
||||
meta_backend_get_idle_monitor (MetaBackend *backend,
|
||||
int device_id)
|
||||
@@ -169,6 +223,9 @@ meta_backend_get_idle_monitor (MetaBackend *backend,
|
||||
return backend->device_monitors[device_id];
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_backend_get_monitor_manager: (skip)
|
||||
*/
|
||||
MetaMonitorManager *
|
||||
meta_backend_get_monitor_manager (MetaBackend *backend)
|
||||
{
|
||||
@@ -177,6 +234,9 @@ meta_backend_get_monitor_manager (MetaBackend *backend)
|
||||
return priv->monitor_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_backend_get_cursor_renderer: (skip)
|
||||
*/
|
||||
MetaCursorRenderer *
|
||||
meta_backend_get_cursor_renderer (MetaBackend *backend)
|
||||
{
|
||||
@@ -185,6 +245,9 @@ meta_backend_get_cursor_renderer (MetaBackend *backend)
|
||||
return priv->cursor_renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_backend_grab_device: (skip)
|
||||
*/
|
||||
gboolean
|
||||
meta_backend_grab_device (MetaBackend *backend,
|
||||
int device_id,
|
||||
@@ -193,6 +256,9 @@ meta_backend_grab_device (MetaBackend *backend,
|
||||
return META_BACKEND_GET_CLASS (backend)->grab_device (backend, device_id, timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_backend_ungrab_device: (skip)
|
||||
*/
|
||||
gboolean
|
||||
meta_backend_ungrab_device (MetaBackend *backend,
|
||||
int device_id,
|
||||
@@ -201,6 +267,9 @@ meta_backend_ungrab_device (MetaBackend *backend,
|
||||
return META_BACKEND_GET_CLASS (backend)->ungrab_device (backend, device_id, timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_backend_warp_pointer: (skip)
|
||||
*/
|
||||
void
|
||||
meta_backend_warp_pointer (MetaBackend *backend,
|
||||
int x,
|
||||
@@ -209,6 +278,47 @@ meta_backend_warp_pointer (MetaBackend *backend,
|
||||
META_BACKEND_GET_CLASS (backend)->warp_pointer (backend, x, y);
|
||||
}
|
||||
|
||||
void
|
||||
meta_backend_set_keymap (MetaBackend *backend,
|
||||
const char *layouts,
|
||||
const char *variants,
|
||||
const char *options)
|
||||
{
|
||||
META_BACKEND_GET_CLASS (backend)->set_keymap (backend, layouts, variants, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_backend_get_keymap: (skip)
|
||||
*/
|
||||
struct xkb_keymap *
|
||||
meta_backend_get_keymap (MetaBackend *backend)
|
||||
|
||||
{
|
||||
return META_BACKEND_GET_CLASS (backend)->get_keymap (backend);
|
||||
}
|
||||
|
||||
void
|
||||
meta_backend_lock_layout_group (MetaBackend *backend,
|
||||
guint idx)
|
||||
{
|
||||
META_BACKEND_GET_CLASS (backend)->lock_layout_group (backend, idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_backend_get_stage:
|
||||
* @backend: A #MetaBackend
|
||||
*
|
||||
* Gets the global #ClutterStage that's managed by this backend.
|
||||
*
|
||||
* Returns: (transfer none): the #ClutterStage
|
||||
*/
|
||||
ClutterActor *
|
||||
meta_backend_get_stage (MetaBackend *backend)
|
||||
{
|
||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||
return priv->stage;
|
||||
}
|
||||
|
||||
static GType
|
||||
get_backend_type (void)
|
||||
{
|
||||
@@ -281,6 +391,9 @@ static GSourceFuncs event_funcs = {
|
||||
event_dispatch
|
||||
};
|
||||
|
||||
/**
|
||||
* meta_clutter_init: (skip)
|
||||
*/
|
||||
void
|
||||
meta_clutter_init (void)
|
||||
{
|
||||
|
@@ -30,7 +30,7 @@
|
||||
typedef struct {
|
||||
CoglTexture2D *texture;
|
||||
struct gbm_bo *bo;
|
||||
int hot_x, hot_y;
|
||||
int offset_x, offset_y;
|
||||
} MetaCursorImage;
|
||||
|
||||
struct _MetaCursorReference {
|
||||
@@ -41,11 +41,11 @@ struct _MetaCursorReference {
|
||||
};
|
||||
|
||||
CoglTexture *meta_cursor_reference_get_cogl_texture (MetaCursorReference *cursor,
|
||||
int *hot_x,
|
||||
int *hot_y);
|
||||
int *offset_x,
|
||||
int *offset_y);
|
||||
|
||||
struct gbm_bo *meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
|
||||
int *hot_x,
|
||||
int *hot_y);
|
||||
int *offset_x,
|
||||
int *offset_y);
|
||||
|
||||
#endif /* META_CURSOR_PRIVATE_H */
|
||||
|
@@ -27,21 +27,29 @@
|
||||
#include "meta-cursor-renderer.h"
|
||||
#include "meta-cursor-private.h"
|
||||
|
||||
#include <meta/meta-backend.h>
|
||||
#include <meta/util.h>
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
#include <cogl/cogl-wayland-server.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include "meta-stage.h"
|
||||
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
typedef struct
|
||||
{
|
||||
CoglTexture *texture;
|
||||
MetaRectangle current_rect;
|
||||
gboolean handled_by_backend;
|
||||
} MetaCursorLayer;
|
||||
|
||||
struct _MetaCursorRendererPrivate
|
||||
{
|
||||
int current_x, current_y;
|
||||
MetaRectangle current_rect;
|
||||
|
||||
MetaCursorLayer core_layer;
|
||||
MetaCursorLayer dnd_layer;
|
||||
|
||||
MetaCursorReference *displayed_cursor;
|
||||
gboolean handled_by_backend;
|
||||
};
|
||||
typedef struct _MetaCursorRendererPrivate MetaCursorRendererPrivate;
|
||||
|
||||
@@ -51,17 +59,16 @@ static void
|
||||
queue_redraw (MetaCursorRenderer *renderer)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||
ClutterActor *stage = compositor->stage;
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
ClutterActor *stage = meta_backend_get_stage (backend);
|
||||
|
||||
/* During early initialization, we can have no stage */
|
||||
if (!stage)
|
||||
return;
|
||||
|
||||
if (priv->handled_by_backend)
|
||||
meta_stage_set_cursor (META_STAGE (stage), NULL, &priv->current_rect);
|
||||
else
|
||||
meta_stage_set_cursor (META_STAGE (stage), priv->displayed_cursor, &priv->current_rect);
|
||||
if (priv->core_layer.texture && !priv->core_layer.handled_by_backend)
|
||||
meta_stage_set_cursor (META_STAGE (stage), layer->texture, &priv->current_rect);
|
||||
meta_stage_set_dnd_surface (META_STAGE (stage),
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -81,33 +88,68 @@ meta_cursor_renderer_init (MetaCursorRenderer *renderer)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
update_layer (MetaCursorRenderer *renderer,
|
||||
MetaCursorLayer *layer,
|
||||
CoglTexture *texture,
|
||||
int offset_x,
|
||||
int offset_y)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||
|
||||
layer->texture = texture;
|
||||
|
||||
if (layer->texture)
|
||||
{
|
||||
layer->current_rect.x = priv->current_x + offset_x;
|
||||
layer->current_rect.y = priv->current_y + offset_y;
|
||||
layer->current_rect.width = cogl_texture_get_width (layer->texture);
|
||||
layer->current_rect.height = cogl_texture_get_height (layer->texture);
|
||||
}
|
||||
else
|
||||
{
|
||||
layer->current_rect.x = 0;
|
||||
layer->current_rect.y = 0;
|
||||
layer->current_rect.width = 0;
|
||||
layer->current_rect.height = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_cursor (MetaCursorRenderer *renderer)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||
gboolean handled_by_backend;
|
||||
gboolean should_redraw = FALSE;
|
||||
CoglTexture *texture;
|
||||
int hot_x, hot_y;
|
||||
|
||||
if (priv->displayed_cursor)
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
CoglTexture *texture;
|
||||
int hot_x, hot_y;
|
||||
int offset_x, offset_y;
|
||||
|
||||
texture = meta_cursor_reference_get_cogl_texture (priv->displayed_cursor, &hot_x, &hot_y);
|
||||
texture = meta_cursor_reference_get_cogl_texture (priv->displayed_cursor, &offset_x, &offset_y);
|
||||
|
||||
priv->current_rect.x = priv->current_x - hot_x;
|
||||
priv->current_rect.y = priv->current_y - hot_y;
|
||||
priv->current_rect.x = priv->current_x + offset_x;
|
||||
priv->current_rect.y = priv->current_y + offset_y;
|
||||
priv->current_rect.width = cogl_texture_get_width (COGL_TEXTURE (texture));
|
||||
priv->current_rect.height = cogl_texture_get_height (COGL_TEXTURE (texture));
|
||||
=======
|
||||
texture = meta_cursor_reference_get_cogl_texture (priv->displayed_cursor, &hot_x, &hot_y);
|
||||
>>>>>>> 75e7834... dnd 2
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->current_rect.x = 0;
|
||||
priv->current_rect.y = 0;
|
||||
priv->current_rect.width = 0;
|
||||
priv->current_rect.height = 0;
|
||||
texture = NULL;
|
||||
hot_x = 0;
|
||||
hot_y = 0;
|
||||
}
|
||||
|
||||
update_layer (renderer, &priv->core_layer, texture, hot_x, hot_y);
|
||||
update_layer (renderer, &priv->
|
||||
|
||||
handled_by_backend = META_CURSOR_RENDERER_GET_CLASS (renderer)->update_cursor (renderer);
|
||||
if (handled_by_backend != priv->handled_by_backend)
|
||||
{
|
||||
@@ -141,6 +183,17 @@ meta_cursor_renderer_set_cursor (MetaCursorRenderer *renderer,
|
||||
update_cursor (renderer);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_renderer_set_dnd_surface (MetaCursorRenderer *renderer,
|
||||
CoglTexture *texture,
|
||||
int offset_x,
|
||||
int offset_y)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||
|
||||
update_layer (renderer, &priv->dnd_layer,
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_renderer_set_position (MetaCursorRenderer *renderer,
|
||||
int x, int y)
|
||||
@@ -168,5 +221,5 @@ meta_cursor_renderer_get_rect (MetaCursorRenderer *renderer)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||
|
||||
return &priv->current_rect;
|
||||
return &priv->core_layer.current_rect;
|
||||
}
|
||||
|
@@ -23,8 +23,6 @@
|
||||
#define META_CURSOR_TRACKER_PRIVATE_H
|
||||
|
||||
#include <meta/meta-cursor-tracker.h>
|
||||
#include <wayland-server.h>
|
||||
#include <gbm.h>
|
||||
|
||||
#include "meta-cursor.h"
|
||||
#include "meta-cursor-renderer.h"
|
||||
@@ -32,7 +30,6 @@
|
||||
struct _MetaCursorTracker {
|
||||
GObject parent_instance;
|
||||
|
||||
MetaScreen *screen;
|
||||
MetaCursorRenderer *renderer;
|
||||
|
||||
gboolean is_showing;
|
||||
|
@@ -34,25 +34,21 @@
|
||||
#include <meta/errors.h>
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
#include <cogl/cogl-wayland-server.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
|
||||
#include "meta-backend.h"
|
||||
#include "meta-backend-private.h"
|
||||
|
||||
#include "meta-cursor-private.h"
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
#include "screen-private.h"
|
||||
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
|
||||
G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT);
|
||||
|
||||
enum {
|
||||
CURSOR_CHANGED,
|
||||
LAST_SIGNAL
|
||||
CURSOR_CHANGED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL];
|
||||
@@ -60,10 +56,12 @@ static guint signals[LAST_SIGNAL];
|
||||
static MetaCursorReference *
|
||||
get_displayed_cursor (MetaCursorTracker *tracker)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
|
||||
if (!tracker->is_showing)
|
||||
return NULL;
|
||||
|
||||
if (tracker->screen->display->grab_op == META_GRAB_OP_NONE)
|
||||
if (meta_display_windows_are_interactable (display))
|
||||
{
|
||||
if (tracker->has_window_cursor)
|
||||
return tracker->window_cursor;
|
||||
@@ -97,6 +95,9 @@ sync_cursor (MetaCursorTracker *tracker)
|
||||
static void
|
||||
meta_cursor_tracker_init (MetaCursorTracker *self)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
|
||||
self->renderer = meta_backend_get_cursor_renderer (backend);
|
||||
self->is_showing = TRUE;
|
||||
}
|
||||
|
||||
@@ -129,47 +130,9 @@ meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass)
|
||||
}
|
||||
|
||||
static MetaCursorTracker *
|
||||
make_wayland_cursor_tracker (MetaScreen *screen)
|
||||
meta_cursor_tracker_new (void)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaWaylandCompositor *compositor;
|
||||
MetaCursorTracker *self;
|
||||
|
||||
self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
|
||||
self->screen = screen;
|
||||
self->renderer = meta_backend_get_cursor_renderer (backend);
|
||||
|
||||
compositor = meta_wayland_compositor_get_default ();
|
||||
compositor->seat->pointer.cursor_tracker = self;
|
||||
meta_cursor_tracker_update_position (self, 0, 0);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static MetaCursorTracker *
|
||||
make_x11_cursor_tracker (MetaScreen *screen)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaCursorTracker *self;
|
||||
|
||||
self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
|
||||
self->screen = screen;
|
||||
self->renderer = meta_backend_get_cursor_renderer (backend);
|
||||
|
||||
XFixesSelectCursorInput (screen->display->xdisplay,
|
||||
screen->xroot,
|
||||
XFixesDisplayCursorNotifyMask);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static MetaCursorTracker *
|
||||
meta_cursor_tracker_new (MetaScreen *screen)
|
||||
{
|
||||
if (meta_is_wayland_compositor ())
|
||||
return make_wayland_cursor_tracker (screen);
|
||||
else
|
||||
return make_x11_cursor_tracker (screen);
|
||||
return g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
|
||||
}
|
||||
|
||||
static MetaCursorTracker *_cursor_tracker;
|
||||
@@ -186,7 +149,7 @@ MetaCursorTracker *
|
||||
meta_cursor_tracker_get_for_screen (MetaScreen *screen)
|
||||
{
|
||||
if (!_cursor_tracker)
|
||||
_cursor_tracker = meta_cursor_tracker_new (screen);
|
||||
_cursor_tracker = meta_cursor_tracker_new ();
|
||||
|
||||
return _cursor_tracker;
|
||||
}
|
||||
@@ -207,12 +170,13 @@ gboolean
|
||||
meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
|
||||
XEvent *xevent)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
XFixesCursorNotifyEvent *notify_event;
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
return FALSE;
|
||||
|
||||
if (xevent->xany.type != tracker->screen->display->xfixes_event_base + XFixesCursorNotify)
|
||||
if (xevent->xany.type != display->xfixes_event_base + XFixesCursorNotify)
|
||||
return FALSE;
|
||||
|
||||
notify_event = (XFixesCursorNotifyEvent *)xevent;
|
||||
@@ -243,6 +207,7 @@ meta_cursor_reference_take_texture (CoglTexture2D *texture,
|
||||
static void
|
||||
ensure_xfixes_cursor (MetaCursorTracker *tracker)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
XFixesCursorImage *cursor_image;
|
||||
CoglTexture2D *sprite;
|
||||
guint8 *cursor_data;
|
||||
@@ -252,7 +217,7 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
|
||||
if (tracker->xfixes_cursor)
|
||||
return;
|
||||
|
||||
cursor_image = XFixesGetCursorImage (tracker->screen->display->xdisplay);
|
||||
cursor_image = XFixesGetCursorImage (display->xdisplay);
|
||||
if (!cursor_image)
|
||||
return;
|
||||
|
||||
@@ -345,6 +310,7 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
|
||||
int *y)
|
||||
{
|
||||
MetaCursorReference *cursor;
|
||||
int offset_x, offset_y;
|
||||
|
||||
g_return_if_fail (META_IS_CURSOR_TRACKER (tracker));
|
||||
|
||||
@@ -359,14 +325,19 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
|
||||
}
|
||||
|
||||
if (cursor)
|
||||
meta_cursor_reference_get_cogl_texture (cursor, x, y);
|
||||
{
|
||||
meta_cursor_reference_get_cogl_texture (cursor, &offset_x, &offset_y);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (x)
|
||||
*x = 0;
|
||||
if (y)
|
||||
*y = 0;
|
||||
offset_x = 0;
|
||||
offset_y = 0;
|
||||
}
|
||||
|
||||
if (x)
|
||||
*x = -offset_x;
|
||||
if (y)
|
||||
*y = -offset_y;
|
||||
}
|
||||
|
||||
void
|
||||
|
@@ -27,7 +27,7 @@
|
||||
|
||||
#include "display-private.h"
|
||||
#include "screen-private.h"
|
||||
#include "meta-backend.h"
|
||||
#include "meta-backend-private.h"
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
#include "backends/native/meta-cursor-renderer-native.h"
|
||||
@@ -39,7 +39,9 @@
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
#include <X11/Xcursor/Xcursor.h>
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
#include <cogl/cogl-wayland-server.h>
|
||||
#endif
|
||||
|
||||
MetaCursorReference *
|
||||
meta_cursor_reference_ref (MetaCursorReference *self)
|
||||
@@ -247,6 +249,7 @@ meta_cursor_reference_from_theme (MetaCursor cursor)
|
||||
return self;
|
||||
}
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
static void
|
||||
meta_cursor_image_load_from_buffer (MetaCursorImage *image,
|
||||
struct wl_resource *buffer,
|
||||
@@ -345,28 +348,29 @@ meta_cursor_reference_from_buffer (struct wl_resource *buffer,
|
||||
|
||||
return self;
|
||||
}
|
||||
#endif
|
||||
|
||||
CoglTexture *
|
||||
meta_cursor_reference_get_cogl_texture (MetaCursorReference *cursor,
|
||||
int *hot_x,
|
||||
int *hot_y)
|
||||
int *offset_x,
|
||||
int *offset_y)
|
||||
{
|
||||
if (hot_x)
|
||||
*hot_x = cursor->image.hot_x;
|
||||
if (hot_y)
|
||||
*hot_y = cursor->image.hot_y;
|
||||
if (offset_x)
|
||||
*offset_x = cursor->image.offset_x;
|
||||
if (offset_y)
|
||||
*offset_y = cursor->image.offset_y;
|
||||
return COGL_TEXTURE (cursor->image.texture);
|
||||
}
|
||||
|
||||
struct gbm_bo *
|
||||
meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
|
||||
int *hot_x,
|
||||
int *hot_y)
|
||||
int *offset_x,
|
||||
int *offset_y)
|
||||
{
|
||||
if (hot_x)
|
||||
*hot_x = cursor->image.hot_x;
|
||||
if (hot_y)
|
||||
*hot_y = cursor->image.hot_y;
|
||||
if (offset_x)
|
||||
*offset_x = cursor->image.offset_x;
|
||||
if (offset_y)
|
||||
*offset_y = cursor->image.offset_y;
|
||||
return cursor->image.bo;
|
||||
}
|
||||
|
||||
|
@@ -28,13 +28,14 @@ MetaCursorReference * meta_cursor_reference_ref (MetaCursorReference *cursor);
|
||||
void meta_cursor_reference_unref (MetaCursorReference *cursor);
|
||||
|
||||
#include <meta/common.h>
|
||||
#include <wayland-server.h>
|
||||
|
||||
MetaCursorReference * meta_cursor_reference_from_theme (MetaCursor cursor);
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
#include <wayland-server.h>
|
||||
MetaCursorReference * meta_cursor_reference_from_buffer (struct wl_resource *buffer,
|
||||
int hot_x,
|
||||
int hot_y);
|
||||
int offset_x, int offset_y);
|
||||
#endif
|
||||
|
||||
MetaCursor meta_cursor_reference_get_meta_cursor (MetaCursorReference *cursor);
|
||||
|
||||
|
@@ -38,7 +38,7 @@
|
||||
#include <meta/meta-idle-monitor.h>
|
||||
#include "meta-idle-monitor-private.h"
|
||||
#include "meta-idle-monitor-dbus.h"
|
||||
#include "meta-backend.h"
|
||||
#include "meta-backend-private.h"
|
||||
|
||||
G_STATIC_ASSERT(sizeof(unsigned long) == sizeof(gpointer));
|
||||
|
||||
|
@@ -60,7 +60,7 @@ typedef struct {
|
||||
gboolean enabled;
|
||||
MetaRectangle rect;
|
||||
float refresh_rate;
|
||||
enum wl_output_transform transform;
|
||||
MetaMonitorTransform transform;
|
||||
|
||||
gboolean is_primary;
|
||||
gboolean is_presentation;
|
||||
@@ -656,20 +656,20 @@ handle_text (GMarkupParseContext *context,
|
||||
else if (strcmp (parser->output_field, "rotation") == 0)
|
||||
{
|
||||
if (strncmp (text, "normal", text_len) == 0)
|
||||
parser->output.transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
parser->output.transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||
else if (strncmp (text, "left", text_len) == 0)
|
||||
parser->output.transform = WL_OUTPUT_TRANSFORM_90;
|
||||
parser->output.transform = META_MONITOR_TRANSFORM_90;
|
||||
else if (strncmp (text, "upside_down", text_len) == 0)
|
||||
parser->output.transform = WL_OUTPUT_TRANSFORM_180;
|
||||
parser->output.transform = META_MONITOR_TRANSFORM_180;
|
||||
else if (strncmp (text, "right", text_len) == 0)
|
||||
parser->output.transform = WL_OUTPUT_TRANSFORM_270;
|
||||
parser->output.transform = META_MONITOR_TRANSFORM_270;
|
||||
else
|
||||
g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
|
||||
"Invalid rotation type %.*s", (int)text_len, text);
|
||||
}
|
||||
else if (strcmp (parser->output_field, "reflect_x") == 0)
|
||||
parser->output.transform += read_bool (text, text_len, error) ?
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED : 0;
|
||||
META_MONITOR_TRANSFORM_FLIPPED : 0;
|
||||
else if (strcmp (parser->output_field, "reflect_y") == 0)
|
||||
{
|
||||
/* FIXME (look at the rotation map in monitor.c) */
|
||||
@@ -1115,7 +1115,7 @@ make_default_config (MetaMonitorConfig *self,
|
||||
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 = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
ret->outputs[0].transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||
ret->outputs[0].is_primary = TRUE;
|
||||
|
||||
return ret;
|
||||
@@ -1167,7 +1167,7 @@ make_default_config (MetaMonitorConfig *self,
|
||||
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 = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
ret->outputs[j].transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||
ret->outputs[j].is_primary = FALSE;
|
||||
ret->outputs[j].is_presentation = FALSE;
|
||||
}
|
||||
@@ -1202,7 +1202,7 @@ make_default_config (MetaMonitorConfig *self,
|
||||
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 = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
ret->outputs[i].transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||
ret->outputs[i].is_primary = (output == primary);
|
||||
|
||||
/* Disable outputs that would go beyond framebuffer limits */
|
||||
@@ -1250,7 +1250,7 @@ ensure_at_least_one_output (MetaMonitorConfig *self,
|
||||
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 = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
ret->outputs[i].transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||
ret->outputs[i].is_primary = TRUE;
|
||||
}
|
||||
else
|
||||
@@ -1512,7 +1512,7 @@ meta_monitor_config_save (MetaMonitorConfig *self)
|
||||
output->rect.x,
|
||||
output->rect.y,
|
||||
rotation_map[output->transform & 0x3],
|
||||
output->transform >= WL_OUTPUT_TRANSFORM_FLIPPED ? "yes" : "no",
|
||||
output->transform >= META_MONITOR_TRANSFORM_FLIPPED ? "yes" : "no",
|
||||
output->is_primary ? "yes" : "no",
|
||||
output->is_presentation ? "yes" : "no");
|
||||
}
|
||||
@@ -1621,13 +1621,13 @@ output_supports_mode (MetaOutput *output,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
crtc_assignment_assign (CrtcAssignment *assign,
|
||||
MetaCRTC *crtc,
|
||||
MetaMonitorMode *mode,
|
||||
int x,
|
||||
int y,
|
||||
enum wl_output_transform transform,
|
||||
MetaOutput *output)
|
||||
crtc_assignment_assign (CrtcAssignment *assign,
|
||||
MetaCRTC *crtc,
|
||||
MetaMonitorMode *mode,
|
||||
int x,
|
||||
int y,
|
||||
MetaMonitorTransform transform,
|
||||
MetaOutput *output)
|
||||
{
|
||||
MetaCRTCInfo *info = g_hash_table_lookup (assign->info, crtc);
|
||||
|
||||
|
@@ -27,7 +27,7 @@
|
||||
|
||||
#include "meta-monitor-manager-dummy.h"
|
||||
|
||||
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
|
||||
#define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1)
|
||||
|
||||
struct _MetaMonitorManagerDummy
|
||||
{
|
||||
@@ -66,8 +66,8 @@ meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
|
||||
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 = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
manager->crtcs[0].all_transforms = ALL_WL_TRANSFORMS;
|
||||
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;
|
||||
|
||||
@@ -75,7 +75,7 @@ meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
|
||||
manager->n_outputs = 1;
|
||||
|
||||
manager->outputs[0].crtc = &manager->crtcs[0];
|
||||
manager->outputs[0].output_id = 1;
|
||||
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");
|
||||
|
@@ -37,7 +37,7 @@
|
||||
#include <meta/errors.h>
|
||||
#include "meta-monitor-config.h"
|
||||
#include "backends/x11/meta-monitor-manager-xrandr.h"
|
||||
#include "meta-backend.h"
|
||||
#include "meta-backend-private.h"
|
||||
|
||||
enum {
|
||||
CONFIRM_DISPLAY_CHANGE,
|
||||
@@ -125,7 +125,7 @@ make_logical_config (MetaMonitorManager *manager)
|
||||
*/
|
||||
info.is_presentation = TRUE;
|
||||
info.in_fullscreen = -1;
|
||||
info.output_id = 0;
|
||||
info.winsys_id = 0;
|
||||
|
||||
g_array_append_val (monitor_infos, info);
|
||||
|
||||
@@ -156,8 +156,8 @@ make_logical_config (MetaMonitorManager *manager)
|
||||
info->is_primary = info->is_primary || output->is_primary;
|
||||
info->is_presentation = info->is_presentation && output->is_presentation;
|
||||
|
||||
if (output->is_primary || info->output_id == 0)
|
||||
info->output_id = output->output_id;
|
||||
if (output->is_primary || info->winsys_id == 0)
|
||||
info->winsys_id = output->winsys_id;
|
||||
|
||||
if (info->is_primary)
|
||||
manager->primary_monitor_index = info->number;
|
||||
@@ -477,7 +477,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
|
||||
GVariantBuilder transforms;
|
||||
|
||||
g_variant_builder_init (&transforms, G_VARIANT_TYPE ("au"));
|
||||
for (j = 0; j <= WL_OUTPUT_TRANSFORM_FLIPPED_270; j++)
|
||||
for (j = 0; j <= META_MONITOR_TRANSFORM_FLIPPED_270; j++)
|
||||
if (crtc->all_transforms & (1 << j))
|
||||
g_variant_builder_add (&transforms, "u", j);
|
||||
|
||||
@@ -560,7 +560,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
|
||||
|
||||
g_variant_builder_add (&output_builder, "(uxiausauaua{sv})",
|
||||
i, /* ID */
|
||||
(gint64)output->output_id,
|
||||
(gint64)output->winsys_id,
|
||||
(int)(output->crtc ? output->crtc - manager->crtcs : -1),
|
||||
&crtcs,
|
||||
output->name,
|
||||
@@ -667,7 +667,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
||||
int new_mode, x, y;
|
||||
int new_screen_width, new_screen_height;
|
||||
guint transform;
|
||||
guint output_id;
|
||||
guint output_index;
|
||||
GPtrArray *crtc_infos, *output_infos;
|
||||
|
||||
if (serial != manager->serial)
|
||||
@@ -694,7 +694,6 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
||||
MetaOutput *first_output;
|
||||
MetaCRTC *crtc;
|
||||
MetaMonitorMode *mode;
|
||||
guint output_id;
|
||||
|
||||
crtc_info = g_slice_new (MetaCRTCInfo);
|
||||
crtc_info->outputs = g_ptr_array_new ();
|
||||
@@ -756,8 +755,8 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
||||
crtc_info->y = 0;
|
||||
}
|
||||
|
||||
if (transform < WL_OUTPUT_TRANSFORM_NORMAL ||
|
||||
transform > WL_OUTPUT_TRANSFORM_FLIPPED_270 ||
|
||||
if (transform < META_MONITOR_TRANSFORM_NORMAL ||
|
||||
transform > META_MONITOR_TRANSFORM_FLIPPED_270 ||
|
||||
((crtc->all_transforms & (1 << transform)) == 0))
|
||||
{
|
||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||
@@ -768,18 +767,18 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
||||
crtc_info->transform = transform;
|
||||
|
||||
first_output = NULL;
|
||||
while (g_variant_iter_loop (nested_outputs, "u", &output_id))
|
||||
while (g_variant_iter_loop (nested_outputs, "u", &output_index))
|
||||
{
|
||||
MetaOutput *output;
|
||||
|
||||
if (output_id >= manager->n_outputs)
|
||||
if (output_index >= manager->n_outputs)
|
||||
{
|
||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||
G_DBUS_ERROR_INVALID_ARGS,
|
||||
"Invalid output id");
|
||||
return TRUE;
|
||||
}
|
||||
output = &manager->outputs[output_id];
|
||||
output = &manager->outputs[output_index];
|
||||
|
||||
if (!output_can_config (output, crtc, mode))
|
||||
{
|
||||
@@ -824,12 +823,12 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
||||
}
|
||||
|
||||
g_variant_iter_init (&output_iter, outputs);
|
||||
while (g_variant_iter_loop (&output_iter, "(u@a{sv})", &output_id, &properties))
|
||||
while (g_variant_iter_loop (&output_iter, "(u@a{sv})", &output_index, &properties))
|
||||
{
|
||||
MetaOutputInfo *output_info;
|
||||
gboolean primary, presentation;
|
||||
|
||||
if (output_id >= manager->n_outputs)
|
||||
if (output_index >= manager->n_outputs)
|
||||
{
|
||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||
G_DBUS_ERROR_INVALID_ARGS,
|
||||
@@ -838,7 +837,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
||||
}
|
||||
|
||||
output_info = g_slice_new0 (MetaOutputInfo);
|
||||
output_info->output = &manager->outputs[output_id];
|
||||
output_info->output = &manager->outputs[output_index];
|
||||
|
||||
if (g_variant_lookup (properties, "primary", "b", &primary))
|
||||
output_info->is_primary = primary;
|
||||
@@ -909,7 +908,7 @@ static gboolean
|
||||
meta_monitor_manager_handle_change_backlight (MetaDBusDisplayConfig *skeleton,
|
||||
GDBusMethodInvocation *invocation,
|
||||
guint serial,
|
||||
guint output_id,
|
||||
guint output_index,
|
||||
gint value)
|
||||
{
|
||||
MetaMonitorManager *manager = META_MONITOR_MANAGER (skeleton);
|
||||
@@ -923,14 +922,14 @@ meta_monitor_manager_handle_change_backlight (MetaDBusDisplayConfig *skeleton,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (output_id >= manager->n_outputs)
|
||||
if (output_index >= manager->n_outputs)
|
||||
{
|
||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||
G_DBUS_ERROR_INVALID_ARGS,
|
||||
"Invalid output id");
|
||||
return TRUE;
|
||||
}
|
||||
output = &manager->outputs[output_id];
|
||||
output = &manager->outputs[output_index];
|
||||
|
||||
if (value < 0 || value > 100)
|
||||
{
|
||||
|
@@ -41,8 +41,6 @@
|
||||
#include "display-private.h"
|
||||
#include <meta/screen.h>
|
||||
#include "stack-tracker.h"
|
||||
#include "ui.h"
|
||||
#include <wayland-server.h>
|
||||
|
||||
#include "meta-display-config-shared.h"
|
||||
#include "meta-dbus-display-config.h"
|
||||
@@ -60,12 +58,23 @@ typedef struct _MetaMonitorInfo MetaMonitorInfo;
|
||||
typedef struct _MetaCRTCInfo MetaCRTCInfo;
|
||||
typedef struct _MetaOutputInfo MetaOutputInfo;
|
||||
|
||||
typedef enum {
|
||||
META_MONITOR_TRANSFORM_NORMAL,
|
||||
META_MONITOR_TRANSFORM_90,
|
||||
META_MONITOR_TRANSFORM_180,
|
||||
META_MONITOR_TRANSFORM_270,
|
||||
META_MONITOR_TRANSFORM_FLIPPED,
|
||||
META_MONITOR_TRANSFORM_FLIPPED_90,
|
||||
META_MONITOR_TRANSFORM_FLIPPED_180,
|
||||
META_MONITOR_TRANSFORM_FLIPPED_270,
|
||||
} MetaMonitorTransform;
|
||||
|
||||
struct _MetaOutput
|
||||
{
|
||||
/* The CRTC driving this output, NULL if the output is not enabled */
|
||||
MetaCRTC *crtc;
|
||||
/* The low-level ID of this output, used to apply back configuration */
|
||||
glong output_id;
|
||||
glong winsys_id;
|
||||
char *name;
|
||||
char *vendor;
|
||||
char *product;
|
||||
@@ -114,7 +123,7 @@ struct _MetaCRTC
|
||||
glong crtc_id;
|
||||
MetaRectangle rect;
|
||||
MetaMonitorMode *current_mode;
|
||||
enum wl_output_transform transform;
|
||||
MetaMonitorTransform transform;
|
||||
unsigned int all_transforms;
|
||||
|
||||
/* Only used to build the logical configuration
|
||||
@@ -162,14 +171,14 @@ struct _MetaMonitorInfo
|
||||
gboolean in_fullscreen;
|
||||
|
||||
/* The primary or first output for this monitor, 0 if we can't figure out.
|
||||
It can be matched to an output_id of a MetaOutput.
|
||||
It can be matched to a winsys_id of a MetaOutput.
|
||||
|
||||
This is used as an opaque token on reconfiguration when switching from
|
||||
clone to extened, to decide on what output the windows should go next
|
||||
(it's an attempt to keep windows on the same monitor, and preferably on
|
||||
the primary one).
|
||||
*/
|
||||
glong output_id;
|
||||
glong winsys_id;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -185,7 +194,7 @@ struct _MetaCRTCInfo {
|
||||
MetaMonitorMode *mode;
|
||||
int x;
|
||||
int y;
|
||||
enum wl_output_transform transform;
|
||||
MetaMonitorTransform transform;
|
||||
GPtrArray *outputs;
|
||||
};
|
||||
|
||||
@@ -339,7 +348,7 @@ gboolean meta_monitor_manager_has_hotplug_mode_update (MetaMonitorMana
|
||||
/* Returns true if transform causes width and height to be inverted
|
||||
This is true for the odd transforms in the enum */
|
||||
static inline gboolean
|
||||
meta_monitor_transform_is_rotated (enum wl_output_transform transform)
|
||||
meta_monitor_transform_is_rotated (MetaMonitorTransform transform)
|
||||
{
|
||||
return (transform % 2);
|
||||
}
|
||||
|
214
src/backends/meta-stage.c
Normal file
214
src/backends/meta-stage.c
Normal file
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "meta-stage.h"
|
||||
|
||||
#include "meta-cursor-private.h"
|
||||
#include <meta/meta-backend.h>
|
||||
#include <meta/util.h>
|
||||
|
||||
typedef struct {
|
||||
gboolean enabled;
|
||||
|
||||
CoglPipeline *pipeline;
|
||||
CoglTexture *texture;
|
||||
|
||||
MetaRectangle current_rect;
|
||||
MetaRectangle previous_rect;
|
||||
gboolean previous_is_valid;
|
||||
} MetaOverlay;
|
||||
|
||||
struct _MetaStagePrivate {
|
||||
MetaOverlay dnd_overlay;
|
||||
MetaOverlay cursor_overlay;
|
||||
};
|
||||
typedef struct _MetaStagePrivate MetaStagePrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaStage, meta_stage, CLUTTER_TYPE_STAGE);
|
||||
|
||||
static void
|
||||
meta_overlay_init (MetaOverlay *overlay)
|
||||
{
|
||||
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
|
||||
overlay->pipeline = cogl_pipeline_new (ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_overlay_free (MetaOverlay *overlay)
|
||||
{
|
||||
if (overlay->pipeline)
|
||||
cogl_object_unref (overlay->pipeline);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_overlay_set (MetaOverlay *overlay,
|
||||
CoglTexture *texture,
|
||||
MetaRectangle *rect)
|
||||
{
|
||||
if (overlay->texture != texture)
|
||||
{
|
||||
overlay->texture = texture;
|
||||
|
||||
if (texture)
|
||||
{
|
||||
cogl_pipeline_set_layer_texture (overlay->pipeline, 0, texture);
|
||||
overlay->enabled = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
cogl_pipeline_set_layer_texture (overlay->pipeline, 0, NULL);
|
||||
overlay->enabled = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
overlay->current_rect = *rect;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_overlay_paint (MetaOverlay *overlay)
|
||||
{
|
||||
if (!overlay->enabled)
|
||||
return;
|
||||
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (),
|
||||
overlay->pipeline,
|
||||
overlay->current_rect.x,
|
||||
overlay->current_rect.y,
|
||||
overlay->current_rect.x +
|
||||
overlay->current_rect.width,
|
||||
overlay->current_rect.y +
|
||||
overlay->current_rect.height);
|
||||
|
||||
overlay->previous_rect = overlay->current_rect;
|
||||
overlay->previous_is_valid = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_stage_finalize (GObject *object)
|
||||
{
|
||||
MetaStage *stage = META_STAGE (object);
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
|
||||
meta_overlay_free (&priv->dnd_overlay);
|
||||
meta_overlay_free (&priv->cursor_overlay);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_stage_paint (ClutterActor *actor)
|
||||
{
|
||||
MetaStage *stage = META_STAGE (actor);
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
|
||||
CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor);
|
||||
|
||||
meta_overlay_paint (&priv->dnd_overlay);
|
||||
meta_overlay_paint (&priv->cursor_overlay);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_stage_class_init (MetaStageClass *klass)
|
||||
{
|
||||
ClutterActorClass *actor_class = (ClutterActorClass *) klass;
|
||||
GObjectClass *object_class = (GObjectClass *) klass;
|
||||
|
||||
object_class->finalize = meta_stage_finalize;
|
||||
|
||||
actor_class->paint = meta_stage_paint;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_stage_init (MetaStage *stage)
|
||||
{
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
|
||||
meta_overlay_init (&priv->dnd_overlay);
|
||||
meta_overlay_init (&priv->cursor_overlay);
|
||||
|
||||
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), FALSE);
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
meta_stage_new (void)
|
||||
{
|
||||
return g_object_new (META_TYPE_STAGE,
|
||||
"cursor-visible", FALSE,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
queue_redraw_for_overlay (MetaStage *stage,
|
||||
MetaOverlay *overlay)
|
||||
{
|
||||
cairo_rectangle_int_t clip;
|
||||
|
||||
/* Clear the location the overlay was at before, if we need to. */
|
||||
if (overlay->previous_is_valid)
|
||||
{
|
||||
clip.x = overlay->previous_rect.x;
|
||||
clip.y = overlay->previous_rect.y;
|
||||
clip.width = overlay->previous_rect.width;
|
||||
clip.height = overlay->previous_rect.height;
|
||||
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &clip);
|
||||
overlay->previous_is_valid = FALSE;
|
||||
}
|
||||
|
||||
/* Draw the overlay at the new position */
|
||||
if (overlay->enabled)
|
||||
{
|
||||
clip.x = overlay->current_rect.x;
|
||||
clip.y = overlay->current_rect.y;
|
||||
clip.width = overlay->current_rect.width;
|
||||
clip.height = overlay->current_rect.height;
|
||||
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &clip);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_stage_set_dnd_surface (MetaStage *stage,
|
||||
CoglTexture *texture,
|
||||
MetaRectangle *rect)
|
||||
{
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
meta_overlay_set (&priv->dnd_overlay, texture, rect);
|
||||
queue_redraw_for_overlay (stage, &priv->dnd_overlay);
|
||||
}
|
||||
|
||||
void
|
||||
meta_stage_set_cursor (MetaStage *stage,
|
||||
CoglTexture *texture,
|
||||
MetaRectangle *rect)
|
||||
{
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
|
||||
g_assert (meta_is_wayland_compositor () || texture == NULL);
|
||||
|
||||
meta_overlay_set (&priv->cursor_overlay, texture, rect);
|
||||
queue_redraw_for_overlay (stage, &priv->cursor_overlay);
|
||||
}
|
@@ -51,9 +51,14 @@ GType meta_stage_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ClutterActor *meta_stage_new (void);
|
||||
|
||||
void meta_stage_set_cursor (MetaStage *stage,
|
||||
MetaCursorReference *cursor,
|
||||
MetaRectangle *rect);
|
||||
void meta_stage_set_dnd_surface (MetaStage *stage,
|
||||
CoglTexture *texture,
|
||||
MetaRectangle *rect);
|
||||
|
||||
void meta_stage_set_cursor (MetaStage *stage,
|
||||
CoglTexture *texture,
|
||||
MetaRectangle *rect);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* META_STAGE_H */
|
@@ -174,6 +174,63 @@ meta_backend_native_create_cursor_renderer (MetaBackend *backend)
|
||||
return g_object_new (META_TYPE_CURSOR_RENDERER_NATIVE, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_native_warp_pointer (MetaBackend *backend,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
|
||||
ClutterInputDevice *device = clutter_device_manager_get_core_device (manager, CLUTTER_POINTER_DEVICE);
|
||||
|
||||
/* XXX */
|
||||
guint32 time_ = 0;
|
||||
|
||||
clutter_evdev_warp_pointer (device, time_, x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_native_set_keymap (MetaBackend *backend,
|
||||
const char *layouts,
|
||||
const char *variants,
|
||||
const char *options)
|
||||
{
|
||||
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
|
||||
struct xkb_rule_names names;
|
||||
struct xkb_keymap *keymap;
|
||||
struct xkb_context *context;
|
||||
|
||||
names.rules = DEFAULT_XKB_RULES_FILE;
|
||||
names.model = DEFAULT_XKB_MODEL;
|
||||
names.layout = layouts;
|
||||
names.variant = variants;
|
||||
names.options = options;
|
||||
|
||||
context = xkb_context_new (XKB_CONTEXT_NO_FLAGS);
|
||||
keymap = xkb_keymap_new_from_names (context, &names, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
xkb_context_unref (context);
|
||||
|
||||
clutter_evdev_set_keyboard_map (manager, keymap);
|
||||
|
||||
g_signal_emit_by_name (backend, "keymap-changed", 0);
|
||||
|
||||
xkb_keymap_unref (keymap);
|
||||
}
|
||||
|
||||
static struct xkb_keymap *
|
||||
meta_backend_native_get_keymap (MetaBackend *backend)
|
||||
{
|
||||
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
|
||||
return clutter_evdev_get_keyboard_map (manager);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_native_lock_layout_group (MetaBackend *backend,
|
||||
guint idx)
|
||||
{
|
||||
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
|
||||
clutter_evdev_set_keyboard_layout_index (manager, idx);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_native_class_init (MetaBackendNativeClass *klass)
|
||||
{
|
||||
@@ -183,6 +240,11 @@ meta_backend_native_class_init (MetaBackendNativeClass *klass)
|
||||
backend_class->create_idle_monitor = meta_backend_native_create_idle_monitor;
|
||||
backend_class->create_monitor_manager = meta_backend_native_create_monitor_manager;
|
||||
backend_class->create_cursor_renderer = meta_backend_native_create_cursor_renderer;
|
||||
|
||||
backend_class->warp_pointer = meta_backend_native_warp_pointer;
|
||||
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;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -72,16 +72,16 @@ set_crtc_cursor (MetaCursorRendererNative *native,
|
||||
struct gbm_bo *bo;
|
||||
union gbm_bo_handle handle;
|
||||
int width, height;
|
||||
int hot_x, hot_y;
|
||||
int offset_x, offset_y;
|
||||
|
||||
bo = meta_cursor_reference_get_gbm_bo (cursor, &hot_x, &hot_y);
|
||||
bo = meta_cursor_reference_get_gbm_bo (cursor, &offset_x, &offset_y);
|
||||
|
||||
handle = gbm_bo_get_handle (bo);
|
||||
width = gbm_bo_get_width (bo);
|
||||
height = gbm_bo_get_height (bo);
|
||||
|
||||
drmModeSetCursor2 (priv->drm_fd, crtc->crtc_id, handle.u32,
|
||||
width, height, hot_x, hot_y);
|
||||
width, height, -offset_x, -offset_y);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@@ -41,8 +41,7 @@
|
||||
#include "dbus-utils.h"
|
||||
#include "meta-dbus-login1.h"
|
||||
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
#include "backends/meta-backend.h"
|
||||
#include "backends/meta-backend-private.h"
|
||||
#include "meta-cursor-renderer-native.h"
|
||||
|
||||
struct _MetaLauncher
|
||||
@@ -101,15 +100,15 @@ session_unpause (void)
|
||||
clutter_egl_thaw_master_clock ();
|
||||
|
||||
{
|
||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (backend);
|
||||
ClutterActor *stage = meta_backend_get_stage (backend);
|
||||
|
||||
/* When we mode-switch back, we need to immediately queue a redraw
|
||||
* in case nothing else queued one for us, and force the cursor to
|
||||
* update. */
|
||||
|
||||
clutter_actor_queue_redraw (compositor->stage);
|
||||
clutter_actor_queue_redraw (stage);
|
||||
meta_cursor_renderer_native_force_update (META_CURSOR_RENDERER_NATIVE (renderer));
|
||||
}
|
||||
}
|
||||
|
@@ -40,8 +40,6 @@
|
||||
#include <meta/errors.h>
|
||||
#include "edid.h"
|
||||
|
||||
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
|
||||
|
||||
typedef struct {
|
||||
drmModeConnector *connector;
|
||||
|
||||
@@ -259,7 +257,7 @@ find_output_by_id (MetaOutput *outputs,
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
if (outputs[i].output_id == id)
|
||||
if (outputs[i].winsys_id == id)
|
||||
return &outputs[i];
|
||||
|
||||
return NULL;
|
||||
@@ -363,9 +361,9 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
|
||||
meta_crtc->rect.width = crtc->width;
|
||||
meta_crtc->rect.height = crtc->height;
|
||||
meta_crtc->is_dirty = FALSE;
|
||||
meta_crtc->transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
meta_crtc->transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||
/* FIXME: implement! */
|
||||
meta_crtc->all_transforms = 1 << WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
meta_crtc->all_transforms = 1 << META_MONITOR_TRANSFORM_NORMAL;
|
||||
|
||||
if (crtc->mode_valid)
|
||||
{
|
||||
@@ -408,7 +406,7 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
|
||||
meta_output->driver_private = output_kms = g_slice_new0 (MetaOutputKms);
|
||||
meta_output->driver_notify = (GDestroyNotify)meta_output_destroy_notify;
|
||||
|
||||
meta_output->output_id = connector->connector_id;
|
||||
meta_output->winsys_id = connector->connector_id;
|
||||
meta_output->name = make_output_name (connector);
|
||||
meta_output->width_mm = connector->mmWidth;
|
||||
meta_output->height_mm = connector->mmHeight;
|
||||
@@ -491,7 +489,7 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
|
||||
meta_output->crtc = NULL;
|
||||
|
||||
old_output = find_output_by_id (old_outputs, n_old_outputs,
|
||||
meta_output->output_id);
|
||||
meta_output->winsys_id);
|
||||
if (old_output)
|
||||
{
|
||||
meta_output->is_primary = old_output->is_primary;
|
||||
@@ -667,7 +665,7 @@ 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->output_id,
|
||||
int ok = drmModeConnectorSetProperty(manager_kms->fd, meta_output->winsys_id,
|
||||
output_kms->dpms_prop_id, state);
|
||||
|
||||
if (ok < 0)
|
||||
@@ -748,7 +746,7 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
|
||||
{
|
||||
MetaOutput *output = g_ptr_array_index (crtc_info->outputs, j);
|
||||
|
||||
connectors[j] = output->output_id;
|
||||
connectors[j] = output->winsys_id;
|
||||
|
||||
output->is_dirty = TRUE;
|
||||
output->crtc = crtc;
|
||||
|
@@ -24,11 +24,18 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "meta-backend-x11.h"
|
||||
|
||||
#include <clutter/x11/clutter-x11.h>
|
||||
|
||||
#include <X11/extensions/sync.h>
|
||||
#include <X11/XKBlib.h>
|
||||
#include <X11/extensions/XKBrules.h>
|
||||
#include <X11/Xlib-xcb.h>
|
||||
#include <xkbcommon/xkbcommon-x11.h>
|
||||
|
||||
#include "meta-idle-monitor-xsync.h"
|
||||
#include "meta-monitor-manager-xrandr.h"
|
||||
@@ -43,6 +50,7 @@ struct _MetaBackendX11Private
|
||||
{
|
||||
/* The host X11 display */
|
||||
Display *xdisplay;
|
||||
xcb_connection_t *xcb;
|
||||
GSource *source;
|
||||
|
||||
int xsync_event_base;
|
||||
@@ -51,6 +59,12 @@ struct _MetaBackendX11Private
|
||||
int xinput_opcode;
|
||||
int xinput_event_base;
|
||||
int xinput_error_base;
|
||||
Time latest_evtime;
|
||||
|
||||
uint8_t xkb_event_base;
|
||||
uint8_t xkb_error_base;
|
||||
|
||||
struct xkb_keymap *keymap;
|
||||
};
|
||||
typedef struct _MetaBackendX11Private MetaBackendX11Private;
|
||||
|
||||
@@ -71,6 +85,7 @@ static void
|
||||
translate_device_event (MetaBackendX11 *x11,
|
||||
XIDeviceEvent *device_event)
|
||||
{
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
Window stage_window = meta_backend_x11_get_xwindow (x11);
|
||||
|
||||
if (device_event->event != stage_window)
|
||||
@@ -88,6 +103,21 @@ translate_device_event (MetaBackendX11 *x11,
|
||||
device_event->event_x = device_event->root_x;
|
||||
device_event->event_y = device_event->root_y;
|
||||
}
|
||||
|
||||
if (!device_event->send_event && device_event->time != CurrentTime)
|
||||
{
|
||||
if (device_event->time < priv->latest_evtime)
|
||||
{
|
||||
/* Emulated pointer events received after XIRejectTouch is received
|
||||
* on a passive touch grab will contain older timestamps, update those
|
||||
* so we dont get InvalidTime at grabs.
|
||||
*/
|
||||
device_event->time = priv->latest_evtime;
|
||||
}
|
||||
|
||||
/* Update the internal latest evtime, for any possible later use */
|
||||
priv->latest_evtime = device_event->time;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clutter makes the assumption that there is only one X window
|
||||
@@ -117,6 +147,9 @@ maybe_spoof_event_as_stage_event (MetaBackendX11 *x11,
|
||||
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:
|
||||
@@ -125,6 +158,21 @@ maybe_spoof_event_as_stage_event (MetaBackendX11 *x11,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
keymap_changed (MetaBackend *backend)
|
||||
{
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
|
||||
if (priv->keymap)
|
||||
{
|
||||
xkb_keymap_unref (priv->keymap);
|
||||
priv->keymap = NULL;
|
||||
}
|
||||
|
||||
g_signal_emit_by_name (backend, "keymap-changed", 0);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_host_xevent (MetaBackend *backend,
|
||||
XEvent *event)
|
||||
@@ -135,24 +183,49 @@ handle_host_xevent (MetaBackend *backend,
|
||||
|
||||
XGetEventData (priv->xdisplay, &event->xcookie);
|
||||
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
|
||||
if (display)
|
||||
{
|
||||
MetaCompositor *compositor = display->compositor;
|
||||
if (meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event))
|
||||
bypass_clutter = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (xkb_ev->device == META_VIRTUAL_CORE_KEYBOARD_ID)
|
||||
{
|
||||
switch (xkb_ev->xkb_type)
|
||||
{
|
||||
case XkbNewKeyboardNotify:
|
||||
case XkbMapNotify:
|
||||
keymap_changed (backend);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
MetaMonitorManager *manager = meta_backend_get_monitor_manager (backend);
|
||||
if (META_IS_MONITOR_MANAGER_XRANDR (manager) &&
|
||||
meta_monitor_manager_xrandr_handle_xevent (META_MONITOR_MANAGER_XRANDR (manager), event))
|
||||
{
|
||||
bypass_clutter = TRUE;
|
||||
goto out;
|
||||
}
|
||||
bypass_clutter = TRUE;
|
||||
}
|
||||
|
||||
maybe_spoof_event_as_stage_event (x11, event);
|
||||
|
||||
out:
|
||||
if (!bypass_clutter)
|
||||
clutter_x11_handle_event (event);
|
||||
{
|
||||
maybe_spoof_event_as_stage_event (x11, event);
|
||||
clutter_x11_handle_event (event);
|
||||
}
|
||||
|
||||
XFreeEventData (priv->xdisplay, &event->xcookie);
|
||||
}
|
||||
@@ -235,6 +308,24 @@ x_event_source_new (MetaBackend *backend)
|
||||
return source;
|
||||
}
|
||||
|
||||
static void
|
||||
take_touch_grab (MetaBackend *backend)
|
||||
{
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
XIEventMask mask = { META_VIRTUAL_CORE_POINTER_ID, sizeof (mask_bits), mask_bits };
|
||||
XIGrabModifiers mods = { XIAnyModifier, 0 };
|
||||
|
||||
XISetMask (mask.mask, XI_TouchBegin);
|
||||
XISetMask (mask.mask, XI_TouchUpdate);
|
||||
XISetMask (mask.mask, XI_TouchEnd);
|
||||
|
||||
XIGrabTouchBegin (priv->xdisplay, META_VIRTUAL_CORE_POINTER_ID,
|
||||
DefaultRootWindow (priv->xdisplay),
|
||||
False, &mask, 1, &mods);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_x11_post_init (MetaBackend *backend)
|
||||
{
|
||||
@@ -272,6 +363,19 @@ meta_backend_x11_post_init (MetaBackend *backend)
|
||||
meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer\n");
|
||||
}
|
||||
|
||||
take_touch_grab (backend);
|
||||
|
||||
priv->xcb = XGetXCBConnection (priv->xdisplay);
|
||||
if (!xkb_x11_setup_xkb_extension (priv->xcb,
|
||||
XKB_X11_MIN_MAJOR_XKB_VERSION,
|
||||
XKB_X11_MIN_MINOR_XKB_VERSION,
|
||||
XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS,
|
||||
NULL, NULL,
|
||||
&priv->xkb_event_base,
|
||||
&priv->xkb_error_base))
|
||||
meta_fatal ("X server doesn't have the XKB extension, version %d.%d or newer\n",
|
||||
XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION);
|
||||
|
||||
META_BACKEND_CLASS (meta_backend_x11_parent_class)->post_init (backend);
|
||||
}
|
||||
|
||||
@@ -313,6 +417,9 @@ meta_backend_x11_grab_device (MetaBackend *backend,
|
||||
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||
int ret;
|
||||
|
||||
if (timestamp != CurrentTime)
|
||||
timestamp = MAX (timestamp, priv->latest_evtime);
|
||||
|
||||
XISetMask (mask.mask, XI_ButtonPress);
|
||||
XISetMask (mask.mask, XI_ButtonRelease);
|
||||
XISetMask (mask.mask, XI_Enter);
|
||||
@@ -362,6 +469,198 @@ meta_backend_x11_warp_pointer (MetaBackend *backend,
|
||||
x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
get_xkbrf_var_defs (Display *xdisplay,
|
||||
const char *layouts,
|
||||
const char *variants,
|
||||
const char *options,
|
||||
char **rules_p,
|
||||
XkbRF_VarDefsRec *var_defs)
|
||||
{
|
||||
char *rules = NULL;
|
||||
|
||||
/* Get it from the X property or fallback on defaults */
|
||||
if (!XkbRF_GetNamesProp (xdisplay, &rules, var_defs) || !rules)
|
||||
{
|
||||
rules = strdup (DEFAULT_XKB_RULES_FILE);
|
||||
var_defs->model = strdup (DEFAULT_XKB_MODEL);
|
||||
var_defs->layout = NULL;
|
||||
var_defs->variant = NULL;
|
||||
var_defs->options = NULL;
|
||||
}
|
||||
|
||||
/* Swap in our new options... */
|
||||
free (var_defs->layout);
|
||||
var_defs->layout = strdup (layouts);
|
||||
free (var_defs->variant);
|
||||
var_defs->variant = strdup (variants);
|
||||
free (var_defs->options);
|
||||
var_defs->options = strdup (options);
|
||||
|
||||
/* Sometimes, the property is a file path, and sometimes it's
|
||||
not. Normalize it so it's always a file path. */
|
||||
if (rules[0] == '/')
|
||||
*rules_p = g_strdup (rules);
|
||||
else
|
||||
*rules_p = g_build_filename (XKB_BASE, "rules", rules, NULL);
|
||||
|
||||
free (rules);
|
||||
}
|
||||
|
||||
static void
|
||||
free_xkbrf_var_defs (XkbRF_VarDefsRec *var_defs)
|
||||
{
|
||||
free (var_defs->model);
|
||||
free (var_defs->layout);
|
||||
free (var_defs->variant);
|
||||
free (var_defs->options);
|
||||
}
|
||||
|
||||
static void
|
||||
free_xkb_component_names (XkbComponentNamesRec *p)
|
||||
{
|
||||
free (p->keymap);
|
||||
free (p->keycodes);
|
||||
free (p->types);
|
||||
free (p->compat);
|
||||
free (p->symbols);
|
||||
free (p->geometry);
|
||||
}
|
||||
|
||||
static void
|
||||
upload_xkb_description (Display *xdisplay,
|
||||
const gchar *rules_file_path,
|
||||
XkbRF_VarDefsRec *var_defs,
|
||||
XkbComponentNamesRec *comp_names)
|
||||
{
|
||||
XkbDescRec *xkb_desc;
|
||||
gchar *rules_file;
|
||||
|
||||
/* Upload it to the X server using the same method as setxkbmap */
|
||||
xkb_desc = XkbGetKeyboardByName (xdisplay,
|
||||
XkbUseCoreKbd,
|
||||
comp_names,
|
||||
XkbGBN_AllComponentsMask,
|
||||
XkbGBN_AllComponentsMask &
|
||||
(~XkbGBN_GeometryMask), True);
|
||||
if (!xkb_desc)
|
||||
{
|
||||
g_warning ("Couldn't upload new XKB keyboard description");
|
||||
return;
|
||||
}
|
||||
|
||||
XkbFreeKeyboard (xkb_desc, 0, True);
|
||||
|
||||
rules_file = g_path_get_basename (rules_file_path);
|
||||
|
||||
if (!XkbRF_SetNamesProp (xdisplay, rules_file, var_defs))
|
||||
g_warning ("Couldn't update the XKB root window property");
|
||||
|
||||
g_free (rules_file);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_x11_set_keymap (MetaBackend *backend,
|
||||
const char *layouts,
|
||||
const char *variants,
|
||||
const char *options)
|
||||
{
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
XkbRF_RulesRec *xkb_rules;
|
||||
XkbRF_VarDefsRec xkb_var_defs = { 0 };
|
||||
gchar *rules_file_path;
|
||||
|
||||
get_xkbrf_var_defs (priv->xdisplay,
|
||||
layouts,
|
||||
variants,
|
||||
options,
|
||||
&rules_file_path,
|
||||
&xkb_var_defs);
|
||||
|
||||
xkb_rules = XkbRF_Load (rules_file_path, NULL, True, True);
|
||||
if (xkb_rules)
|
||||
{
|
||||
XkbComponentNamesRec xkb_comp_names = { 0 };
|
||||
|
||||
XkbRF_GetComponents (xkb_rules, &xkb_var_defs, &xkb_comp_names);
|
||||
upload_xkb_description (priv->xdisplay, rules_file_path, &xkb_var_defs, &xkb_comp_names);
|
||||
|
||||
free_xkb_component_names (&xkb_comp_names);
|
||||
XkbRF_Free (xkb_rules, True);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Couldn't load XKB rules");
|
||||
}
|
||||
|
||||
free_xkbrf_var_defs (&xkb_var_defs);
|
||||
g_free (rules_file_path);
|
||||
}
|
||||
|
||||
static struct xkb_keymap *
|
||||
meta_backend_x11_get_keymap (MetaBackend *backend)
|
||||
{
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
|
||||
if (priv->keymap == NULL)
|
||||
{
|
||||
struct xkb_context *context = xkb_context_new (XKB_CONTEXT_NO_FLAGS);
|
||||
priv->keymap = xkb_x11_keymap_new_from_device (context,
|
||||
priv->xcb,
|
||||
xkb_x11_get_core_keyboard_device_id (priv->xcb),
|
||||
XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
xkb_context_unref (context);
|
||||
}
|
||||
|
||||
return priv->keymap;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_x11_lock_layout_group (MetaBackend *backend,
|
||||
guint idx)
|
||||
{
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
|
||||
XkbLockGroup (priv->xdisplay, XkbUseCoreKbd, idx);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_x11_update_screen_size (MetaBackend *backend,
|
||||
int width, int height)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_x11_select_stage_events (MetaBackend *backend)
|
||||
{
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
Window xwin = meta_backend_x11_get_xwindow (x11);
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||
|
||||
XISetMask (mask.mask, XI_KeyPress);
|
||||
XISetMask (mask.mask, XI_KeyRelease);
|
||||
XISetMask (mask.mask, XI_ButtonPress);
|
||||
XISetMask (mask.mask, XI_ButtonRelease);
|
||||
XISetMask (mask.mask, XI_Enter);
|
||||
XISetMask (mask.mask, XI_Leave);
|
||||
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);
|
||||
XISelectEvents (priv->xdisplay, xwin, &mask, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_x11_class_init (MetaBackendX11Class *klass)
|
||||
{
|
||||
@@ -371,10 +670,14 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass)
|
||||
backend_class->create_idle_monitor = meta_backend_x11_create_idle_monitor;
|
||||
backend_class->create_monitor_manager = meta_backend_x11_create_monitor_manager;
|
||||
backend_class->create_cursor_renderer = meta_backend_x11_create_cursor_renderer;
|
||||
|
||||
backend_class->grab_device = meta_backend_x11_grab_device;
|
||||
backend_class->ungrab_device = meta_backend_x11_ungrab_device;
|
||||
backend_class->warp_pointer = meta_backend_x11_warp_pointer;
|
||||
backend_class->set_keymap = meta_backend_x11_set_keymap;
|
||||
backend_class->get_keymap = meta_backend_x11_get_keymap;
|
||||
backend_class->lock_layout_group = meta_backend_x11_lock_layout_group;
|
||||
backend_class->update_screen_size = meta_backend_x11_update_screen_size;
|
||||
backend_class->select_stage_events = meta_backend_x11_select_stage_events;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -395,12 +698,6 @@ meta_backend_x11_get_xdisplay (MetaBackendX11 *x11)
|
||||
Window
|
||||
meta_backend_x11_get_xwindow (MetaBackendX11 *x11)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
MetaCompositor *compositor = display->compositor;
|
||||
|
||||
if (compositor == NULL)
|
||||
return None;
|
||||
|
||||
ClutterStage *stage = CLUTTER_STAGE (compositor->stage);
|
||||
return clutter_x11_get_stage_window (stage);
|
||||
ClutterActor *stage = meta_backend_get_stage (META_BACKEND (x11));
|
||||
return clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
|
||||
}
|
||||
|
@@ -35,6 +35,8 @@
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#include <X11/extensions/dpms.h>
|
||||
#include <X11/Xlib-xcb.h>
|
||||
#include <xcb/randr.h>
|
||||
|
||||
#include "meta-backend-x11.h"
|
||||
#include <meta/main.h>
|
||||
@@ -42,7 +44,7 @@
|
||||
#include "edid.h"
|
||||
#include "meta-monitor-config.h"
|
||||
|
||||
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
|
||||
#define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1)
|
||||
|
||||
/* Look for DPI_FALLBACK in:
|
||||
* http://git.gnome.org/browse/gnome-settings-daemon/tree/plugins/xsettings/gsd-xsettings-manager.c
|
||||
@@ -67,31 +69,31 @@ struct _MetaMonitorManagerXrandrClass
|
||||
|
||||
G_DEFINE_TYPE (MetaMonitorManagerXrandr, meta_monitor_manager_xrandr, META_TYPE_MONITOR_MANAGER);
|
||||
|
||||
static enum wl_output_transform
|
||||
wl_transform_from_xrandr (Rotation rotation)
|
||||
static MetaMonitorTransform
|
||||
meta_monitor_transform_from_xrandr (Rotation rotation)
|
||||
{
|
||||
static const enum wl_output_transform y_reflected_map[4] = {
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED_180,
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED_90,
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED,
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED_270
|
||||
static const MetaMonitorTransform y_reflected_map[4] = {
|
||||
META_MONITOR_TRANSFORM_FLIPPED_180,
|
||||
META_MONITOR_TRANSFORM_FLIPPED_90,
|
||||
META_MONITOR_TRANSFORM_FLIPPED,
|
||||
META_MONITOR_TRANSFORM_FLIPPED_270
|
||||
};
|
||||
enum wl_output_transform ret;
|
||||
MetaMonitorTransform ret;
|
||||
|
||||
switch (rotation & 0x7F)
|
||||
{
|
||||
default:
|
||||
case RR_Rotate_0:
|
||||
ret = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
ret = META_MONITOR_TRANSFORM_NORMAL;
|
||||
break;
|
||||
case RR_Rotate_90:
|
||||
ret = WL_OUTPUT_TRANSFORM_90;
|
||||
ret = META_MONITOR_TRANSFORM_90;
|
||||
break;
|
||||
case RR_Rotate_180:
|
||||
ret = WL_OUTPUT_TRANSFORM_180;
|
||||
ret = META_MONITOR_TRANSFORM_180;
|
||||
break;
|
||||
case RR_Rotate_270:
|
||||
ret = WL_OUTPUT_TRANSFORM_270;
|
||||
ret = META_MONITOR_TRANSFORM_270;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -105,42 +107,42 @@ wl_transform_from_xrandr (Rotation rotation)
|
||||
|
||||
#define ALL_ROTATIONS (RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270)
|
||||
|
||||
static unsigned int
|
||||
wl_transform_from_xrandr_all (Rotation rotation)
|
||||
static MetaMonitorTransform
|
||||
meta_monitor_transform_from_xrandr_all (Rotation rotation)
|
||||
{
|
||||
unsigned ret;
|
||||
|
||||
/* Handle the common cases first (none or all) */
|
||||
if (rotation == 0 || rotation == RR_Rotate_0)
|
||||
return (1 << WL_OUTPUT_TRANSFORM_NORMAL);
|
||||
return (1 << META_MONITOR_TRANSFORM_NORMAL);
|
||||
|
||||
/* All rotations and one reflection -> all of them by composition */
|
||||
if ((rotation & ALL_ROTATIONS) &&
|
||||
((rotation & RR_Reflect_X) || (rotation & RR_Reflect_Y)))
|
||||
return ALL_WL_TRANSFORMS;
|
||||
return ALL_TRANSFORMS;
|
||||
|
||||
ret = 1 << WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
ret = 1 << META_MONITOR_TRANSFORM_NORMAL;
|
||||
if (rotation & RR_Rotate_90)
|
||||
ret |= 1 << WL_OUTPUT_TRANSFORM_90;
|
||||
ret |= 1 << META_MONITOR_TRANSFORM_90;
|
||||
if (rotation & RR_Rotate_180)
|
||||
ret |= 1 << WL_OUTPUT_TRANSFORM_180;
|
||||
ret |= 1 << META_MONITOR_TRANSFORM_180;
|
||||
if (rotation & RR_Rotate_270)
|
||||
ret |= 1 << WL_OUTPUT_TRANSFORM_270;
|
||||
ret |= 1 << META_MONITOR_TRANSFORM_270;
|
||||
if (rotation & (RR_Rotate_0 | RR_Reflect_X))
|
||||
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED;
|
||||
ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED;
|
||||
if (rotation & (RR_Rotate_90 | RR_Reflect_X))
|
||||
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_90;
|
||||
ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED_90;
|
||||
if (rotation & (RR_Rotate_180 | RR_Reflect_X))
|
||||
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_180;
|
||||
ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED_180;
|
||||
if (rotation & (RR_Rotate_270 | RR_Reflect_X))
|
||||
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_270;
|
||||
ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED_270;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
output_get_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output)
|
||||
output_get_boolean_property (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output, const char *propname)
|
||||
{
|
||||
gboolean value;
|
||||
Atom atom, actual_type;
|
||||
@@ -148,9 +150,9 @@ output_get_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
unsigned long nitems, bytes_after;
|
||||
unsigned char *buffer;
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, "_MUTTER_PRESENTATION_OUTPUT", False);
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, propname, False);
|
||||
XRRGetOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->output_id,
|
||||
(XID)output->winsys_id,
|
||||
atom,
|
||||
0, G_MAXLONG, False, False, XA_CARDINAL,
|
||||
&actual_type, &actual_format,
|
||||
@@ -166,6 +168,13 @@ output_get_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
return value;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
output_get_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output)
|
||||
{
|
||||
return output_get_boolean_property (manager_xrandr, output, "_MUTTER_PRESENTATION_OUTPUT");
|
||||
}
|
||||
|
||||
static int
|
||||
normalize_backlight (MetaOutput *output,
|
||||
int hw_value)
|
||||
@@ -186,7 +195,7 @@ output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
|
||||
XRRGetOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->output_id,
|
||||
(XID)output->winsys_id,
|
||||
atom,
|
||||
0, G_MAXLONG, False, False, XA_INTEGER,
|
||||
&actual_type, &actual_format,
|
||||
@@ -207,30 +216,34 @@ output_get_backlight_limits_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output)
|
||||
{
|
||||
Atom atom;
|
||||
XRRPropertyInfo *info;
|
||||
xcb_connection_t *xcb_conn;
|
||||
xcb_randr_query_output_property_reply_t *reply;
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
|
||||
info = XRRQueryOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->output_id,
|
||||
atom);
|
||||
|
||||
if (info == NULL)
|
||||
{
|
||||
meta_verbose ("could not get output property for %s\n", output->name);
|
||||
return;
|
||||
}
|
||||
xcb_conn = XGetXCBConnection (manager_xrandr->xdisplay);
|
||||
reply = xcb_randr_query_output_property_reply (xcb_conn,
|
||||
xcb_randr_query_output_property (xcb_conn,
|
||||
(xcb_randr_output_t) output->winsys_id,
|
||||
(xcb_atom_t) atom),
|
||||
NULL);
|
||||
|
||||
if (!info->range || info->num_values != 2)
|
||||
/* This can happen on systems without backlights. */
|
||||
if (reply == NULL)
|
||||
return;
|
||||
|
||||
if (!reply->range || reply->length != 2)
|
||||
{
|
||||
meta_verbose ("backlight %s was not range\n", output->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
output->backlight_min = info->values[0];
|
||||
output->backlight_max = info->values[1];
|
||||
int32_t *values = xcb_randr_query_output_property_valid_values (reply);
|
||||
output->backlight_min = values[0];
|
||||
output->backlight_max = values[1];
|
||||
|
||||
out:
|
||||
XFree (info);
|
||||
free (reply);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -278,25 +291,25 @@ get_edid_property (Display *dpy,
|
||||
|
||||
static GBytes *
|
||||
read_output_edid (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
XID output_id)
|
||||
XID winsys_id)
|
||||
{
|
||||
Atom edid_atom;
|
||||
guint8 *result;
|
||||
gsize len;
|
||||
|
||||
edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID", FALSE);
|
||||
result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len);
|
||||
result = get_edid_property (manager_xrandr->xdisplay, winsys_id, edid_atom, &len);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID_DATA", FALSE);
|
||||
result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len);
|
||||
result = get_edid_property (manager_xrandr->xdisplay, winsys_id, edid_atom, &len);
|
||||
}
|
||||
|
||||
if (!result)
|
||||
{
|
||||
edid_atom = XInternAtom (manager_xrandr->xdisplay, "XFree86_DDC_EDID1_RAWDATA", FALSE);
|
||||
result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len);
|
||||
result = get_edid_property (manager_xrandr->xdisplay, winsys_id, edid_atom, &len);
|
||||
}
|
||||
|
||||
if (result)
|
||||
@@ -312,25 +325,25 @@ read_output_edid (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
|
||||
static gboolean
|
||||
output_get_hotplug_mode_update (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
XID output_id)
|
||||
MetaOutput *output)
|
||||
{
|
||||
Atom atom;
|
||||
XRRPropertyInfo *info;
|
||||
gboolean result = FALSE;
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, "hotplug_mode_update", False);
|
||||
info = XRRQueryOutputProperty (manager_xrandr->xdisplay, output_id,
|
||||
atom);
|
||||
|
||||
if (info)
|
||||
{
|
||||
result = TRUE;
|
||||
XFree (info);
|
||||
}
|
||||
|
||||
return result;
|
||||
return output_get_boolean_property (manager_xrandr, output, "hotplug_mode_update");
|
||||
}
|
||||
|
||||
static char *
|
||||
get_xmode_name (XRRModeInfo *xmode)
|
||||
{
|
||||
int width = xmode->width;
|
||||
int height = xmode->height;
|
||||
|
||||
if (xmode->hSkew != 0)
|
||||
{
|
||||
width += 2 * (xmode->hSkew >> 8);
|
||||
height += 2 * (xmode->hSkew & 0xff);
|
||||
}
|
||||
|
||||
return g_strdup_printf ("%dx%d", width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
||||
@@ -417,6 +430,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
||||
mode->height = xmode->height;
|
||||
mode->refresh_rate = (xmode->dotClock /
|
||||
((float)xmode->hTotal * xmode->vTotal));
|
||||
mode->name = get_xmode_name (xmode);
|
||||
}
|
||||
|
||||
for (i = 0; i < (unsigned)resources->ncrtc; i++)
|
||||
@@ -434,8 +448,8 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
||||
meta_crtc->rect.width = crtc->width;
|
||||
meta_crtc->rect.height = crtc->height;
|
||||
meta_crtc->is_dirty = FALSE;
|
||||
meta_crtc->transform = wl_transform_from_xrandr (crtc->rotation);
|
||||
meta_crtc->all_transforms = wl_transform_from_xrandr_all (crtc->rotations);
|
||||
meta_crtc->transform = meta_monitor_transform_from_xrandr (crtc->rotation);
|
||||
meta_crtc->all_transforms = meta_monitor_transform_from_xrandr_all (crtc->rotations);
|
||||
|
||||
for (j = 0; j < (unsigned)resources->nmode; j++)
|
||||
{
|
||||
@@ -467,10 +481,10 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
||||
GBytes *edid;
|
||||
MonitorInfo *parsed_edid;
|
||||
|
||||
meta_output->output_id = resources->outputs[i];
|
||||
meta_output->winsys_id = resources->outputs[i];
|
||||
meta_output->name = g_strdup (output->name);
|
||||
|
||||
edid = read_output_edid (manager_xrandr, meta_output->output_id);
|
||||
edid = read_output_edid (manager_xrandr, meta_output->winsys_id);
|
||||
if (edid)
|
||||
{
|
||||
gsize len;
|
||||
@@ -503,8 +517,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
||||
meta_output->width_mm = output->mm_width;
|
||||
meta_output->height_mm = output->mm_height;
|
||||
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
|
||||
meta_output->hotplug_mode_update =
|
||||
output_get_hotplug_mode_update (manager_xrandr, meta_output->output_id);
|
||||
meta_output->hotplug_mode_update = output_get_hotplug_mode_update (manager_xrandr, meta_output);
|
||||
|
||||
meta_output->n_modes = output->nmode;
|
||||
meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
|
||||
@@ -556,7 +569,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
||||
meta_output->possible_clones[j] = GINT_TO_POINTER (output->clones[j]);
|
||||
}
|
||||
|
||||
meta_output->is_primary = ((XID)meta_output->output_id == primary_output);
|
||||
meta_output->is_primary = ((XID)meta_output->winsys_id == primary_output);
|
||||
meta_output->is_presentation = output_get_presentation_xrandr (manager_xrandr, meta_output);
|
||||
output_get_backlight_limits_xrandr (manager_xrandr, meta_output);
|
||||
|
||||
@@ -589,7 +602,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
||||
|
||||
for (k = 0; k < manager->n_outputs; k++)
|
||||
{
|
||||
if (clone == (XID)manager->outputs[k].output_id)
|
||||
if (clone == (XID)manager->outputs[k].winsys_id)
|
||||
{
|
||||
meta_output->possible_clones[j] = &manager->outputs[k];
|
||||
break;
|
||||
@@ -605,7 +618,7 @@ meta_monitor_manager_xrandr_read_edid (MetaMonitorManager *manager,
|
||||
{
|
||||
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
|
||||
|
||||
return read_output_edid (manager_xrandr, output->output_id);
|
||||
return read_output_edid (manager_xrandr, output->winsys_id);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -637,25 +650,25 @@ meta_monitor_manager_xrandr_set_power_save_mode (MetaMonitorManager *manager,
|
||||
}
|
||||
|
||||
static Rotation
|
||||
wl_transform_to_xrandr (enum wl_output_transform transform)
|
||||
meta_monitor_transform_to_xrandr (MetaMonitorTransform transform)
|
||||
{
|
||||
switch (transform)
|
||||
{
|
||||
case WL_OUTPUT_TRANSFORM_NORMAL:
|
||||
case META_MONITOR_TRANSFORM_NORMAL:
|
||||
return RR_Rotate_0;
|
||||
case WL_OUTPUT_TRANSFORM_90:
|
||||
case META_MONITOR_TRANSFORM_90:
|
||||
return RR_Rotate_90;
|
||||
case WL_OUTPUT_TRANSFORM_180:
|
||||
case META_MONITOR_TRANSFORM_180:
|
||||
return RR_Rotate_180;
|
||||
case WL_OUTPUT_TRANSFORM_270:
|
||||
case META_MONITOR_TRANSFORM_270:
|
||||
return RR_Rotate_270;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED:
|
||||
case META_MONITOR_TRANSFORM_FLIPPED:
|
||||
return RR_Reflect_X | RR_Rotate_0;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
|
||||
case META_MONITOR_TRANSFORM_FLIPPED_90:
|
||||
return RR_Reflect_X | RR_Rotate_90;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
|
||||
case META_MONITOR_TRANSFORM_FLIPPED_180:
|
||||
return RR_Reflect_X | RR_Rotate_180;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
|
||||
case META_MONITOR_TRANSFORM_FLIPPED_270:
|
||||
return RR_Reflect_X | RR_Rotate_270;
|
||||
}
|
||||
|
||||
@@ -672,7 +685,7 @@ output_set_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, "_MUTTER_PRESENTATION_OUTPUT", False);
|
||||
XRRChangeOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->output_id,
|
||||
(XID)output->winsys_id,
|
||||
atom,
|
||||
XA_CARDINAL, 32, PropModeReplace,
|
||||
(unsigned char*) &value, 1);
|
||||
@@ -828,7 +841,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
output->crtc = crtc;
|
||||
new_controlled_mask |= 1UL << j;
|
||||
|
||||
outputs[j] = output->output_id;
|
||||
outputs[j] = output->winsys_id;
|
||||
}
|
||||
|
||||
if (crtc->current_mode == mode &&
|
||||
@@ -847,7 +860,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
manager_xrandr->time,
|
||||
crtc_info->x, crtc_info->y,
|
||||
(XID)mode->mode_id,
|
||||
wl_transform_to_xrandr (crtc_info->transform),
|
||||
meta_monitor_transform_to_xrandr (crtc_info->transform),
|
||||
outputs, n_outputs);
|
||||
|
||||
if (ok != Success)
|
||||
@@ -891,7 +904,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
{
|
||||
XRRSetOutputPrimary (manager_xrandr->xdisplay,
|
||||
DefaultRootWindow (manager_xrandr->xdisplay),
|
||||
(XID)output_info->output->output_id);
|
||||
(XID)output_info->output->winsys_id);
|
||||
}
|
||||
|
||||
output_set_presentation_xrandr (manager_xrandr,
|
||||
@@ -934,7 +947,7 @@ meta_monitor_manager_xrandr_change_backlight (MetaMonitorManager *manager,
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
|
||||
XRRChangeOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->output_id,
|
||||
(XID)output->winsys_id,
|
||||
atom,
|
||||
XA_INTEGER, 32, PropModeReplace,
|
||||
(unsigned char *) &hw_value, 1);
|
||||
|
@@ -22,48 +22,6 @@
|
||||
#include <clutter/clutter.h>
|
||||
#include "cogl-utils.h"
|
||||
|
||||
/**
|
||||
* meta_create_color_texture_4ub:
|
||||
* @red: red component
|
||||
* @green: green component
|
||||
* @blue: blue component
|
||||
* @alpha: alpha component
|
||||
* @flags: Optional flags for the texture, or %COGL_TEXTURE_NONE;
|
||||
* %COGL_TEXTURE_NO_SLICING is useful if the texture will be
|
||||
* repeated to create a constant color fill, since hardware
|
||||
* repeat can't be used for a sliced texture.
|
||||
*
|
||||
* Creates a texture that is a single pixel with the specified
|
||||
* unpremultiplied color components.
|
||||
*
|
||||
* Return value: (transfer full): a newly created Cogl texture
|
||||
*/
|
||||
CoglTexture *
|
||||
meta_create_color_texture_4ub (guint8 red,
|
||||
guint8 green,
|
||||
guint8 blue,
|
||||
guint8 alpha,
|
||||
CoglTextureFlags flags)
|
||||
{
|
||||
CoglColor color;
|
||||
guint8 pixel[4];
|
||||
|
||||
cogl_color_init_from_4ub (&color, red, green, blue, alpha);
|
||||
cogl_color_premultiply (&color);
|
||||
|
||||
pixel[0] = cogl_color_get_red_byte (&color);
|
||||
pixel[1] = cogl_color_get_green_byte (&color);
|
||||
pixel[2] = cogl_color_get_blue_byte (&color);
|
||||
pixel[3] = cogl_color_get_alpha_byte (&color);
|
||||
|
||||
return cogl_texture_new_from_data (1, 1,
|
||||
flags,
|
||||
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
4, pixel);
|
||||
}
|
||||
|
||||
|
||||
/* Based on gnome-shell/src/st/st-private.c:_st_create_texture_material.c */
|
||||
|
||||
/**
|
||||
|
@@ -23,11 +23,6 @@
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
CoglTexture * meta_create_color_texture_4ub (guint8 red,
|
||||
guint8 green,
|
||||
guint8 blue,
|
||||
guint8 alpha,
|
||||
CoglTextureFlags flags);
|
||||
CoglPipeline * meta_create_texture_pipeline (CoglTexture *texture);
|
||||
|
||||
#endif /* __META_COGL_UTILS_H__ */
|
||||
|
@@ -15,8 +15,7 @@ struct _MetaCompositor
|
||||
{
|
||||
MetaDisplay *display;
|
||||
|
||||
guint pre_paint_func_id;
|
||||
guint post_paint_func_id;
|
||||
guint repaint_func_id;
|
||||
|
||||
gint64 server_time_query_time;
|
||||
gint64 server_time_offset;
|
||||
@@ -41,7 +40,6 @@ struct _MetaCompositor
|
||||
MetaPluginManager *plugin_mgr;
|
||||
|
||||
gboolean frame_has_updated_xsurfaces;
|
||||
gboolean have_x11_sync_object;
|
||||
};
|
||||
|
||||
/* Wait 2ms after vblank before starting to draw next frame */
|
||||
|
@@ -67,41 +67,29 @@
|
||||
#include <meta/compositor-mutter.h>
|
||||
#include <meta/prefs.h>
|
||||
#include <meta/main.h>
|
||||
#include <meta/meta-backend.h>
|
||||
#include <meta/meta-background-actor.h>
|
||||
#include <meta/meta-background-group.h>
|
||||
#include <meta/meta-shadow-factory.h>
|
||||
#include "meta-window-actor-private.h"
|
||||
#include "meta-window-group.h"
|
||||
#include "meta-stage.h"
|
||||
#include "window-private.h" /* to check window->hidden */
|
||||
#include "display-private.h" /* for meta_display_lookup_x_window() */
|
||||
#include "display-private.h" /* for meta_display_lookup_x_window() and meta_display_cancel_touch() */
|
||||
#include "util-private.h"
|
||||
#include "frame.h"
|
||||
#include <X11/extensions/shape.h>
|
||||
#include <X11/extensions/Xcomposite.h>
|
||||
#include "meta-sync-ring.h"
|
||||
|
||||
#include "backends/meta-backend.h"
|
||||
#include "backends/x11/meta-backend-x11.h"
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
is_modal (MetaDisplay *display)
|
||||
{
|
||||
return display->grab_op == META_GRAB_OP_COMPOSITOR;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
composite_at_least_version (MetaDisplay *display, int maj, int min)
|
||||
{
|
||||
static int major = -1;
|
||||
static int minor = -1;
|
||||
|
||||
if (major == -1)
|
||||
meta_display_get_compositor_version (display, &major, &minor);
|
||||
|
||||
return (major > maj || (major == maj && minor >= min));
|
||||
return display->event_route == META_EVENT_ROUTE_COMPOSITOR_GRAB;
|
||||
}
|
||||
|
||||
static void sync_actor_stacking (MetaCompositor *compositor);
|
||||
@@ -137,11 +125,7 @@ meta_switch_workspace_completed (MetaCompositor *compositor)
|
||||
void
|
||||
meta_compositor_destroy (MetaCompositor *compositor)
|
||||
{
|
||||
clutter_threads_remove_repaint_func (compositor->pre_paint_func_id);
|
||||
clutter_threads_remove_repaint_func (compositor->post_paint_func_id);
|
||||
|
||||
if (compositor->have_x11_sync_object)
|
||||
meta_sync_ring_destroy ();
|
||||
clutter_threads_remove_repaint_func (compositor->repaint_func_id);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -155,33 +139,6 @@ process_damage (MetaCompositor *compositor,
|
||||
compositor->frame_has_updated_xsurfaces = TRUE;
|
||||
}
|
||||
|
||||
static Window
|
||||
get_output_window (MetaCompositor *compositor)
|
||||
{
|
||||
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
|
||||
Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
|
||||
Window output;
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||
|
||||
output = XCompositeGetOverlayWindow (xdisplay, DefaultRootWindow (xdisplay));
|
||||
|
||||
meta_core_add_old_event_mask (xdisplay, output, &mask);
|
||||
|
||||
XISetMask (mask.mask, XI_KeyPress);
|
||||
XISetMask (mask.mask, XI_KeyRelease);
|
||||
XISetMask (mask.mask, XI_ButtonPress);
|
||||
XISetMask (mask.mask, XI_ButtonRelease);
|
||||
XISetMask (mask.mask, XI_Enter);
|
||||
XISetMask (mask.mask, XI_Leave);
|
||||
XISetMask (mask.mask, XI_FocusIn);
|
||||
XISetMask (mask.mask, XI_FocusOut);
|
||||
XISetMask (mask.mask, XI_Motion);
|
||||
XISelectEvents (xdisplay, output, &mask, 1);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/* compat helper */
|
||||
static MetaCompositor *
|
||||
get_compositor_for_screen (MetaScreen *screen)
|
||||
@@ -388,12 +345,20 @@ meta_begin_modal_for_plugin (MetaCompositor *compositor,
|
||||
return FALSE;
|
||||
|
||||
display->grab_op = META_GRAB_OP_COMPOSITOR;
|
||||
display->event_route = META_EVENT_ROUTE_COMPOSITOR_GRAB;
|
||||
display->grab_window = NULL;
|
||||
display->grab_have_pointer = TRUE;
|
||||
display->grab_have_keyboard = TRUE;
|
||||
|
||||
g_signal_emit_by_name (display, "grab-op-begin",
|
||||
meta_plugin_get_screen (plugin),
|
||||
display->grab_window, display->grab_op);
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
meta_display_sync_wayland_input_focus (display);
|
||||
{
|
||||
meta_display_sync_wayland_input_focus (display);
|
||||
meta_display_cancel_touch (display);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -408,7 +373,12 @@ meta_end_modal_for_plugin (MetaCompositor *compositor,
|
||||
|
||||
g_return_if_fail (is_modal (display));
|
||||
|
||||
g_signal_emit_by_name (display, "grab-op-end",
|
||||
meta_plugin_get_screen (plugin),
|
||||
display->grab_window, display->grab_op);
|
||||
|
||||
display->grab_op = META_GRAB_OP_NONE;
|
||||
display->event_route = META_EVENT_ROUTE_NORMAL;
|
||||
display->grab_window = NULL;
|
||||
display->grab_have_pointer = FALSE;
|
||||
display->grab_have_keyboard = FALSE;
|
||||
@@ -430,8 +400,10 @@ after_stage_paint (ClutterStage *stage,
|
||||
for (l = compositor->windows; l; l = l->next)
|
||||
meta_window_actor_post_paint (l->data);
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
if (meta_is_wayland_compositor ())
|
||||
meta_wayland_compositor_paint_finished (meta_wayland_compositor_get_default ());
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -483,62 +455,24 @@ meta_compositor_manage (MetaCompositor *compositor)
|
||||
MetaDisplay *display = compositor->display;
|
||||
Display *xdisplay = display->xdisplay;
|
||||
MetaScreen *screen = display->screen;
|
||||
Window xwin = 0;
|
||||
gint width, height;
|
||||
|
||||
meta_screen_set_cm_selection (display->screen);
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
MetaWaylandCompositor *wayland_compositor = meta_wayland_compositor_get_default ();
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
compositor->stage = meta_backend_get_stage (backend);
|
||||
}
|
||||
|
||||
compositor->stage = meta_stage_new ();
|
||||
clutter_actor_show (compositor->stage);
|
||||
|
||||
wayland_compositor->stage = compositor->stage;
|
||||
|
||||
meta_screen_get_size (screen, &width, &height);
|
||||
clutter_actor_set_size (compositor->stage, width, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
compositor->stage = clutter_stage_new ();
|
||||
|
||||
meta_screen_get_size (screen, &width, &height);
|
||||
clutter_actor_realize (compositor->stage);
|
||||
|
||||
xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (compositor->stage));
|
||||
|
||||
XResizeWindow (xdisplay, xwin, width, height);
|
||||
|
||||
{
|
||||
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
|
||||
Display *backend_xdisplay = meta_backend_x11_get_xdisplay (backend);
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||
|
||||
meta_core_add_old_event_mask (backend_xdisplay, xwin, &mask);
|
||||
|
||||
XISetMask (mask.mask, XI_KeyPress);
|
||||
XISetMask (mask.mask, XI_KeyRelease);
|
||||
XISetMask (mask.mask, XI_ButtonPress);
|
||||
XISetMask (mask.mask, XI_ButtonRelease);
|
||||
XISetMask (mask.mask, XI_Enter);
|
||||
XISetMask (mask.mask, XI_Leave);
|
||||
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);
|
||||
XISelectEvents (backend_xdisplay, xwin, &mask, 1);
|
||||
}
|
||||
}
|
||||
|
||||
clutter_stage_set_paint_callback (CLUTTER_STAGE (compositor->stage),
|
||||
after_stage_paint,
|
||||
compositor,
|
||||
NULL);
|
||||
/* We use connect_after() here to accomodate code in GNOME Shell that,
|
||||
* when benchmarking drawing performance, connects to ::after-paint
|
||||
* and calls glFinish(). The timing information from that will be
|
||||
* more accurate if we hold off until that completes before we signal
|
||||
* apps to begin drawing the next frame. If there are no other
|
||||
* connections to ::after-paint, connect() vs. connect_after() doesn't
|
||||
* matter.
|
||||
*/
|
||||
g_signal_connect_after (CLUTTER_STAGE (compositor->stage), "after-paint",
|
||||
G_CALLBACK (after_stage_paint), compositor);
|
||||
|
||||
clutter_stage_set_sync_delay (CLUTTER_STAGE (compositor->stage), META_SYNC_DELAY);
|
||||
|
||||
@@ -557,7 +491,12 @@ meta_compositor_manage (MetaCompositor *compositor)
|
||||
}
|
||||
else
|
||||
{
|
||||
compositor->output = get_output_window (compositor);
|
||||
Window xwin;
|
||||
|
||||
compositor->output = screen->composite_overlay_window;
|
||||
|
||||
xwin = meta_backend_x11_get_xwindow (META_BACKEND_X11 (meta_get_backend ()));
|
||||
|
||||
XReparentWindow (xdisplay, xwin, compositor->output, 0, 0);
|
||||
|
||||
meta_empty_stage_input_region (screen);
|
||||
@@ -576,8 +515,6 @@ meta_compositor_manage (MetaCompositor *compositor)
|
||||
* contents until we show the stage.
|
||||
*/
|
||||
XMapWindow (xdisplay, compositor->output);
|
||||
|
||||
compositor->have_x11_sync_object = meta_sync_ring_init (display);
|
||||
}
|
||||
|
||||
redirect_windows (display->screen);
|
||||
@@ -700,12 +637,11 @@ meta_compositor_remove_window (MetaCompositor *compositor,
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_set_updates_frozen (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
gboolean updates_frozen)
|
||||
meta_compositor_sync_updates_frozen (MetaCompositor *compositor,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
meta_window_actor_set_updates_frozen (window_actor, updates_frozen);
|
||||
meta_window_actor_sync_updates_frozen (window_actor);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -765,9 +701,6 @@ meta_compositor_process_event (MetaCompositor *compositor,
|
||||
XEvent *event,
|
||||
MetaWindow *window)
|
||||
{
|
||||
if (meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event))
|
||||
return TRUE;
|
||||
|
||||
if (!meta_is_wayland_compositor () &&
|
||||
event->type == meta_display_get_damage_event_base (compositor->display) + XDamageNotify)
|
||||
{
|
||||
@@ -789,10 +722,6 @@ meta_compositor_process_event (MetaCompositor *compositor,
|
||||
if (!meta_is_wayland_compositor () && event->type == MapNotify)
|
||||
clutter_x11_handle_event (event);
|
||||
|
||||
if (compositor->have_x11_sync_object &&
|
||||
event->type == (compositor->display->xsync_event_base + XSyncAlarmNotify))
|
||||
meta_sync_ring_handle_event ((XSyncAlarmNotifyEvent *) event);
|
||||
|
||||
/* The above handling is basically just "observing" the events, so we return
|
||||
* FALSE to indicate that the event should not be filtered out; if we have
|
||||
* GTK+ windows in the same process, GTK+ needs the ConfigureNotify event, for example.
|
||||
@@ -1059,43 +988,6 @@ meta_compositor_sync_window_geometry (MetaCompositor *compositor,
|
||||
meta_window_actor_sync_actor_geometry (window_actor, did_placement);
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_sync_screen_size (MetaCompositor *compositor,
|
||||
guint width,
|
||||
guint height)
|
||||
{
|
||||
MetaDisplay *display = compositor->display;
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
/* FIXME: when we support a sliced stage, this is the place to do it
|
||||
But! This is not the place to apply KMS config, here we only
|
||||
notify Clutter/Cogl/GL that the framebuffer sizes changed.
|
||||
|
||||
And because for now clutter does not do sliced, we use one
|
||||
framebuffer the size of the whole screen, and when running on
|
||||
bare metal MetaMonitorManager will do the necessary tricks to
|
||||
show the right portions on the right screens.
|
||||
*/
|
||||
|
||||
clutter_actor_set_size (compositor->stage, width, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
Display *xdisplay;
|
||||
Window xwin;
|
||||
|
||||
xdisplay = meta_display_get_xdisplay (display);
|
||||
xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (compositor->stage));
|
||||
|
||||
XResizeWindow (xdisplay, xwin, width, height);
|
||||
}
|
||||
|
||||
meta_verbose ("Changed size for stage on screen %d to %dx%d\n",
|
||||
meta_screen_get_screen_number (display->screen),
|
||||
width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
frame_callback (CoglOnscreen *onscreen,
|
||||
CoglFrameEvent event,
|
||||
@@ -1138,12 +1030,11 @@ frame_callback (CoglOnscreen *onscreen,
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_pre_paint_func (gpointer data)
|
||||
static void
|
||||
pre_paint_windows (MetaCompositor *compositor)
|
||||
{
|
||||
GList *l;
|
||||
MetaWindowActor *top_window;
|
||||
MetaCompositor *compositor = data;
|
||||
|
||||
if (compositor->onscreen == NULL)
|
||||
{
|
||||
@@ -1155,7 +1046,7 @@ meta_pre_paint_func (gpointer data)
|
||||
}
|
||||
|
||||
if (compositor->windows == NULL)
|
||||
return TRUE;
|
||||
return;
|
||||
|
||||
top_window = g_list_last (compositor->windows)->data;
|
||||
|
||||
@@ -1172,12 +1063,10 @@ meta_pre_paint_func (gpointer data)
|
||||
{
|
||||
/* We need to make sure that any X drawing that happens before
|
||||
* the XDamageSubtract() for each window above is visible to
|
||||
* subsequent GL rendering; the standardized way to do this is
|
||||
* GL_EXT_X11_sync_object. Since this isn't implemented yet in
|
||||
* mesa, we also have a path that relies on the implementation
|
||||
* of the open source drivers.
|
||||
*
|
||||
* Anything else, we just hope for the best.
|
||||
* subsequent GL rendering; the only standardized way to do this
|
||||
* is EXT_x11_sync_object, which isn't yet widely available. For
|
||||
* now, we count on details of Xorg and the open source drivers,
|
||||
* and hope for the best otherwise.
|
||||
*
|
||||
* Xorg and open source driver specifics:
|
||||
*
|
||||
@@ -1192,28 +1081,17 @@ meta_pre_paint_func (gpointer data)
|
||||
* round trip request at this point is sufficient to flush the
|
||||
* GLX buffers.
|
||||
*/
|
||||
if (compositor->have_x11_sync_object)
|
||||
compositor->have_x11_sync_object = meta_sync_ring_insert_wait ();
|
||||
else
|
||||
XSync (compositor->display->xdisplay, False);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_post_paint_func (gpointer data)
|
||||
{
|
||||
MetaCompositor *compositor = data;
|
||||
|
||||
if (compositor->frame_has_updated_xsurfaces)
|
||||
{
|
||||
if (compositor->have_x11_sync_object)
|
||||
compositor->have_x11_sync_object = meta_sync_ring_after_frame ();
|
||||
XSync (compositor->display->xdisplay, False);
|
||||
|
||||
compositor->frame_has_updated_xsurfaces = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_repaint_func (gpointer data)
|
||||
{
|
||||
MetaCompositor *compositor = data;
|
||||
pre_paint_windows (compositor);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -1237,11 +1115,7 @@ meta_compositor_new (MetaDisplay *display)
|
||||
{
|
||||
MetaCompositor *compositor;
|
||||
|
||||
if (!composite_at_least_version (display, 0, 3))
|
||||
return NULL;
|
||||
|
||||
compositor = g_new0 (MetaCompositor, 1);
|
||||
|
||||
compositor->display = display;
|
||||
|
||||
if (g_getenv("META_DISABLE_MIPMAPS"))
|
||||
@@ -1252,16 +1126,10 @@ meta_compositor_new (MetaDisplay *display)
|
||||
G_CALLBACK (on_shadow_factory_changed),
|
||||
compositor);
|
||||
|
||||
compositor->pre_paint_func_id =
|
||||
clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_PRE_PAINT,
|
||||
meta_pre_paint_func,
|
||||
compositor,
|
||||
NULL);
|
||||
compositor->post_paint_func_id =
|
||||
clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT,
|
||||
meta_post_paint_func,
|
||||
compositor,
|
||||
NULL);
|
||||
compositor->repaint_func_id = clutter_threads_add_repaint_func (meta_repaint_func,
|
||||
compositor,
|
||||
NULL);
|
||||
|
||||
return compositor;
|
||||
}
|
||||
|
||||
@@ -1426,3 +1294,12 @@ meta_compositor_show_window_menu (MetaCompositor *compositor,
|
||||
{
|
||||
meta_plugin_manager_show_window_menu (compositor->plugin_mgr, window, menu, x, y);
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_show_window_menu_for_rect (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
MetaWindowMenuType menu,
|
||||
MetaRectangle *rect)
|
||||
{
|
||||
meta_plugin_manager_show_window_menu_for_rect (compositor->plugin_mgr, window, menu, rect);
|
||||
}
|
||||
|
@@ -185,7 +185,7 @@ cullable_iface_init (MetaCullableInterface *iface)
|
||||
* meta_background_actor_get_clip_region:
|
||||
* @self: a #MetaBackgroundActor
|
||||
*
|
||||
* Return value (transfer full): a #cairo_region_t that represents the part of
|
||||
* Return value (transfer none): a #cairo_region_t that represents the part of
|
||||
* the background not obscured by other #MetaBackgroundActor or
|
||||
* #MetaWindowActor objects.
|
||||
*/
|
||||
@@ -193,24 +193,5 @@ cairo_region_t *
|
||||
meta_background_actor_get_clip_region (MetaBackgroundActor *self)
|
||||
{
|
||||
MetaBackgroundActorPrivate *priv = self->priv;
|
||||
ClutterActorBox content_box;
|
||||
cairo_rectangle_int_t content_area = { 0 };
|
||||
cairo_region_t *clip_region;
|
||||
|
||||
g_return_val_if_fail (META_IS_BACKGROUND_ACTOR (self), NULL);
|
||||
|
||||
if (!priv->clip_region)
|
||||
return NULL;
|
||||
|
||||
clutter_actor_get_content_box (CLUTTER_ACTOR (self), &content_box);
|
||||
|
||||
content_area.x = content_box.x1;
|
||||
content_area.y = content_box.y1;
|
||||
content_area.width = content_box.x2 - content_box.x1;
|
||||
content_area.height = content_box.y2 - content_box.y1;
|
||||
|
||||
clip_region = cairo_region_create_rectangle (&content_area);
|
||||
cairo_region_intersect (clip_region, priv->clip_region);
|
||||
|
||||
return clip_region;
|
||||
return priv->clip_region;
|
||||
}
|
||||
|
@@ -288,6 +288,26 @@ get_wrap_mode (MetaBackground *self)
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
texture_has_alpha (CoglTexture *texture)
|
||||
{
|
||||
if (!texture)
|
||||
return FALSE;
|
||||
|
||||
switch (cogl_texture_get_components (texture))
|
||||
{
|
||||
case COGL_TEXTURE_COMPONENTS_A:
|
||||
case COGL_TEXTURE_COMPONENTS_RGBA:
|
||||
return TRUE;
|
||||
case COGL_TEXTURE_COMPONENTS_RG:
|
||||
case COGL_TEXTURE_COMPONENTS_RGB:
|
||||
case COGL_TEXTURE_COMPONENTS_DEPTH:
|
||||
return FALSE;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
static ClutterPaintNode *
|
||||
meta_background_paint_node_new (MetaBackground *self,
|
||||
ClutterActor *actor)
|
||||
@@ -296,6 +316,7 @@ meta_background_paint_node_new (MetaBackground *self,
|
||||
ClutterPaintNode *node;
|
||||
guint8 opacity;
|
||||
guint8 color_component;
|
||||
gboolean needs_blending;
|
||||
|
||||
opacity = clutter_actor_get_paint_opacity (actor);
|
||||
color_component = (guint8) (0.5 + opacity * priv->brightness);
|
||||
@@ -308,6 +329,13 @@ meta_background_paint_node_new (MetaBackground *self,
|
||||
|
||||
node = clutter_pipeline_node_new (priv->pipeline);
|
||||
|
||||
needs_blending = (opacity < 255) || (texture_has_alpha (priv->texture));
|
||||
|
||||
if (needs_blending)
|
||||
cogl_pipeline_set_blend (priv->pipeline, "RGBA = ADD (SRC_COLOR, DST_COLOR*(1-SRC_COLOR[A]))", NULL);
|
||||
else
|
||||
cogl_pipeline_set_blend (priv->pipeline, "RGBA = ADD (SRC_COLOR, 0)", NULL);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -382,8 +410,6 @@ meta_background_paint_content (ClutterContent *content,
|
||||
if (priv->texture == NULL)
|
||||
return;
|
||||
|
||||
node = meta_background_paint_node_new (self, actor);
|
||||
|
||||
clutter_actor_get_content_box (actor, &actor_box);
|
||||
|
||||
/* First figure out where on the monitor the texture is supposed to be painted.
|
||||
@@ -413,12 +439,14 @@ meta_background_paint_content (ClutterContent *content,
|
||||
clip_region = meta_background_actor_get_clip_region (META_BACKGROUND_ACTOR (actor));
|
||||
|
||||
if (clip_region != NULL)
|
||||
{
|
||||
cairo_region_intersect (paintable_region, clip_region);
|
||||
cairo_region_destroy (clip_region);
|
||||
}
|
||||
cairo_region_intersect (paintable_region, clip_region);
|
||||
}
|
||||
|
||||
if (cairo_region_is_empty (paintable_region))
|
||||
goto out;
|
||||
|
||||
node = meta_background_paint_node_new (self, actor);
|
||||
|
||||
/* Finally, split the paintable region up into distinct areas
|
||||
* and paint each area one by one
|
||||
*/
|
||||
@@ -441,10 +469,11 @@ meta_background_paint_content (ClutterContent *content,
|
||||
|
||||
clutter_paint_node_add_texture_rectangle (node, &texture_rectangle, tx1, ty1, tx2, ty2);
|
||||
}
|
||||
cairo_region_destroy (paintable_region);
|
||||
|
||||
clutter_paint_node_add_child (root, node);
|
||||
clutter_paint_node_unref (node);
|
||||
|
||||
out:
|
||||
cairo_region_destroy (paintable_region);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -498,7 +527,8 @@ set_brightness (MetaBackground *self,
|
||||
|
||||
priv->brightness = brightness;
|
||||
|
||||
if (priv->effects & META_BACKGROUND_EFFECTS_VIGNETTE)
|
||||
if (clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL) &&
|
||||
priv->effects & META_BACKGROUND_EFFECTS_VIGNETTE)
|
||||
{
|
||||
ensure_pipeline (self);
|
||||
cogl_pipeline_set_uniform_1f (priv->pipeline,
|
||||
@@ -506,6 +536,14 @@ set_brightness (MetaBackground *self,
|
||||
"brightness"),
|
||||
priv->brightness);
|
||||
}
|
||||
else
|
||||
{
|
||||
ensure_pipeline (self);
|
||||
CoglColor blend_color;
|
||||
cogl_color_init_from_4f (&blend_color, brightness, brightness, brightness, 1.0);
|
||||
cogl_pipeline_set_layer_combine (priv->pipeline, 1, "RGB=MODULATE(PREVIOUS, CONSTANT) A=REPLACE(PREVIOUS)", NULL);
|
||||
cogl_pipeline_set_layer_combine_constant (priv->pipeline, 1, &blend_color);
|
||||
}
|
||||
|
||||
clutter_content_invalidate (CLUTTER_CONTENT (self));
|
||||
|
||||
@@ -523,6 +561,9 @@ set_vignette_sharpness (MetaBackground *self,
|
||||
|
||||
priv->vignette_sharpness = sharpness;
|
||||
|
||||
if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
|
||||
return;
|
||||
|
||||
if (priv->effects & META_BACKGROUND_EFFECTS_VIGNETTE)
|
||||
{
|
||||
ensure_pipeline (self);
|
||||
@@ -543,6 +584,9 @@ add_vignette (MetaBackground *self)
|
||||
MetaBackgroundPrivate *priv = self->priv;
|
||||
static CoglSnippet *snippet = NULL;
|
||||
|
||||
if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
|
||||
return;
|
||||
|
||||
ensure_pipeline (self);
|
||||
|
||||
/* Cogl automatically caches pipelines with no eviction policy,
|
||||
@@ -770,6 +814,8 @@ meta_background_load_gradient (MetaBackground *self,
|
||||
ClutterColor *color,
|
||||
ClutterColor *second_color)
|
||||
{
|
||||
ClutterBackend *backend = clutter_get_default_backend ();
|
||||
CoglContext *ctx = clutter_backend_get_cogl_context (backend);
|
||||
MetaBackgroundPrivate *priv = self->priv;
|
||||
CoglTexture *texture;
|
||||
guint width, height;
|
||||
@@ -799,18 +845,17 @@ meta_background_load_gradient (MetaBackground *self,
|
||||
pixels[0] = color->red;
|
||||
pixels[1] = color->green;
|
||||
pixels[2] = color->blue;
|
||||
pixels[3] = color->alpha;
|
||||
pixels[3] = 0xFF;
|
||||
pixels[4] = second_color->red;
|
||||
pixels[5] = second_color->green;
|
||||
pixels[6] = second_color->blue;
|
||||
pixels[7] = second_color->alpha;
|
||||
pixels[7] = 0xFF;
|
||||
|
||||
texture = cogl_texture_new_from_data (width, height,
|
||||
COGL_TEXTURE_NO_SLICING,
|
||||
COGL_PIXEL_FORMAT_RGBA_8888,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
4,
|
||||
pixels);
|
||||
texture = COGL_TEXTURE (cogl_texture_2d_new_from_data (ctx, width, height,
|
||||
COGL_PIXEL_FORMAT_RGB_888,
|
||||
4,
|
||||
pixels,
|
||||
NULL));
|
||||
set_texture (self, COGL_TEXTURE (texture));
|
||||
}
|
||||
|
||||
@@ -828,10 +873,13 @@ void
|
||||
meta_background_load_color (MetaBackground *self,
|
||||
ClutterColor *color)
|
||||
{
|
||||
ClutterBackend *backend = clutter_get_default_backend ();
|
||||
CoglContext *ctx = clutter_backend_get_cogl_context (backend);
|
||||
MetaBackgroundPrivate *priv = self->priv;
|
||||
CoglTexture *texture;
|
||||
ClutterActor *stage = meta_get_stage_for_screen (priv->screen);
|
||||
ClutterColor stage_color;
|
||||
uint8_t pixels[4];
|
||||
|
||||
ensure_pipeline (self);
|
||||
|
||||
@@ -844,11 +892,16 @@ meta_background_load_color (MetaBackground *self,
|
||||
color = &stage_color;
|
||||
}
|
||||
|
||||
texture = meta_create_color_texture_4ub (color->red,
|
||||
color->green,
|
||||
color->blue,
|
||||
0xff,
|
||||
COGL_TEXTURE_NO_SLICING);
|
||||
pixels[0] = color->red;
|
||||
pixels[1] = color->green;
|
||||
pixels[2] = color->blue;
|
||||
pixels[3] = 0xFF;
|
||||
|
||||
texture = COGL_TEXTURE (cogl_texture_2d_new_from_data (ctx, 1, 1,
|
||||
COGL_PIXEL_FORMAT_RGB_888,
|
||||
4,
|
||||
pixels,
|
||||
NULL));
|
||||
set_texture (self, COGL_TEXTURE (texture));
|
||||
}
|
||||
|
||||
@@ -946,6 +999,8 @@ meta_background_load_file_finish (MetaBackground *self,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
ClutterBackend *backend = clutter_get_default_backend ();
|
||||
CoglContext *ctx = clutter_backend_get_cogl_context (backend);
|
||||
GTask *task;
|
||||
LoadFileTaskData *task_data;
|
||||
CoglTexture *texture;
|
||||
@@ -954,6 +1009,7 @@ meta_background_load_file_finish (MetaBackground *self,
|
||||
guchar *pixels;
|
||||
gboolean has_alpha;
|
||||
gboolean loaded = FALSE;
|
||||
CoglPixelFormat pixel_format;
|
||||
|
||||
g_return_val_if_fail (g_task_is_valid (result, self), FALSE);
|
||||
|
||||
@@ -972,15 +1028,13 @@ meta_background_load_file_finish (MetaBackground *self,
|
||||
pixels = gdk_pixbuf_get_pixels (pixbuf);
|
||||
has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
|
||||
|
||||
texture = cogl_texture_new_from_data (width,
|
||||
height,
|
||||
COGL_TEXTURE_NO_ATLAS,
|
||||
has_alpha ?
|
||||
COGL_PIXEL_FORMAT_RGBA_8888 :
|
||||
COGL_PIXEL_FORMAT_RGB_888,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
row_stride,
|
||||
pixels);
|
||||
pixel_format = has_alpha ? COGL_PIXEL_FORMAT_RGBA_8888 : COGL_PIXEL_FORMAT_RGB_888;
|
||||
|
||||
texture = COGL_TEXTURE (cogl_texture_2d_new_from_data (ctx, width, height,
|
||||
pixel_format,
|
||||
row_stride,
|
||||
pixels,
|
||||
NULL));
|
||||
|
||||
if (texture == NULL)
|
||||
{
|
||||
|
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
#include <meta/meta-plugin.h>
|
||||
#include <meta/meta-version.h>
|
||||
#include "meta-module.h"
|
||||
|
||||
#include <gmodule.h>
|
||||
@@ -68,7 +69,7 @@ meta_module_load (GTypeModule *gmodule)
|
||||
(gpointer *)(void *)®ister_type) &&
|
||||
info && register_type)
|
||||
{
|
||||
if (info->version_api != MUTTER_PLUGIN_API_VERSION)
|
||||
if (info->version_api != META_PLUGIN_API_VERSION)
|
||||
g_warning ("Plugin API mismatch for [%s]", priv->path);
|
||||
else
|
||||
{
|
||||
|
@@ -170,6 +170,15 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
|
||||
klass->minimize (plugin, actor);
|
||||
}
|
||||
break;
|
||||
case META_PLUGIN_UNMINIMIZE:
|
||||
if (klass->unminimize)
|
||||
{
|
||||
retval = TRUE;
|
||||
meta_plugin_manager_kill_window_effects (plugin_mgr,
|
||||
actor);
|
||||
klass->unminimize (plugin, actor);
|
||||
}
|
||||
break;
|
||||
case META_PLUGIN_MAP:
|
||||
if (klass->map)
|
||||
{
|
||||
@@ -374,3 +383,20 @@ meta_plugin_manager_show_window_menu (MetaPluginManager *plugin_mgr,
|
||||
if (klass->show_window_menu)
|
||||
klass->show_window_menu (plugin, window, menu, x, y);
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_manager_show_window_menu_for_rect (MetaPluginManager *plugin_mgr,
|
||||
MetaWindow *window,
|
||||
MetaWindowMenuType menu,
|
||||
MetaRectangle *rect)
|
||||
{
|
||||
MetaPlugin *plugin = plugin_mgr->plugin;
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
MetaDisplay *display = plugin_mgr->compositor->display;
|
||||
|
||||
if (display->display_opening)
|
||||
return;
|
||||
|
||||
if (klass->show_window_menu_for_rect)
|
||||
klass->show_window_menu_for_rect (plugin, window, menu, rect);
|
||||
}
|
||||
|
@@ -35,6 +35,7 @@
|
||||
#define META_PLUGIN_MAP (1<<3)
|
||||
#define META_PLUGIN_DESTROY (1<<4)
|
||||
#define META_PLUGIN_SWITCH_WORKSPACE (1<<5)
|
||||
#define META_PLUGIN_UNMINIMIZE (1<<6)
|
||||
|
||||
#define META_PLUGIN_ALL_EFFECTS (~0)
|
||||
|
||||
@@ -87,5 +88,10 @@ void meta_plugin_manager_show_window_menu (MetaPluginManager *mgr,
|
||||
int x,
|
||||
int y);
|
||||
|
||||
void meta_plugin_manager_show_window_menu_for_rect (MetaPluginManager *mgr,
|
||||
MetaWindow *window,
|
||||
MetaWindowMenuType menu,
|
||||
MetaRectangle *rect);
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -110,6 +110,13 @@ meta_plugin_minimize_completed (MetaPlugin *plugin,
|
||||
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_MINIMIZE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_unminimize_completed (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor)
|
||||
{
|
||||
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_UNMINIMIZE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_maximize_completed (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor)
|
||||
|
@@ -121,17 +121,17 @@ static guint signals[LAST_SIGNAL] = { 0 };
|
||||
/* The first element in this array also defines the default parameters
|
||||
* for newly created classes */
|
||||
MetaShadowClassInfo default_shadow_classes[] = {
|
||||
{ "normal", { 6, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
|
||||
{ "dialog", { 6, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
|
||||
{ "modal_dialog", { 6, -1, 0, 1, 128 }, { 3, -1, 0, 3, 32 } },
|
||||
{ "normal", { 3, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
|
||||
{ "dialog", { 3, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
|
||||
{ "modal_dialog", { 3, -1, 0, 1, 128 }, { 3, -1, 0, 3, 32 } },
|
||||
{ "utility", { 3, -1, 0, 1, 128 }, { 3, -1, 0, 1, 32 } },
|
||||
{ "border", { 6, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
|
||||
{ "menu", { 6, -1, 0, 3, 128 }, { 3, -1, 0, 0, 32 } },
|
||||
{ "border", { 3, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
|
||||
{ "menu", { 3, -1, 0, 3, 128 }, { 3, -1, 0, 0, 32 } },
|
||||
|
||||
{ "popup-menu", { 1, -1, 0, 1, 128 }, { 1, -1, 0, 1, 128 } },
|
||||
{ "popup-menu", { 1, 0, 0, 1, 128 }, { 1, -1, 0, 1, 128 } },
|
||||
|
||||
{ "dropdown-menu", { 1, 10, 0, 1, 128 }, { 1, 10, 0, 1, 128 } },
|
||||
{ "attached", { 1, -1, 0, 1, 128 }, { 1, -1, 0, 1, 128 } }
|
||||
{ "attached", { 1, 0, 0, 1, 128 }, { 1, -1, 0, 1, 128 } }
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaShadowFactory, meta_shadow_factory, G_TYPE_OBJECT);
|
||||
@@ -496,7 +496,12 @@ get_box_filter_size (int radius)
|
||||
static int
|
||||
get_shadow_spread (int radius)
|
||||
{
|
||||
int d = get_box_filter_size (radius);
|
||||
int d;
|
||||
|
||||
if (radius == 0)
|
||||
return 0;
|
||||
|
||||
d = get_box_filter_size (radius);
|
||||
|
||||
if (d % 2 == 1)
|
||||
return 3 * (d / 2);
|
||||
@@ -536,7 +541,7 @@ blur_xspan (guchar *row,
|
||||
* be well predicted and there are enough different possibilities
|
||||
* that trying to write this as a series of unconditional loops
|
||||
* is hard and not an obvious win. The main slow down here seems
|
||||
* to be the integer division for pixel; one possible optimization
|
||||
* to be the integer division per pixel; one possible optimization
|
||||
* would be to accumulate into two 16-bit integer buffers and
|
||||
* only divide down after all three passes. (SSE parallel implementation
|
||||
* of the divide step is possible.)
|
||||
@@ -544,27 +549,27 @@ blur_xspan (guchar *row,
|
||||
for (i = x0 - d + offset; i < x1 + offset; i++)
|
||||
{
|
||||
if (i >= 0 && i < row_width)
|
||||
sum += row[i];
|
||||
sum += row[i];
|
||||
|
||||
if (i >= x0 + offset)
|
||||
{
|
||||
if (i >= d)
|
||||
sum -= row[i - d];
|
||||
{
|
||||
if (i >= d)
|
||||
sum -= row[i - d];
|
||||
|
||||
tmp_buffer[i - offset] = (sum + d / 2) / d;
|
||||
}
|
||||
tmp_buffer[i - offset] = (sum + d / 2) / d;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(row + x0, tmp_buffer + x0, x1 - x0);
|
||||
memcpy (row + x0, tmp_buffer + x0, x1 - x0);
|
||||
}
|
||||
|
||||
static void
|
||||
blur_rows (cairo_region_t *convolve_region,
|
||||
int x_offset,
|
||||
int y_offset,
|
||||
guchar *buffer,
|
||||
int buffer_width,
|
||||
int buffer_height,
|
||||
guchar *buffer,
|
||||
int buffer_width,
|
||||
int buffer_height,
|
||||
int d)
|
||||
{
|
||||
int i, j;
|
||||
@@ -581,30 +586,30 @@ blur_rows (cairo_region_t *convolve_region,
|
||||
cairo_region_get_rectangle (convolve_region, i, &rect);
|
||||
|
||||
for (j = y_offset + rect.y; j < y_offset + rect.y + rect.height; j++)
|
||||
{
|
||||
guchar *row = buffer + j * buffer_width;
|
||||
int x0 = x_offset + rect.x;
|
||||
int x1 = x0 + rect.width;
|
||||
{
|
||||
guchar *row = buffer + j * buffer_width;
|
||||
int x0 = x_offset + rect.x;
|
||||
int x1 = x0 + rect.width;
|
||||
|
||||
/* We want to produce a symmetric blur that spreads a pixel
|
||||
* equally far to the left and right. If d is odd that happens
|
||||
* naturally, but for d even, we approximate by using a blur
|
||||
* on either side and then a centered blur of size d + 1.
|
||||
* (techique also from the SVG specification)
|
||||
* (technique also from the SVG specification)
|
||||
*/
|
||||
if (d % 2 == 1)
|
||||
{
|
||||
blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 0);
|
||||
blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 0);
|
||||
blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 1);
|
||||
blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, -1);
|
||||
blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d + 1, 0);
|
||||
}
|
||||
}
|
||||
if (d % 2 == 1)
|
||||
{
|
||||
blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 0);
|
||||
blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 0);
|
||||
blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 1);
|
||||
blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, -1);
|
||||
blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d + 1, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_free (tmp_buffer);
|
||||
@@ -629,7 +634,7 @@ fade_bytes (guchar *bytes,
|
||||
*/
|
||||
static guchar *
|
||||
flip_buffer (guchar *buffer,
|
||||
int width,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
/* Working in blocks increases cache efficiency, compared to reading
|
||||
@@ -641,33 +646,33 @@ flip_buffer (guchar *buffer,
|
||||
int i0, j0;
|
||||
|
||||
for (j0 = 0; j0 < height; j0 += BLOCK_SIZE)
|
||||
for (i0 = 0; i0 <= j0; i0 += BLOCK_SIZE)
|
||||
{
|
||||
int max_j = MIN(j0 + BLOCK_SIZE, height);
|
||||
int max_i = MIN(i0 + BLOCK_SIZE, width);
|
||||
int i, j;
|
||||
for (i0 = 0; i0 <= j0; i0 += BLOCK_SIZE)
|
||||
{
|
||||
int max_j = MIN(j0 + BLOCK_SIZE, height);
|
||||
int max_i = MIN(i0 + BLOCK_SIZE, width);
|
||||
int i, j;
|
||||
|
||||
if (i0 == j0)
|
||||
{
|
||||
for (j = j0; j < max_j; j++)
|
||||
for (i = i0; i < j; i++)
|
||||
{
|
||||
guchar tmp = buffer[j * width + i];
|
||||
buffer[j * width + i] = buffer[i * width + j];
|
||||
buffer[i * width + j] = tmp;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (j = j0; j < max_j; j++)
|
||||
for (i = i0; i < max_i; i++)
|
||||
{
|
||||
guchar tmp = buffer[j * width + i];
|
||||
buffer[j * width + i] = buffer[i * width + j];
|
||||
buffer[i * width + j] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i0 == j0)
|
||||
{
|
||||
for (j = j0; j < max_j; j++)
|
||||
for (i = i0; i < j; i++)
|
||||
{
|
||||
guchar tmp = buffer[j * width + i];
|
||||
buffer[j * width + i] = buffer[i * width + j];
|
||||
buffer[i * width + j] = tmp;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (j = j0; j < max_j; j++)
|
||||
for (i = i0; i < max_i; i++)
|
||||
{
|
||||
guchar tmp = buffer[j * width + i];
|
||||
buffer[j * width + i] = buffer[i * width + j];
|
||||
buffer[i * width + j] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
@@ -678,15 +683,15 @@ flip_buffer (guchar *buffer,
|
||||
|
||||
for (i0 = 0; i0 < width; i0 += BLOCK_SIZE)
|
||||
for (j0 = 0; j0 < height; j0 += BLOCK_SIZE)
|
||||
{
|
||||
int max_j = MIN(j0 + BLOCK_SIZE, height);
|
||||
int max_i = MIN(i0 + BLOCK_SIZE, width);
|
||||
int i, j;
|
||||
{
|
||||
int max_j = MIN(j0 + BLOCK_SIZE, height);
|
||||
int max_i = MIN(i0 + BLOCK_SIZE, width);
|
||||
int i, j;
|
||||
|
||||
for (i = i0; i < max_i; i++)
|
||||
for (j = j0; j < max_j; j++)
|
||||
new_buffer[i * height + j] = buffer[j * width + i];
|
||||
}
|
||||
new_buffer[i * height + j] = buffer[j * width + i];
|
||||
}
|
||||
|
||||
g_free (buffer);
|
||||
|
||||
@@ -699,6 +704,8 @@ static void
|
||||
make_shadow (MetaShadow *shadow,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
ClutterBackend *backend = clutter_get_default_backend ();
|
||||
CoglContext *ctx = clutter_backend_get_cogl_context (backend);
|
||||
int d = get_box_filter_size (shadow->key.radius);
|
||||
int spread = get_shadow_spread (shadow->key.radius);
|
||||
cairo_rectangle_int_t extents;
|
||||
@@ -758,7 +765,7 @@ make_shadow (MetaShadow *shadow,
|
||||
|
||||
cairo_region_get_rectangle (region, k, &rect);
|
||||
for (j = y_offset + rect.y; j < y_offset + rect.y + rect.height; j++)
|
||||
memset (buffer + buffer_width * j + x_offset + rect.x, 255, rect.width);
|
||||
memset (buffer + buffer_width * j + x_offset + rect.x, 255, rect.width);
|
||||
}
|
||||
|
||||
/* Step 2: swap rows and columns */
|
||||
@@ -788,15 +795,15 @@ make_shadow (MetaShadow *shadow,
|
||||
* in the case of top_fade >= 0. We also account for padding at the left for symmetry
|
||||
* though that doesn't currently occur.
|
||||
*/
|
||||
shadow->texture = cogl_texture_new_from_data (shadow->outer_border_left + extents.width + shadow->outer_border_right,
|
||||
shadow->outer_border_top + extents.height + shadow->outer_border_bottom,
|
||||
COGL_TEXTURE_NONE,
|
||||
COGL_PIXEL_FORMAT_A_8,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
buffer_width,
|
||||
(buffer +
|
||||
(y_offset - shadow->outer_border_top) * buffer_width +
|
||||
(x_offset - shadow->outer_border_left)));
|
||||
shadow->texture = COGL_TEXTURE (cogl_texture_2d_new_from_data (ctx,
|
||||
shadow->outer_border_left + extents.width + shadow->outer_border_right,
|
||||
shadow->outer_border_top + extents.height + shadow->outer_border_bottom,
|
||||
COGL_PIXEL_FORMAT_A_8,
|
||||
buffer_width,
|
||||
(buffer +
|
||||
(y_offset - shadow->outer_border_top) * buffer_width +
|
||||
(x_offset - shadow->outer_border_left)),
|
||||
NULL));
|
||||
|
||||
cairo_region_destroy (row_convolve_region);
|
||||
cairo_region_destroy (column_convolve_region);
|
||||
|
@@ -32,8 +32,6 @@
|
||||
ClutterActor *meta_shaped_texture_new (void);
|
||||
void meta_shaped_texture_set_texture (MetaShapedTexture *stex,
|
||||
CoglTexture *texture);
|
||||
gboolean meta_shaped_texture_get_unobscured_bounds (MetaShapedTexture *stex,
|
||||
cairo_rectangle_int_t *unobscured_bounds);
|
||||
gboolean meta_shaped_texture_is_obscured (MetaShapedTexture *self);
|
||||
|
||||
#endif
|
||||
|
@@ -28,16 +28,14 @@
|
||||
#include <config.h>
|
||||
|
||||
#include <meta/meta-shaped-texture.h>
|
||||
#include <meta/util.h>
|
||||
#include "meta-shaped-texture-private.h"
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
#include <gdk/gdk.h> /* for gdk_rectangle_intersect() */
|
||||
|
||||
#include "clutter-utils.h"
|
||||
#include "meta-texture-tower.h"
|
||||
|
||||
#include "meta-shaped-texture-private.h"
|
||||
#include "meta-window-actor-private.h"
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <cogl/cogl.h>
|
||||
#include <gdk/gdk.h> /* for gdk_rectangle_intersect() */
|
||||
#include "meta-cullable.h"
|
||||
|
||||
static void meta_shaped_texture_dispose (GObject *object);
|
||||
@@ -65,6 +63,14 @@ G_DEFINE_TYPE_WITH_CODE (MetaShapedTexture, meta_shaped_texture, CLUTTER_TYPE_AC
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_SHAPED_TEXTURE, \
|
||||
MetaShapedTexturePrivate))
|
||||
|
||||
enum {
|
||||
SIZE_CHANGED,
|
||||
|
||||
LAST_SIGNAL,
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL];
|
||||
|
||||
struct _MetaShapedTexturePrivate
|
||||
{
|
||||
MetaTextureTower *paint_tower;
|
||||
@@ -97,6 +103,13 @@ meta_shaped_texture_class_init (MetaShapedTextureClass *klass)
|
||||
actor_class->paint = meta_shaped_texture_paint;
|
||||
actor_class->get_paint_volume = meta_shaped_texture_get_paint_volume;
|
||||
|
||||
signals[SIZE_CHANGED] = g_signal_new ("size-changed",
|
||||
G_TYPE_FROM_CLASS (gobject_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
g_type_class_add_private (klass, sizeof (MetaShapedTexturePrivate));
|
||||
}
|
||||
|
||||
@@ -249,22 +262,20 @@ set_cogl_texture (MetaShapedTexture *stex,
|
||||
cogl_object_ref (cogl_tex);
|
||||
width = cogl_texture_get_width (COGL_TEXTURE (cogl_tex));
|
||||
height = cogl_texture_get_height (COGL_TEXTURE (cogl_tex));
|
||||
|
||||
if (width != priv->tex_width ||
|
||||
height != priv->tex_height)
|
||||
{
|
||||
priv->tex_width = width;
|
||||
priv->tex_height = height;
|
||||
|
||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (stex));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* size changed to 0 going to an invalid handle */
|
||||
priv->tex_width = 0;
|
||||
priv->tex_height = 0;
|
||||
width = 0;
|
||||
height = 0;
|
||||
}
|
||||
|
||||
if (priv->tex_width != width ||
|
||||
priv->tex_height != height)
|
||||
{
|
||||
priv->tex_width = width;
|
||||
priv->tex_height = height;
|
||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (stex));
|
||||
g_signal_emit (stex, signals[SIZE_CHANGED], 0);
|
||||
}
|
||||
|
||||
/* NB: We don't queue a redraw of the actor here because we don't
|
||||
@@ -285,10 +296,8 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
||||
guchar opacity;
|
||||
CoglContext *ctx;
|
||||
CoglFramebuffer *fb;
|
||||
CoglPipeline *pipeline = NULL;
|
||||
CoglTexture *paint_tex;
|
||||
ClutterActorBox alloc;
|
||||
cairo_region_t *blended_region = NULL;
|
||||
CoglPipelineFilter filter;
|
||||
|
||||
if (priv->clip_region && cairo_region_is_empty (priv->clip_region))
|
||||
@@ -326,6 +335,8 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
||||
if (tex_width == 0 || tex_height == 0) /* no contents yet */
|
||||
return;
|
||||
|
||||
cairo_rectangle_int_t tex_rect = { 0, 0, tex_width, tex_height };
|
||||
|
||||
/* Use nearest-pixel interpolation if the texture is unscaled. This
|
||||
* improves performance, especially with software rendering.
|
||||
*/
|
||||
@@ -341,7 +352,45 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
||||
opacity = clutter_actor_get_paint_opacity (actor);
|
||||
clutter_actor_get_allocation_box (actor, &alloc);
|
||||
|
||||
if (priv->opaque_region != NULL && opacity == 255)
|
||||
cairo_region_t *blended_region;
|
||||
gboolean use_opaque_region = (priv->opaque_region != NULL && opacity == 255);
|
||||
|
||||
if (use_opaque_region)
|
||||
{
|
||||
if (priv->clip_region != NULL)
|
||||
blended_region = cairo_region_copy (priv->clip_region);
|
||||
else
|
||||
blended_region = cairo_region_create_rectangle (&tex_rect);
|
||||
|
||||
cairo_region_subtract (blended_region, priv->opaque_region);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (priv->clip_region != NULL)
|
||||
blended_region = cairo_region_reference (priv->clip_region);
|
||||
else
|
||||
blended_region = NULL;
|
||||
}
|
||||
|
||||
/* Limit to how many separate rectangles we'll draw; beyond this just
|
||||
* fall back and draw the whole thing */
|
||||
#define MAX_RECTS 16
|
||||
|
||||
if (blended_region != NULL)
|
||||
{
|
||||
int n_rects = cairo_region_num_rectangles (blended_region);
|
||||
if (n_rects > MAX_RECTS)
|
||||
{
|
||||
/* Fall back to taking the fully blended path. */
|
||||
use_opaque_region = FALSE;
|
||||
|
||||
cairo_region_destroy (blended_region);
|
||||
blended_region = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* First, paint the unblended parts, which are part of the opaque region. */
|
||||
if (use_opaque_region)
|
||||
{
|
||||
CoglPipeline *opaque_pipeline;
|
||||
cairo_region_t *region;
|
||||
@@ -358,103 +407,87 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
||||
region = cairo_region_reference (priv->opaque_region);
|
||||
}
|
||||
|
||||
if (cairo_region_is_empty (region))
|
||||
goto paint_blended;
|
||||
|
||||
opaque_pipeline = get_unblended_pipeline (ctx);
|
||||
cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex);
|
||||
cogl_pipeline_set_layer_filters (opaque_pipeline, 0, filter, filter);
|
||||
|
||||
n_rects = cairo_region_num_rectangles (region);
|
||||
for (i = 0; i < n_rects; i++)
|
||||
if (!cairo_region_is_empty (region))
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
cairo_region_get_rectangle (region, i, &rect);
|
||||
paint_clipped_rectangle (fb, opaque_pipeline, &rect, &alloc);
|
||||
opaque_pipeline = get_unblended_pipeline (ctx);
|
||||
cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex);
|
||||
cogl_pipeline_set_layer_filters (opaque_pipeline, 0, filter, filter);
|
||||
|
||||
n_rects = cairo_region_num_rectangles (region);
|
||||
for (i = 0; i < n_rects; i++)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
cairo_region_get_rectangle (region, i, &rect);
|
||||
paint_clipped_rectangle (fb, opaque_pipeline, &rect, &alloc);
|
||||
}
|
||||
|
||||
cogl_object_unref (opaque_pipeline);
|
||||
}
|
||||
|
||||
cogl_object_unref (opaque_pipeline);
|
||||
|
||||
if (priv->clip_region != NULL)
|
||||
{
|
||||
blended_region = cairo_region_copy (priv->clip_region);
|
||||
}
|
||||
else
|
||||
{
|
||||
cairo_rectangle_int_t rect = { 0, 0, tex_width, tex_height };
|
||||
blended_region = cairo_region_create_rectangle (&rect);
|
||||
}
|
||||
|
||||
cairo_region_subtract (blended_region, priv->opaque_region);
|
||||
|
||||
paint_blended:
|
||||
cairo_region_destroy (region);
|
||||
}
|
||||
|
||||
if (blended_region == NULL && priv->clip_region != NULL)
|
||||
blended_region = cairo_region_reference (priv->clip_region);
|
||||
/* Now, go ahead and paint the blended parts. */
|
||||
|
||||
if (blended_region != NULL && cairo_region_is_empty (blended_region))
|
||||
goto out;
|
||||
|
||||
if (priv->mask_texture == NULL)
|
||||
/* We have three cases:
|
||||
* 1) blended_region has rectangles - paint the rectangles.
|
||||
* 2) blended_region is empty - don't paint anything
|
||||
* 3) blended_region is NULL - paint fully-blended.
|
||||
*
|
||||
* 1) and 3) are the times where we have to paint stuff. This tests
|
||||
* for 1) and 3).
|
||||
*/
|
||||
if (blended_region == NULL || !cairo_region_is_empty (blended_region))
|
||||
{
|
||||
pipeline = get_unmasked_pipeline (ctx);
|
||||
}
|
||||
else
|
||||
{
|
||||
pipeline = get_masked_pipeline (ctx);
|
||||
cogl_pipeline_set_layer_texture (pipeline, 1, priv->mask_texture);
|
||||
cogl_pipeline_set_layer_filters (pipeline, 1, filter, filter);
|
||||
}
|
||||
CoglPipeline *blended_pipeline;
|
||||
|
||||
cogl_pipeline_set_layer_texture (pipeline, 0, paint_tex);
|
||||
cogl_pipeline_set_layer_filters (pipeline, 0, filter, filter);
|
||||
if (priv->mask_texture == NULL)
|
||||
{
|
||||
blended_pipeline = get_unmasked_pipeline (ctx);
|
||||
}
|
||||
else
|
||||
{
|
||||
blended_pipeline = get_masked_pipeline (ctx);
|
||||
cogl_pipeline_set_layer_texture (blended_pipeline, 1, priv->mask_texture);
|
||||
cogl_pipeline_set_layer_filters (blended_pipeline, 1, filter, filter);
|
||||
}
|
||||
|
||||
{
|
||||
CoglColor color;
|
||||
cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity);
|
||||
cogl_pipeline_set_color (pipeline, &color);
|
||||
}
|
||||
cogl_pipeline_set_layer_texture (blended_pipeline, 0, paint_tex);
|
||||
cogl_pipeline_set_layer_filters (blended_pipeline, 0, filter, filter);
|
||||
|
||||
if (blended_region != NULL)
|
||||
{
|
||||
int n_rects;
|
||||
CoglColor color;
|
||||
cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity);
|
||||
cogl_pipeline_set_color (blended_pipeline, &color);
|
||||
|
||||
/* Limit to how many separate rectangles we'll draw; beyond this just
|
||||
* fall back and draw the whole thing */
|
||||
# define MAX_RECTS 16
|
||||
|
||||
n_rects = cairo_region_num_rectangles (blended_region);
|
||||
if (n_rects <= MAX_RECTS)
|
||||
{
|
||||
if (blended_region != NULL)
|
||||
{
|
||||
/* 1) blended_region is not empty. Paint the rectangles. */
|
||||
int i;
|
||||
cairo_rectangle_int_t tex_rect = { 0, 0, tex_width, tex_height };
|
||||
int n_rects = cairo_region_num_rectangles (blended_region);
|
||||
|
||||
for (i = 0; i < n_rects; i++)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
for (i = 0; i < n_rects; i++)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
cairo_region_get_rectangle (blended_region, i, &rect);
|
||||
|
||||
cairo_region_get_rectangle (blended_region, i, &rect);
|
||||
if (!gdk_rectangle_intersect (&tex_rect, &rect, &rect))
|
||||
continue;
|
||||
|
||||
if (!gdk_rectangle_intersect (&tex_rect, &rect, &rect))
|
||||
continue;
|
||||
|
||||
paint_clipped_rectangle (fb, pipeline, &rect, &alloc);
|
||||
paint_clipped_rectangle (fb, blended_pipeline, &rect, &alloc);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 3) blended_region is NULL. Do a full paint. */
|
||||
cogl_framebuffer_draw_rectangle (fb, blended_pipeline,
|
||||
0, 0,
|
||||
alloc.x2 - alloc.x1,
|
||||
alloc.y2 - alloc.y1);
|
||||
}
|
||||
|
||||
goto out;
|
||||
}
|
||||
cogl_object_unref (blended_pipeline);
|
||||
}
|
||||
|
||||
cogl_framebuffer_draw_rectangle (fb, pipeline,
|
||||
0, 0,
|
||||
alloc.x2 - alloc.x1,
|
||||
alloc.y2 - alloc.y1);
|
||||
|
||||
out:
|
||||
if (pipeline != NULL)
|
||||
cogl_object_unref (pipeline);
|
||||
if (blended_region != NULL)
|
||||
cairo_region_destroy (blended_region);
|
||||
}
|
||||
@@ -472,7 +505,7 @@ meta_shaped_texture_get_preferred_width (ClutterActor *self,
|
||||
priv = META_SHAPED_TEXTURE (self)->priv;
|
||||
|
||||
if (min_width_p)
|
||||
*min_width_p = 0;
|
||||
*min_width_p = priv->tex_width;
|
||||
|
||||
if (natural_width_p)
|
||||
*natural_width_p = priv->tex_width;
|
||||
@@ -491,43 +524,70 @@ meta_shaped_texture_get_preferred_height (ClutterActor *self,
|
||||
priv = META_SHAPED_TEXTURE (self)->priv;
|
||||
|
||||
if (min_height_p)
|
||||
*min_height_p = 0;
|
||||
*min_height_p = priv->tex_height;
|
||||
|
||||
if (natural_height_p)
|
||||
*natural_height_p = priv->tex_height;
|
||||
}
|
||||
|
||||
static cairo_region_t *
|
||||
effective_unobscured_region (MetaShapedTexture *self)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv = self->priv;
|
||||
ClutterActor *actor;
|
||||
|
||||
/* Fail if we have any mapped clones. */
|
||||
actor = CLUTTER_ACTOR (self);
|
||||
do
|
||||
{
|
||||
if (clutter_actor_has_mapped_clones (actor))
|
||||
return NULL;
|
||||
actor = clutter_actor_get_parent (actor);
|
||||
}
|
||||
while (actor != NULL);
|
||||
|
||||
return priv->unobscured_region;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
get_unobscured_bounds (MetaShapedTexture *self,
|
||||
cairo_rectangle_int_t *unobscured_bounds)
|
||||
{
|
||||
cairo_region_t *unobscured_region = effective_unobscured_region (self);
|
||||
|
||||
if (unobscured_region)
|
||||
{
|
||||
cairo_region_get_extents (unobscured_region, unobscured_bounds);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_shaped_texture_get_paint_volume (ClutterActor *actor,
|
||||
ClutterPaintVolume *volume)
|
||||
{
|
||||
MetaShapedTexture *self = META_SHAPED_TEXTURE (actor);
|
||||
ClutterActorBox box;
|
||||
cairo_rectangle_int_t unobscured_bounds;
|
||||
|
||||
if (!clutter_paint_volume_set_from_allocation (volume, actor))
|
||||
if (!clutter_actor_has_allocation (actor))
|
||||
return FALSE;
|
||||
|
||||
if (meta_shaped_texture_get_unobscured_bounds (self, &unobscured_bounds))
|
||||
clutter_actor_get_allocation_box (actor, &box);
|
||||
|
||||
if (get_unobscured_bounds (self, &unobscured_bounds))
|
||||
{
|
||||
ClutterVertex origin;
|
||||
cairo_rectangle_int_t bounds;
|
||||
|
||||
/* I hate ClutterPaintVolume so much... */
|
||||
clutter_paint_volume_get_origin (volume, &origin);
|
||||
bounds.x = origin.x;
|
||||
bounds.y = origin.y;
|
||||
bounds.width = clutter_paint_volume_get_width (volume);
|
||||
bounds.height = clutter_paint_volume_get_height (volume);
|
||||
|
||||
gdk_rectangle_intersect (&bounds, &unobscured_bounds, &bounds);
|
||||
|
||||
origin.x = bounds.x;
|
||||
origin.y = bounds.y;
|
||||
clutter_paint_volume_set_origin (volume, &origin);
|
||||
clutter_paint_volume_set_width (volume, bounds.width);
|
||||
clutter_paint_volume_set_height (volume, bounds.height);
|
||||
box.x1 = MAX (unobscured_bounds.x, box.x1);
|
||||
box.x2 = MIN (unobscured_bounds.x + unobscured_bounds.width, box.x2);
|
||||
box.y1 = MAX (unobscured_bounds.y, box.y1);
|
||||
box.y2 = MIN (unobscured_bounds.y + unobscured_bounds.height, box.y2);
|
||||
}
|
||||
box.x2 = MAX (box.x2, box.x1);
|
||||
box.y2 = MAX (box.y2, box.y1);
|
||||
|
||||
clutter_paint_volume_union_box (volume, &box);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -573,39 +633,6 @@ meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex,
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
|
||||
}
|
||||
|
||||
static cairo_region_t *
|
||||
effective_unobscured_region (MetaShapedTexture *self)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv = self->priv;
|
||||
ClutterActor *parent = clutter_actor_get_parent (CLUTTER_ACTOR (self));
|
||||
|
||||
if (clutter_actor_has_mapped_clones (CLUTTER_ACTOR (self)))
|
||||
return NULL;
|
||||
|
||||
while (parent && !META_IS_WINDOW_ACTOR (parent))
|
||||
parent = clutter_actor_get_parent (parent);
|
||||
|
||||
if (parent && clutter_actor_has_mapped_clones (parent))
|
||||
return NULL;
|
||||
|
||||
return priv->unobscured_region;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_shaped_texture_get_unobscured_bounds (MetaShapedTexture *self,
|
||||
cairo_rectangle_int_t *unobscured_bounds)
|
||||
{
|
||||
cairo_region_t *unobscured_region = effective_unobscured_region (self);
|
||||
|
||||
if (unobscured_region)
|
||||
{
|
||||
cairo_region_get_extents (unobscured_region, unobscured_bounds);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_shaped_texture_is_obscured (MetaShapedTexture *self)
|
||||
{
|
||||
|
@@ -1,176 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "meta-stage.h"
|
||||
|
||||
#include "meta-cursor-private.h"
|
||||
#include "meta-backend.h"
|
||||
#include <meta/util.h>
|
||||
|
||||
struct _MetaStagePrivate {
|
||||
CoglPipeline *pipeline;
|
||||
gboolean should_paint_cursor;
|
||||
|
||||
MetaCursorReference *cursor;
|
||||
|
||||
MetaRectangle current_rect;
|
||||
MetaRectangle previous_rect;
|
||||
gboolean previous_is_valid;
|
||||
};
|
||||
typedef struct _MetaStagePrivate MetaStagePrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaStage, meta_stage, CLUTTER_TYPE_STAGE);
|
||||
|
||||
static void
|
||||
update_pipeline (MetaStage *stage)
|
||||
{
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
|
||||
if (priv->cursor)
|
||||
{
|
||||
CoglTexture *texture = meta_cursor_reference_get_cogl_texture (priv->cursor, NULL, NULL);
|
||||
cogl_pipeline_set_layer_texture (priv->pipeline, 0, texture);
|
||||
}
|
||||
else
|
||||
cogl_pipeline_set_layer_texture (priv->pipeline, 0, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_stage_finalize (GObject *object)
|
||||
{
|
||||
MetaStage *stage = META_STAGE (object);
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
|
||||
if (priv->pipeline)
|
||||
cogl_object_unref (priv->pipeline);
|
||||
}
|
||||
|
||||
static void
|
||||
paint_cursor (MetaStage *stage)
|
||||
{
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
if (!priv->cursor)
|
||||
return;
|
||||
|
||||
cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (),
|
||||
priv->pipeline,
|
||||
priv->current_rect.x,
|
||||
priv->current_rect.y,
|
||||
priv->current_rect.x +
|
||||
priv->current_rect.width,
|
||||
priv->current_rect.y +
|
||||
priv->current_rect.height);
|
||||
|
||||
priv->previous_rect = priv->current_rect;
|
||||
priv->previous_is_valid = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_stage_paint (ClutterActor *actor)
|
||||
{
|
||||
MetaStage *stage = META_STAGE (actor);
|
||||
|
||||
CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor);
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
paint_cursor (stage);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_stage_class_init (MetaStageClass *klass)
|
||||
{
|
||||
ClutterActorClass *actor_class = (ClutterActorClass *) klass;
|
||||
GObjectClass *object_class = (GObjectClass *) klass;
|
||||
|
||||
object_class->finalize = meta_stage_finalize;
|
||||
|
||||
actor_class->paint = meta_stage_paint;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_stage_init (MetaStage *stage)
|
||||
{
|
||||
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
|
||||
priv->pipeline = cogl_pipeline_new (ctx);
|
||||
|
||||
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), FALSE);
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
meta_stage_new (void)
|
||||
{
|
||||
return g_object_new (META_TYPE_STAGE,
|
||||
"cursor-visible", FALSE,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
queue_redraw (MetaStage *stage)
|
||||
{
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
cairo_rectangle_int_t clip;
|
||||
|
||||
/* Clear the location the cursor was at before, if we need to. */
|
||||
if (priv->previous_is_valid)
|
||||
{
|
||||
clip.x = priv->previous_rect.x;
|
||||
clip.y = priv->previous_rect.y;
|
||||
clip.width = priv->previous_rect.width;
|
||||
clip.height = priv->previous_rect.height;
|
||||
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &clip);
|
||||
priv->previous_is_valid = FALSE;
|
||||
}
|
||||
|
||||
/* And queue a redraw for the current cursor location. */
|
||||
if (priv->cursor)
|
||||
{
|
||||
clip.x = priv->current_rect.x;
|
||||
clip.y = priv->current_rect.y;
|
||||
clip.width = priv->current_rect.width;
|
||||
clip.height = priv->current_rect.height;
|
||||
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &clip);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_stage_set_cursor (MetaStage *stage,
|
||||
MetaCursorReference *cursor,
|
||||
MetaRectangle *rect)
|
||||
{
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
|
||||
if (priv->cursor != cursor)
|
||||
{
|
||||
priv->cursor = cursor;
|
||||
update_pipeline (stage);
|
||||
}
|
||||
|
||||
priv->current_rect = *rect;
|
||||
queue_redraw (stage);
|
||||
}
|
@@ -34,45 +34,15 @@
|
||||
struct _MetaSurfaceActorWaylandPrivate
|
||||
{
|
||||
MetaWaylandSurface *surface;
|
||||
MetaWaylandBuffer *buffer;
|
||||
struct wl_listener buffer_destroy_listener;
|
||||
};
|
||||
typedef struct _MetaSurfaceActorWaylandPrivate MetaSurfaceActorWaylandPrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaSurfaceActorWayland, meta_surface_actor_wayland, META_TYPE_SURFACE_ACTOR)
|
||||
|
||||
static void
|
||||
meta_surface_actor_handle_buffer_destroy (struct wl_listener *listener, void *data)
|
||||
{
|
||||
MetaSurfaceActorWaylandPrivate *priv = wl_container_of (listener, priv, buffer_destroy_listener);
|
||||
|
||||
/* If the buffer is destroyed while we're attached to it,
|
||||
* we want to unset priv->buffer so we don't access freed
|
||||
* memory. Keep the texture set however so the user doesn't
|
||||
* see the window disappear. */
|
||||
priv->buffer = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_wayland_process_damage (MetaSurfaceActor *actor,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor);
|
||||
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
|
||||
|
||||
if (priv->buffer)
|
||||
{
|
||||
struct wl_resource *resource = priv->buffer->resource;
|
||||
struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (resource);
|
||||
|
||||
if (shm_buffer)
|
||||
{
|
||||
CoglTexture2D *texture = COGL_TEXTURE_2D (priv->buffer->texture);
|
||||
cogl_wayland_texture_set_region_from_shm_buffer (texture, x, y, width, height, shm_buffer, x, y, 0, NULL);
|
||||
}
|
||||
|
||||
meta_surface_actor_update_area (META_SURFACE_ACTOR (self), x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -109,7 +79,7 @@ meta_surface_actor_wayland_is_unredirected (MetaSurfaceActor *actor)
|
||||
}
|
||||
|
||||
static int
|
||||
get_output_scale (int output_id)
|
||||
get_output_scale (int winsys_id)
|
||||
{
|
||||
MetaMonitorManager *monitor_manager = meta_monitor_manager_get ();
|
||||
MetaOutput *outputs;
|
||||
@@ -120,7 +90,7 @@ get_output_scale (int output_id)
|
||||
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
{
|
||||
if (outputs[i].output_id == output_id)
|
||||
if (outputs[i].winsys_id == winsys_id)
|
||||
{
|
||||
output_scale = outputs[i].scale;
|
||||
break;
|
||||
@@ -150,7 +120,7 @@ meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *actor)
|
||||
|
||||
/* XXX: We do not handle x11 clients yet */
|
||||
if (window && window->client_type != META_WINDOW_CLIENT_TYPE_X11)
|
||||
output_scale = get_output_scale (window->monitor->output_id);
|
||||
output_scale = get_output_scale (window->monitor->winsys_id);
|
||||
|
||||
return (double)output_scale / (double)priv->surface->scale;
|
||||
}
|
||||
@@ -213,7 +183,7 @@ meta_surface_actor_wayland_dispose (GObject *object)
|
||||
{
|
||||
MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (object);
|
||||
|
||||
meta_surface_actor_wayland_set_buffer (self, NULL);
|
||||
meta_surface_actor_wayland_set_texture (self, NULL);
|
||||
|
||||
G_OBJECT_CLASS (meta_surface_actor_wayland_parent_class)->dispose (object);
|
||||
}
|
||||
@@ -244,9 +214,6 @@ meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass)
|
||||
static void
|
||||
meta_surface_actor_wayland_init (MetaSurfaceActorWayland *self)
|
||||
{
|
||||
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
|
||||
|
||||
priv->buffer_destroy_listener.notify = meta_surface_actor_handle_buffer_destroy;
|
||||
}
|
||||
|
||||
MetaSurfaceActor *
|
||||
@@ -263,24 +230,11 @@ meta_surface_actor_wayland_new (MetaWaylandSurface *surface)
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self,
|
||||
MetaWaylandBuffer *buffer)
|
||||
meta_surface_actor_wayland_set_texture (MetaSurfaceActorWayland *self,
|
||||
CoglTexture *texture)
|
||||
{
|
||||
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
|
||||
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
|
||||
|
||||
if (priv->buffer)
|
||||
wl_list_remove (&priv->buffer_destroy_listener.link);
|
||||
|
||||
priv->buffer = buffer;
|
||||
|
||||
if (priv->buffer)
|
||||
{
|
||||
wl_signal_add (&priv->buffer->destroy_signal, &priv->buffer_destroy_listener);
|
||||
meta_shaped_texture_set_texture (stex, priv->buffer->texture);
|
||||
}
|
||||
else
|
||||
meta_shaped_texture_set_texture (stex, NULL);
|
||||
meta_shaped_texture_set_texture (stex, texture);
|
||||
}
|
||||
|
||||
MetaWaylandSurface *
|
||||
|
@@ -58,8 +58,8 @@ GType meta_surface_actor_wayland_get_type (void);
|
||||
MetaSurfaceActor * meta_surface_actor_wayland_new (MetaWaylandSurface *surface);
|
||||
MetaWaylandSurface * meta_surface_actor_wayland_get_surface (MetaSurfaceActorWayland *self);
|
||||
|
||||
void meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self,
|
||||
MetaWaylandBuffer *buffer);
|
||||
void meta_surface_actor_wayland_set_texture (MetaSurfaceActorWayland *self,
|
||||
CoglTexture *texture);
|
||||
|
||||
double meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *actor);
|
||||
|
||||
|
@@ -34,6 +34,7 @@
|
||||
#include "window-private.h"
|
||||
#include "meta-shaped-texture-private.h"
|
||||
#include "meta-cullable.h"
|
||||
#include "x11/window-x11.h"
|
||||
|
||||
struct _MetaSurfaceActorX11Private
|
||||
{
|
||||
@@ -143,7 +144,7 @@ update_pixmap (MetaSurfaceActorX11 *self)
|
||||
if (priv->pixmap == None)
|
||||
{
|
||||
Pixmap new_pixmap;
|
||||
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
|
||||
Window xwindow = meta_window_x11_get_toplevel_xwindow (priv->window);
|
||||
|
||||
meta_error_trap_push (display);
|
||||
new_pixmap = XCompositeNameWindowPixmap (xdisplay, xwindow);
|
||||
@@ -178,19 +179,6 @@ is_visible (MetaSurfaceActorX11 *self)
|
||||
return (priv->pixmap != None) && !priv->unredirected;
|
||||
}
|
||||
|
||||
static void
|
||||
damage_area (MetaSurfaceActorX11 *self,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
|
||||
if (!is_visible (self))
|
||||
return;
|
||||
|
||||
cogl_texture_pixmap_x11_update_area (priv->texture, x, y, width, height);
|
||||
meta_surface_actor_update_area (META_SURFACE_ACTOR (self), x, y, width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_x11_process_damage (MetaSurfaceActor *actor,
|
||||
int x, int y, int width, int height)
|
||||
@@ -217,11 +205,10 @@ meta_surface_actor_x11_process_damage (MetaSurfaceActor *actor,
|
||||
priv->does_full_damage = TRUE;
|
||||
}
|
||||
|
||||
/* Drop damage event for unredirected windows */
|
||||
if (priv->unredirected)
|
||||
if (!is_visible (self))
|
||||
return;
|
||||
|
||||
damage_area (self, x, y, width, height);
|
||||
cogl_texture_pixmap_x11_update_area (priv->texture, x, y, width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -292,7 +279,7 @@ sync_unredirected (MetaSurfaceActorX11 *self)
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
MetaDisplay *display = priv->display;
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
|
||||
Window xwindow = meta_window_x11_get_toplevel_xwindow (priv->window);
|
||||
|
||||
meta_error_trap_push (display);
|
||||
|
||||
@@ -384,7 +371,7 @@ create_damage (MetaSurfaceActorX11 *self)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
Display *xdisplay = meta_display_get_xdisplay (priv->display);
|
||||
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
|
||||
Window xwindow = meta_window_x11_get_toplevel_xwindow (priv->window);
|
||||
|
||||
priv->damage = XDamageCreate (xdisplay, xwindow, XDamageReportBoundingBox);
|
||||
}
|
||||
|
@@ -36,20 +36,13 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaSurfaceActor, meta_surface_actor, CLUTTER_
|
||||
|
||||
enum {
|
||||
REPAINT_SCHEDULED,
|
||||
SIZE_CHANGED,
|
||||
|
||||
LAST_SIGNAL,
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL];
|
||||
|
||||
gboolean
|
||||
meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor *self,
|
||||
cairo_rectangle_int_t *unobscured_bounds)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
return meta_shaped_texture_get_unobscured_bounds (priv->texture, unobscured_bounds);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_pick (ClutterActor *actor,
|
||||
const ClutterColor *color)
|
||||
@@ -128,6 +121,13 @@ meta_surface_actor_class_init (MetaSurfaceActorClass *klass)
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
signals[SIZE_CHANGED] = g_signal_new ("size-changed",
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
g_type_class_add_private (klass, sizeof (MetaSurfaceActorPrivate));
|
||||
}
|
||||
|
||||
@@ -152,6 +152,14 @@ cullable_iface_init (MetaCullableInterface *iface)
|
||||
iface->reset_culling = meta_surface_actor_reset_culling;
|
||||
}
|
||||
|
||||
static void
|
||||
texture_size_changed (MetaShapedTexture *texture,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaSurfaceActor *actor = META_SURFACE_ACTOR (user_data);
|
||||
g_signal_emit (actor, signals[SIZE_CHANGED], 0);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_init (MetaSurfaceActor *self)
|
||||
{
|
||||
@@ -162,6 +170,8 @@ meta_surface_actor_init (MetaSurfaceActor *self)
|
||||
MetaSurfaceActorPrivate);
|
||||
|
||||
priv->texture = META_SHAPED_TEXTURE (meta_shaped_texture_new ());
|
||||
g_signal_connect_object (priv->texture, "size-changed",
|
||||
G_CALLBACK (texture_size_changed), self, 0);
|
||||
clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->texture));
|
||||
}
|
||||
|
||||
@@ -178,7 +188,7 @@ meta_surface_actor_get_texture (MetaSurfaceActor *self)
|
||||
return self->priv->texture;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
meta_surface_actor_update_area (MetaSurfaceActor *self,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
@@ -252,6 +262,9 @@ meta_surface_actor_process_damage (MetaSurfaceActor *self,
|
||||
}
|
||||
|
||||
META_SURFACE_ACTOR_GET_CLASS (self)->process_damage (self, x, y, width, height);
|
||||
|
||||
if (meta_surface_actor_is_visible (self))
|
||||
meta_surface_actor_update_area (self, x, y, width, height);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -267,9 +280,15 @@ meta_surface_actor_is_argb32 (MetaSurfaceActor *self)
|
||||
CoglTexture *texture = meta_shaped_texture_get_texture (stex);
|
||||
|
||||
/* If we don't have a texture, like during initialization, assume
|
||||
* that we're ARGB32. */
|
||||
* that we're ARGB32.
|
||||
*
|
||||
* If we are unredirected and we have no texture assume that we are
|
||||
* not ARGB32 otherwise we wouldn't be unredirected in the first
|
||||
* place. This prevents us from continually redirecting and
|
||||
* unredirecting on every paint.
|
||||
*/
|
||||
if (!texture)
|
||||
return TRUE;
|
||||
return !meta_surface_actor_is_unredirected (self);
|
||||
|
||||
switch (cogl_texture_get_components (texture))
|
||||
{
|
||||
|
@@ -55,17 +55,12 @@ MetaShapedTexture *meta_surface_actor_get_texture (MetaSurfaceActor *self);
|
||||
MetaWindow *meta_surface_actor_get_window (MetaSurfaceActor *self);
|
||||
|
||||
gboolean meta_surface_actor_is_obscured (MetaSurfaceActor *self);
|
||||
gboolean meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor *self,
|
||||
cairo_rectangle_int_t *unobscured_bounds);
|
||||
|
||||
void meta_surface_actor_set_input_region (MetaSurfaceActor *self,
|
||||
cairo_region_t *region);
|
||||
void meta_surface_actor_set_opaque_region (MetaSurfaceActor *self,
|
||||
cairo_region_t *region);
|
||||
|
||||
void meta_surface_actor_update_area (MetaSurfaceActor *actor,
|
||||
int x, int y, int width, int height);
|
||||
|
||||
void meta_surface_actor_process_damage (MetaSurfaceActor *actor,
|
||||
int x, int y, int width, int height);
|
||||
void meta_surface_actor_pre_paint (MetaSurfaceActor *actor);
|
||||
|
@@ -1,574 +0,0 @@
|
||||
/*
|
||||
* This is based on an original C++ implementation for compiz that
|
||||
* carries the following copyright notice:
|
||||
*
|
||||
*
|
||||
* Copyright © 2011 NVIDIA Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software
|
||||
* and its documentation for any purpose is hereby granted without
|
||||
* fee, provided that the above copyright notice appear in all copies
|
||||
* and that both that copyright notice and this permission notice
|
||||
* appear in supporting documentation, and that the name of NVIDIA
|
||||
* Corporation not be used in advertising or publicity pertaining to
|
||||
* distribution of the software without specific, written prior
|
||||
* permission. NVIDIA Corporation makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* NVIDIA CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Authors: James Jones <jajones@nvidia.com>
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glx.h>
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
#include <meta/display.h>
|
||||
#include <meta/util.h>
|
||||
|
||||
#include "meta-sync-ring.h"
|
||||
|
||||
/* Theory of operation:
|
||||
*
|
||||
* We use a ring of NUM_SYNCS fence objects. On each frame we advance
|
||||
* to the next fence in the ring. For each fence we do:
|
||||
*
|
||||
* 1. fence is XSyncTriggerFence()'d and glWaitSync()'d
|
||||
* 2. NUM_SYNCS / 2 frames later, fence should be triggered
|
||||
* 3. fence is XSyncResetFence()'d
|
||||
* 4. NUM_SYNCS / 2 frames later, fence should be reset
|
||||
* 5. go back to 1 and re-use fence
|
||||
*
|
||||
* glClientWaitSync() and XAlarms are used in steps 2 and 4,
|
||||
* respectively, to double-check the expectections.
|
||||
*/
|
||||
|
||||
#define NUM_SYNCS 10
|
||||
#define MAX_SYNC_WAIT_TIME (1 * 1000 * 1000 * 1000) /* one sec */
|
||||
#define MAX_REBOOT_ATTEMPTS 2
|
||||
|
||||
typedef enum
|
||||
{
|
||||
META_SYNC_STATE_READY,
|
||||
META_SYNC_STATE_WAITING,
|
||||
META_SYNC_STATE_DONE,
|
||||
META_SYNC_STATE_RESET_PENDING,
|
||||
} MetaSyncState;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Display *xdisplay;
|
||||
|
||||
XSyncFence xfence;
|
||||
GLsync glsync;
|
||||
|
||||
XSyncCounter xcounter;
|
||||
XSyncAlarm xalarm;
|
||||
XSyncValue next_counter_value;
|
||||
|
||||
MetaSyncState state;
|
||||
} MetaSync;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MetaDisplay *display;
|
||||
|
||||
GHashTable *alarm_to_sync;
|
||||
|
||||
MetaSync *syncs_array[NUM_SYNCS];
|
||||
guint current_sync_idx;
|
||||
MetaSync *current_sync;
|
||||
guint warmup_syncs;
|
||||
|
||||
guint reboots;
|
||||
} MetaSyncRing;
|
||||
|
||||
static MetaSyncRing meta_sync_ring = { 0 };
|
||||
|
||||
static XSyncValue SYNC_VALUE_ZERO;
|
||||
static XSyncValue SYNC_VALUE_ONE;
|
||||
|
||||
static void (*meta_gl_get_integerv) (GLenum pname,
|
||||
GLint *params);
|
||||
static const char* (*meta_gl_get_stringi) (GLenum name,
|
||||
GLuint index);
|
||||
static void (*meta_gl_delete_sync) (GLsync sync);
|
||||
static GLenum (*meta_gl_client_wait_sync) (GLsync sync,
|
||||
GLbitfield flags,
|
||||
GLuint64 timeout);
|
||||
static void (*meta_gl_wait_sync) (GLsync sync,
|
||||
GLbitfield flags,
|
||||
GLuint64 timeout);
|
||||
static GLsync (*meta_gl_import_sync) (GLenum external_sync_type,
|
||||
GLintptr external_sync,
|
||||
GLbitfield flags);
|
||||
|
||||
static GLenum (*meta_gl_get_error) (void);
|
||||
static GLboolean (*meta_gl_is_sync) (GLsync sync);
|
||||
|
||||
static MetaSyncRing *
|
||||
meta_sync_ring_get (void)
|
||||
{
|
||||
if (meta_sync_ring.reboots > MAX_REBOOT_ATTEMPTS)
|
||||
return NULL;
|
||||
|
||||
return &meta_sync_ring;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
load_gl_symbol (const char *name,
|
||||
void **func)
|
||||
{
|
||||
*func = cogl_get_proc_address (name);
|
||||
if (!*func)
|
||||
{
|
||||
meta_verbose ("MetaSyncRing: failed to resolve required GL symbol \"%s\"\n", name);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_gl_extensions (void)
|
||||
{
|
||||
int num_extensions, i;
|
||||
gboolean sync = FALSE;
|
||||
gboolean x11_sync_object = FALSE;
|
||||
|
||||
meta_gl_get_integerv (GL_NUM_EXTENSIONS, &num_extensions);
|
||||
|
||||
for (i = 0; i < num_extensions; ++i)
|
||||
{
|
||||
const char *ext = meta_gl_get_stringi (GL_EXTENSIONS, i);
|
||||
|
||||
if (g_strcmp0 ("GL_ARB_sync", ext) == 0)
|
||||
sync = TRUE;
|
||||
else if (g_strcmp0 ("GL_EXT_x11_sync_object", ext) == 0)
|
||||
x11_sync_object = TRUE;
|
||||
}
|
||||
|
||||
return sync && x11_sync_object;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
load_required_symbols (void)
|
||||
{
|
||||
static gboolean success = FALSE;
|
||||
|
||||
if (success)
|
||||
return TRUE;
|
||||
|
||||
/* We don't link against libGL directly because cogl may want to
|
||||
* use something else. This assumes that cogl has been initialized
|
||||
* and dynamically loaded libGL at this point.
|
||||
*/
|
||||
|
||||
if (!load_gl_symbol ("glGetIntegerv", (void **) &meta_gl_get_integerv))
|
||||
goto out;
|
||||
if (!load_gl_symbol ("glGetStringi", (void **) &meta_gl_get_stringi))
|
||||
goto out;
|
||||
|
||||
if (!check_gl_extensions ())
|
||||
{
|
||||
meta_verbose ("MetaSyncRing: couldn't find required GL extensions\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!load_gl_symbol ("glDeleteSync", (void **) &meta_gl_delete_sync))
|
||||
goto out;
|
||||
if (!load_gl_symbol ("glClientWaitSync", (void **) &meta_gl_client_wait_sync))
|
||||
goto out;
|
||||
if (!load_gl_symbol ("glWaitSync", (void **) &meta_gl_wait_sync))
|
||||
goto out;
|
||||
if (!load_gl_symbol ("glImportSyncEXT", (void **) &meta_gl_import_sync))
|
||||
goto out;
|
||||
|
||||
if (!load_gl_symbol ("glGetError", (void **) &meta_gl_get_error))
|
||||
goto out;
|
||||
if (!load_gl_symbol ("glIsSync", (void **) &meta_gl_is_sync))
|
||||
goto out;
|
||||
|
||||
success = TRUE;
|
||||
out:
|
||||
return success;
|
||||
}
|
||||
|
||||
static void
|
||||
print_gl_error (void)
|
||||
{
|
||||
GLenum e;
|
||||
switch (e = meta_gl_get_error ())
|
||||
{
|
||||
case GL_NO_ERROR:
|
||||
meta_warning ("GL_NO_ERROR\n");
|
||||
break;
|
||||
case GL_INVALID_ENUM:
|
||||
meta_warning ("GL_INVALID_ENUM\n");
|
||||
break;
|
||||
case GL_INVALID_VALUE:
|
||||
meta_warning ("GL_INVALID_VALUE\n");
|
||||
break;
|
||||
case GL_INVALID_OPERATION:
|
||||
meta_warning ("GL_INVALID_OPERATION\n");
|
||||
break;
|
||||
case GL_INVALID_FRAMEBUFFER_OPERATION:
|
||||
meta_warning ("GL_INVALID_FRAMEBUFFER_OPERATION\n");
|
||||
break;
|
||||
case GL_OUT_OF_MEMORY:
|
||||
meta_warning ("GL_OUT_OF_MEMORY\n");
|
||||
break;
|
||||
case GL_STACK_OVERFLOW:
|
||||
meta_warning ("GL_STACK_OVERFLOW\n");
|
||||
break;
|
||||
case GL_STACK_UNDERFLOW:
|
||||
meta_warning ("GL_STACK_UNDERFLOW\n");
|
||||
break;
|
||||
default:
|
||||
meta_warning ("GL error 0x%x\n", e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_sync_insert (MetaSync *self)
|
||||
{
|
||||
g_return_if_fail (self->state == META_SYNC_STATE_READY);
|
||||
|
||||
XSyncTriggerFence (self->xdisplay, self->xfence);
|
||||
XFlush (self->xdisplay);
|
||||
|
||||
meta_gl_wait_sync (self->glsync, 0, GL_TIMEOUT_IGNORED);
|
||||
|
||||
self->state = META_SYNC_STATE_WAITING;
|
||||
}
|
||||
|
||||
static GLenum
|
||||
meta_sync_check_update_finished (MetaSync *self,
|
||||
GLuint64 timeout)
|
||||
{
|
||||
GLenum status = GL_WAIT_FAILED;
|
||||
|
||||
switch (self->state)
|
||||
{
|
||||
case META_SYNC_STATE_DONE:
|
||||
status = GL_ALREADY_SIGNALED;
|
||||
break;
|
||||
case META_SYNC_STATE_WAITING:
|
||||
status = meta_gl_client_wait_sync (self->glsync, 0, timeout);
|
||||
if (status == GL_ALREADY_SIGNALED || status == GL_CONDITION_SATISFIED)
|
||||
self->state = META_SYNC_STATE_DONE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
g_warn_if_fail (status != GL_WAIT_FAILED);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_sync_reset (MetaSync *self)
|
||||
{
|
||||
XSyncAlarmAttributes attrs;
|
||||
int overflow;
|
||||
|
||||
g_return_if_fail (self->state == META_SYNC_STATE_DONE);
|
||||
|
||||
XSyncResetFence (self->xdisplay, self->xfence);
|
||||
|
||||
attrs.trigger.wait_value = self->next_counter_value;
|
||||
|
||||
XSyncChangeAlarm (self->xdisplay, self->xalarm, XSyncCAValue, &attrs);
|
||||
XSyncSetCounter (self->xdisplay, self->xcounter, self->next_counter_value);
|
||||
|
||||
XSyncValueAdd (&self->next_counter_value,
|
||||
self->next_counter_value,
|
||||
SYNC_VALUE_ONE,
|
||||
&overflow);
|
||||
|
||||
self->state = META_SYNC_STATE_RESET_PENDING;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_sync_handle_event (MetaSync *self,
|
||||
XSyncAlarmNotifyEvent *event)
|
||||
{
|
||||
g_return_if_fail (event->alarm == self->xalarm);
|
||||
g_return_if_fail (self->state == META_SYNC_STATE_RESET_PENDING);
|
||||
|
||||
self->state = META_SYNC_STATE_READY;
|
||||
}
|
||||
|
||||
static MetaSync *
|
||||
meta_sync_new (Display *xdisplay)
|
||||
{
|
||||
MetaSync *self;
|
||||
XSyncAlarmAttributes attrs;
|
||||
|
||||
self = g_malloc0 (sizeof (MetaSync));
|
||||
|
||||
self->xdisplay = xdisplay;
|
||||
|
||||
self->xfence = XSyncCreateFence (xdisplay, DefaultRootWindow (xdisplay), FALSE);
|
||||
meta_warning ("created X fence 0x%x\n", self->xfence);
|
||||
self->glsync = meta_gl_import_sync (GL_SYNC_X11_FENCE_EXT, self->xfence, 0);
|
||||
print_gl_error ();
|
||||
|
||||
self->xcounter = XSyncCreateCounter (xdisplay, SYNC_VALUE_ZERO);
|
||||
|
||||
attrs.trigger.counter = self->xcounter;
|
||||
attrs.trigger.value_type = XSyncAbsolute;
|
||||
attrs.trigger.wait_value = SYNC_VALUE_ONE;
|
||||
attrs.trigger.test_type = XSyncPositiveTransition;
|
||||
attrs.events = TRUE;
|
||||
self->xalarm = XSyncCreateAlarm (xdisplay,
|
||||
XSyncCACounter |
|
||||
XSyncCAValueType |
|
||||
XSyncCAValue |
|
||||
XSyncCATestType |
|
||||
XSyncCAEvents,
|
||||
&attrs);
|
||||
|
||||
XSyncIntToValue (&self->next_counter_value, 1);
|
||||
|
||||
self->state = META_SYNC_STATE_READY;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static Bool
|
||||
alarm_event_predicate (Display *dpy,
|
||||
XEvent *event,
|
||||
XPointer data)
|
||||
{
|
||||
int xsync_event_base;
|
||||
MetaSyncRing *ring = meta_sync_ring_get ();
|
||||
|
||||
if (!ring)
|
||||
return False;
|
||||
|
||||
xsync_event_base = meta_display_get_sync_event_base (ring->display);
|
||||
|
||||
if (event->type == xsync_event_base + XSyncAlarmNotify)
|
||||
{
|
||||
if (((MetaSync *) data)->xalarm == ((XSyncAlarmNotifyEvent *) event)->alarm)
|
||||
return True;
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_sync_free (MetaSync *self)
|
||||
{
|
||||
/* When our assumptions don't hold, something has gone wrong but we
|
||||
* don't know what, so we reboot the ring. While doing that, we
|
||||
* trigger fences before deleting them to try to get ourselves out
|
||||
* of a potentially stuck GPU state.
|
||||
*/
|
||||
switch (self->state)
|
||||
{
|
||||
case META_SYNC_STATE_WAITING:
|
||||
case META_SYNC_STATE_DONE:
|
||||
/* nothing to do */
|
||||
break;
|
||||
case META_SYNC_STATE_RESET_PENDING:
|
||||
{
|
||||
XEvent event;
|
||||
XIfEvent (self->xdisplay, &event, alarm_event_predicate, (XPointer) self);
|
||||
meta_sync_handle_event (self, (XSyncAlarmNotifyEvent *) &event);
|
||||
}
|
||||
/* fall through */
|
||||
case META_SYNC_STATE_READY:
|
||||
XSyncTriggerFence (self->xdisplay, self->xfence);
|
||||
XFlush (self->xdisplay);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
meta_gl_delete_sync (self->glsync);
|
||||
XSyncDestroyFence (self->xdisplay, self->xfence);
|
||||
XSyncDestroyCounter (self->xdisplay, self->xcounter);
|
||||
XSyncDestroyAlarm (self->xdisplay, self->xalarm);
|
||||
|
||||
g_free (self);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_sync_ring_init (MetaDisplay *display)
|
||||
{
|
||||
guint i;
|
||||
MetaSyncRing *ring = meta_sync_ring_get ();
|
||||
|
||||
if (!ring)
|
||||
return FALSE;
|
||||
|
||||
g_return_val_if_fail (display != NULL, FALSE);
|
||||
g_return_val_if_fail (ring->display == NULL, FALSE);
|
||||
|
||||
if (!load_required_symbols ())
|
||||
return FALSE;
|
||||
|
||||
if (!meta_display_has_sync (display))
|
||||
return FALSE;
|
||||
|
||||
print_gl_error ();
|
||||
|
||||
XSyncIntToValue (&SYNC_VALUE_ZERO, 0);
|
||||
XSyncIntToValue (&SYNC_VALUE_ONE, 1);
|
||||
|
||||
ring->display = display;
|
||||
|
||||
ring->alarm_to_sync = g_hash_table_new (NULL, NULL);
|
||||
|
||||
for (i = 0; i < NUM_SYNCS; ++i)
|
||||
{
|
||||
MetaSync *sync = meta_sync_new (meta_display_get_xdisplay (display));
|
||||
ring->syncs_array[i] = sync;
|
||||
g_hash_table_replace (ring->alarm_to_sync, (gpointer) sync->xalarm, sync);
|
||||
}
|
||||
|
||||
ring->current_sync_idx = 0;
|
||||
ring->current_sync = ring->syncs_array[0];
|
||||
ring->warmup_syncs = 0;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_sync_ring_destroy (void)
|
||||
{
|
||||
guint i;
|
||||
MetaSyncRing *ring = meta_sync_ring_get ();
|
||||
|
||||
if (!ring)
|
||||
return;
|
||||
|
||||
g_return_if_fail (ring->display != NULL);
|
||||
|
||||
ring->current_sync_idx = 0;
|
||||
ring->current_sync = NULL;
|
||||
ring->warmup_syncs = 0;
|
||||
|
||||
for (i = 0; i < NUM_SYNCS; ++i)
|
||||
meta_sync_free (ring->syncs_array[i]);
|
||||
|
||||
g_hash_table_destroy (ring->alarm_to_sync);
|
||||
|
||||
ring->display = NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_sync_ring_reboot (MetaDisplay *display)
|
||||
{
|
||||
MetaSyncRing *ring = meta_sync_ring_get ();
|
||||
|
||||
if (!ring)
|
||||
return FALSE;
|
||||
|
||||
meta_sync_ring_destroy ();
|
||||
|
||||
ring->reboots += 1;
|
||||
|
||||
if (!meta_sync_ring_get ())
|
||||
{
|
||||
meta_warning ("MetaSyncRing: Too many reboots -- disabling\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return meta_sync_ring_init (display);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_sync_ring_after_frame (void)
|
||||
{
|
||||
MetaSyncRing *ring = meta_sync_ring_get ();
|
||||
|
||||
if (!ring)
|
||||
return FALSE;
|
||||
|
||||
g_return_if_fail (ring->display != NULL);
|
||||
|
||||
if (ring->warmup_syncs >= NUM_SYNCS / 2)
|
||||
{
|
||||
guint reset_sync_idx = (ring->current_sync_idx + NUM_SYNCS - (NUM_SYNCS / 2)) % NUM_SYNCS;
|
||||
MetaSync *sync_to_reset = ring->syncs_array[reset_sync_idx];
|
||||
|
||||
GLenum status = meta_sync_check_update_finished (sync_to_reset, 0);
|
||||
if (status == GL_TIMEOUT_EXPIRED)
|
||||
{
|
||||
meta_warning ("MetaSyncRing: We should never wait for a sync -- add more syncs?\n");
|
||||
status = meta_sync_check_update_finished (sync_to_reset, MAX_SYNC_WAIT_TIME);
|
||||
}
|
||||
|
||||
if (status != GL_ALREADY_SIGNALED && status != GL_CONDITION_SATISFIED)
|
||||
{
|
||||
meta_warning ("MetaSyncRing: Timed out waiting for sync object.\n");
|
||||
return meta_sync_ring_reboot (ring->display);
|
||||
}
|
||||
|
||||
meta_sync_reset (sync_to_reset);
|
||||
}
|
||||
else
|
||||
{
|
||||
ring->warmup_syncs += 1;
|
||||
}
|
||||
|
||||
ring->current_sync_idx += 1;
|
||||
ring->current_sync_idx %= NUM_SYNCS;
|
||||
|
||||
ring->current_sync = ring->syncs_array[ring->current_sync_idx];
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_sync_ring_insert_wait (void)
|
||||
{
|
||||
MetaSyncRing *ring = meta_sync_ring_get ();
|
||||
|
||||
if (!ring)
|
||||
return FALSE;
|
||||
|
||||
g_return_if_fail (ring->display != NULL);
|
||||
|
||||
if (ring->current_sync->state != META_SYNC_STATE_READY)
|
||||
{
|
||||
meta_warning ("MetaSyncRing: Sync object is not ready -- were events handled properly?\n");
|
||||
if (!meta_sync_ring_reboot (ring->display))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
meta_sync_insert (ring->current_sync);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_sync_ring_handle_event (XSyncAlarmNotifyEvent *event)
|
||||
{
|
||||
MetaSync *sync;
|
||||
MetaSyncRing *ring = meta_sync_ring_get ();
|
||||
|
||||
if (!ring)
|
||||
return;
|
||||
|
||||
g_return_if_fail (ring->display != NULL);
|
||||
|
||||
sync = g_hash_table_lookup (ring->alarm_to_sync, (gpointer) event->alarm);
|
||||
if (sync)
|
||||
meta_sync_handle_event (sync, event);
|
||||
}
|
@@ -1,17 +0,0 @@
|
||||
#ifndef _META_SYNC_RING_H_
|
||||
#define _META_SYNC_RING_H_
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/sync.h>
|
||||
|
||||
#include <meta/display.h>
|
||||
|
||||
gboolean meta_sync_ring_init (MetaDisplay *dpy);
|
||||
void meta_sync_ring_destroy (void);
|
||||
gboolean meta_sync_ring_after_frame (void);
|
||||
gboolean meta_sync_ring_insert_wait (void);
|
||||
void meta_sync_ring_handle_event (XSyncAlarmNotifyEvent *event);
|
||||
|
||||
#endif /* _META_SYNC_RING_H_ */
|
@@ -378,8 +378,8 @@ texture_tower_create_texture (MetaTextureTower *tower,
|
||||
}
|
||||
|
||||
static void
|
||||
texture_tower_revalidate_fbo (MetaTextureTower *tower,
|
||||
int level)
|
||||
texture_tower_revalidate (MetaTextureTower *tower,
|
||||
int level)
|
||||
{
|
||||
CoglTexture *source_texture = tower->textures[level - 1];
|
||||
int source_texture_width = cogl_texture_get_width (source_texture);
|
||||
@@ -425,13 +425,9 @@ texture_tower_revalidate_fbo (MetaTextureTower *tower,
|
||||
(2. * invalid->y2) / source_texture_height);
|
||||
|
||||
cogl_object_unref (pipeline);
|
||||
}
|
||||
|
||||
static void
|
||||
texture_tower_revalidate (MetaTextureTower *tower,
|
||||
int level)
|
||||
{
|
||||
texture_tower_revalidate_fbo (tower, level);
|
||||
tower->invalid[level].x1 = tower->invalid[level].x2 = 0;
|
||||
tower->invalid[level].y1 = tower->invalid[level].y2 = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -51,8 +51,7 @@ void meta_window_actor_update_shape (MetaWindowActor *self);
|
||||
void meta_window_actor_update_opacity (MetaWindowActor *self);
|
||||
void meta_window_actor_mapped (MetaWindowActor *self);
|
||||
void meta_window_actor_unmapped (MetaWindowActor *self);
|
||||
void meta_window_actor_set_updates_frozen (MetaWindowActor *self,
|
||||
gboolean updates_frozen);
|
||||
void meta_window_actor_sync_updates_frozen (MetaWindowActor *self);
|
||||
void meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
|
||||
gboolean no_delay_frame);
|
||||
|
||||
|
@@ -32,9 +32,17 @@
|
||||
|
||||
#include "meta-surface-actor.h"
|
||||
#include "meta-surface-actor-x11.h"
|
||||
#include "meta-surface-actor-wayland.h"
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
#include "meta-surface-actor-wayland.h"
|
||||
#include "wayland/meta-wayland-surface.h"
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
INITIALLY_FROZEN,
|
||||
DRAWING_FIRST_FRAME,
|
||||
EMITTED_FIRST_FRAME
|
||||
} FirstFrameState;
|
||||
|
||||
struct _MetaWindowActorPrivate
|
||||
{
|
||||
@@ -70,7 +78,7 @@ struct _MetaWindowActorPrivate
|
||||
gint64 frame_drawn_time;
|
||||
|
||||
guint repaint_scheduled_id;
|
||||
guint allocation_changed_id;
|
||||
guint size_changed_id;
|
||||
|
||||
/*
|
||||
* These need to be counters rather than flags, since more plugins
|
||||
@@ -78,6 +86,7 @@ struct _MetaWindowActorPrivate
|
||||
* might be dubious, but we have to at least handle it correctly.
|
||||
*/
|
||||
gint minimize_in_progress;
|
||||
gint unminimize_in_progress;
|
||||
gint maximize_in_progress;
|
||||
gint unmaximize_in_progress;
|
||||
gint map_in_progress;
|
||||
@@ -104,6 +113,7 @@ struct _MetaWindowActorPrivate
|
||||
guint no_shadow : 1;
|
||||
|
||||
guint updates_frozen : 1;
|
||||
guint first_frame_state : 2; /* FirstFrameState */
|
||||
};
|
||||
|
||||
typedef struct _FrameData FrameData;
|
||||
@@ -115,6 +125,14 @@ struct _FrameData
|
||||
gint64 frame_drawn_time;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
FIRST_FRAME,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_META_WINDOW = 1,
|
||||
@@ -181,6 +199,31 @@ meta_window_actor_class_init (MetaWindowActorClass *klass)
|
||||
actor_class->paint = meta_window_actor_paint;
|
||||
actor_class->get_paint_volume = meta_window_actor_get_paint_volume;
|
||||
|
||||
/**
|
||||
* MetaWindowActor::first-frame:
|
||||
* @actor: the #MetaWindowActor instance
|
||||
*
|
||||
* The ::first-frame signal will be emitted the first time a frame
|
||||
* of window contents has been drawn by the application and Mutter
|
||||
* has had the chance to drawn that frame to the screen. If the
|
||||
* window starts off initially hidden, obscured, or on on a
|
||||
* different workspace, the ::first-frame signal will be emitted
|
||||
* even though the user doesn't see the contents.
|
||||
*
|
||||
* MetaDisplay::window-created is a good place to connect to this
|
||||
* signal - at that point, the MetaWindowActor for the window
|
||||
* exists, but the window has reliably not yet been drawn.
|
||||
* Connecting to an existing window that has already been drawn to
|
||||
* the screen is not useful.
|
||||
*/
|
||||
signals[FIRST_FRAME] =
|
||||
g_signal_new ("first-frame",
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
pspec = g_param_spec_object ("meta-window",
|
||||
"MetaWindow",
|
||||
"The displayed MetaWindow",
|
||||
@@ -232,12 +275,11 @@ window_appears_focused_notify (MetaWindow *mw,
|
||||
}
|
||||
|
||||
static void
|
||||
surface_allocation_changed_notify (ClutterActor *actor,
|
||||
const ClutterActorBox *allocation,
|
||||
ClutterAllocationFlags flags,
|
||||
MetaWindowActor *self)
|
||||
surface_size_changed (MetaSurfaceActor *actor,
|
||||
gpointer user_data)
|
||||
{
|
||||
meta_window_actor_sync_actor_geometry (self, FALSE);
|
||||
MetaWindowActor *self = META_WINDOW_ACTOR (user_data);
|
||||
|
||||
meta_window_actor_update_shape (self);
|
||||
}
|
||||
|
||||
@@ -306,6 +348,9 @@ meta_window_actor_thaw (MetaWindowActor *self)
|
||||
if (priv->freeze_count > 0)
|
||||
return;
|
||||
|
||||
if (priv->first_frame_state == INITIALLY_FROZEN)
|
||||
priv->first_frame_state = DRAWING_FIRST_FRAME;
|
||||
|
||||
if (priv->surface)
|
||||
meta_surface_actor_set_frozen (priv->surface, FALSE);
|
||||
|
||||
@@ -326,9 +371,8 @@ set_surface (MetaWindowActor *self,
|
||||
if (priv->surface)
|
||||
{
|
||||
g_signal_handler_disconnect (priv->surface, priv->repaint_scheduled_id);
|
||||
g_signal_handler_disconnect (priv->surface, priv->size_changed_id);
|
||||
priv->repaint_scheduled_id = 0;
|
||||
g_signal_handler_disconnect (priv->surface, priv->allocation_changed_id);
|
||||
priv->allocation_changed_id = 0;
|
||||
clutter_actor_remove_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->surface));
|
||||
g_object_unref (priv->surface);
|
||||
}
|
||||
@@ -340,14 +384,17 @@ set_surface (MetaWindowActor *self,
|
||||
g_object_ref_sink (priv->surface);
|
||||
priv->repaint_scheduled_id = g_signal_connect (priv->surface, "repaint-scheduled",
|
||||
G_CALLBACK (surface_repaint_scheduled), self);
|
||||
priv->allocation_changed_id = g_signal_connect (priv->surface, "allocation-changed",
|
||||
G_CALLBACK (surface_allocation_changed_notify), self);
|
||||
priv->size_changed_id = g_signal_connect (priv->surface, "size-changed",
|
||||
G_CALLBACK (surface_size_changed), self);
|
||||
clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->surface));
|
||||
|
||||
/* If the previous surface actor was frozen, start out
|
||||
* frozen as well... */
|
||||
meta_surface_actor_set_frozen (priv->surface, priv->freeze_count > 0);
|
||||
|
||||
if (!is_frozen (self) && priv->first_frame_state == INITIALLY_FROZEN)
|
||||
priv->first_frame_state = DRAWING_FIRST_FRAME;
|
||||
|
||||
meta_window_actor_update_shape (self);
|
||||
}
|
||||
}
|
||||
@@ -359,9 +406,12 @@ meta_window_actor_update_surface (MetaWindowActor *self)
|
||||
MetaWindow *window = priv->window;
|
||||
MetaSurfaceActor *surface_actor;
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
if (window->surface)
|
||||
surface_actor = window->surface->surface_actor;
|
||||
else if (!meta_is_wayland_compositor ())
|
||||
else
|
||||
#endif
|
||||
if (!meta_is_wayland_compositor ())
|
||||
surface_actor = meta_surface_actor_x11_new (window);
|
||||
else
|
||||
surface_actor = NULL;
|
||||
@@ -551,6 +601,7 @@ meta_window_actor_get_shape_bounds (MetaWindowActor *self,
|
||||
|
||||
cairo_region_get_extents (priv->shape_region, bounds);
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
if (META_IS_SURFACE_ACTOR_WAYLAND (priv->surface))
|
||||
{
|
||||
double scale = priv->surface ?
|
||||
@@ -560,6 +611,7 @@ meta_window_actor_get_shape_bounds (MetaWindowActor *self,
|
||||
bounds->width *= scale;
|
||||
bounds->height *= scale;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -667,25 +719,16 @@ meta_window_actor_get_paint_volume (ClutterActor *actor,
|
||||
{
|
||||
MetaWindowActor *self = META_WINDOW_ACTOR (actor);
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
cairo_rectangle_int_t unobscured_bounds, bounds;
|
||||
gboolean appears_focused = meta_window_appears_focused (priv->window);
|
||||
ClutterVertex origin;
|
||||
|
||||
/* The paint volume is computed before paint functions are called
|
||||
* so our bounds might not be updated yet. Force an update. */
|
||||
meta_window_actor_handle_updates (self);
|
||||
|
||||
meta_window_actor_get_shape_bounds (self, &bounds);
|
||||
|
||||
if (priv->surface)
|
||||
{
|
||||
if (meta_surface_actor_get_unobscured_bounds (priv->surface, &unobscured_bounds))
|
||||
gdk_rectangle_intersect (&bounds, &unobscured_bounds, &bounds);
|
||||
}
|
||||
|
||||
if (appears_focused ? priv->focused_shadow : priv->unfocused_shadow)
|
||||
{
|
||||
cairo_rectangle_int_t shadow_bounds;
|
||||
ClutterActorBox shadow_box;
|
||||
|
||||
/* We could compute an full clip region as we do for the window
|
||||
* texture, but the shadow is relatively cheap to draw, and
|
||||
@@ -695,16 +738,24 @@ meta_window_actor_get_paint_volume (ClutterActor *actor,
|
||||
*/
|
||||
|
||||
meta_window_actor_get_shadow_bounds (self, appears_focused, &shadow_bounds);
|
||||
gdk_rectangle_union (&bounds, &shadow_bounds, &bounds);
|
||||
shadow_box.x1 = shadow_bounds.x;
|
||||
shadow_box.x2 = shadow_bounds.x + shadow_bounds.width;
|
||||
shadow_box.y1 = shadow_bounds.y;
|
||||
shadow_box.y2 = shadow_bounds.y + shadow_bounds.height;
|
||||
|
||||
clutter_paint_volume_union_box (volume, &shadow_box);
|
||||
}
|
||||
|
||||
origin.x = bounds.x;
|
||||
origin.y = bounds.y;
|
||||
origin.z = 0.0f;
|
||||
clutter_paint_volume_set_origin (volume, &origin);
|
||||
if (priv->surface)
|
||||
{
|
||||
const ClutterPaintVolume *child_volume;
|
||||
|
||||
clutter_paint_volume_set_width (volume, bounds.width);
|
||||
clutter_paint_volume_set_height (volume, bounds.height);
|
||||
child_volume = clutter_actor_get_transformed_paint_volume (CLUTTER_ACTOR (priv->surface), actor);
|
||||
if (!child_volume)
|
||||
return FALSE;
|
||||
|
||||
clutter_paint_volume_union (volume, child_volume);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -746,9 +797,11 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
|
||||
return FALSE;
|
||||
|
||||
/*
|
||||
* Add shadows to override redirect windows (e.g., Gtk menus).
|
||||
* Add shadows to override redirect windows on X11 unless the toolkit
|
||||
* indicates that it is handling shadows itself (e.g., Gtk menus).
|
||||
*/
|
||||
if (priv->window->override_redirect)
|
||||
if (priv->window->override_redirect &&
|
||||
!priv->window->has_custom_frame_extents)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
@@ -851,7 +904,7 @@ queue_send_frame_messages_timeout (MetaWindowActor *self)
|
||||
outputs = meta_monitor_manager_get_outputs (monitor_manager, &n_outputs);
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
{
|
||||
if (outputs[i].output_id == window->monitor->output_id && outputs[i].crtc)
|
||||
if (outputs[i].winsys_id == window->monitor->winsys_id && outputs[i].crtc)
|
||||
{
|
||||
refresh_rate = outputs[i].crtc->current_mode->refresh_rate;
|
||||
break;
|
||||
@@ -960,6 +1013,9 @@ start_simple_effect (MetaWindowActor *self,
|
||||
case META_PLUGIN_MINIMIZE:
|
||||
counter = &priv->minimize_in_progress;
|
||||
break;
|
||||
case META_PLUGIN_UNMINIMIZE:
|
||||
counter = &priv->unminimize_in_progress;
|
||||
break;
|
||||
case META_PLUGIN_MAP:
|
||||
counter = &priv->map_in_progress;
|
||||
break;
|
||||
@@ -1030,6 +1086,16 @@ meta_window_actor_effect_completed (MetaWindowActor *self,
|
||||
}
|
||||
}
|
||||
break;
|
||||
case META_PLUGIN_UNMINIMIZE:
|
||||
{
|
||||
priv->unminimize_in_progress--;
|
||||
if (priv->unminimize_in_progress < 0)
|
||||
{
|
||||
g_warning ("Error in unminimize accounting.");
|
||||
priv->unminimize_in_progress = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case META_PLUGIN_MAP:
|
||||
/*
|
||||
* Make sure that the actor is at the correct place in case
|
||||
@@ -1150,7 +1216,7 @@ meta_window_actor_sync_actor_geometry (MetaWindowActor *self,
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
MetaRectangle window_rect;
|
||||
|
||||
meta_window_get_input_rect (priv->window, &window_rect);
|
||||
meta_window_get_buffer_rect (priv->window, &window_rect);
|
||||
|
||||
/* When running as a Wayland compositor we catch size changes when new
|
||||
* buffers are attached */
|
||||
@@ -1195,8 +1261,7 @@ meta_window_actor_show (MetaWindowActor *self,
|
||||
event = META_PLUGIN_MAP;
|
||||
break;
|
||||
case META_COMP_EFFECT_UNMINIMIZE:
|
||||
/* FIXME: should have META_PLUGIN_UNMINIMIZE */
|
||||
event = META_PLUGIN_MAP;
|
||||
event = META_PLUGIN_UNMINIMIZE;
|
||||
break;
|
||||
case META_COMP_EFFECT_NONE:
|
||||
break;
|
||||
@@ -1324,7 +1389,12 @@ meta_window_actor_new (MetaWindow *window)
|
||||
|
||||
priv = self->priv;
|
||||
|
||||
meta_window_actor_set_updates_frozen (self, meta_window_updates_are_frozen (priv->window));
|
||||
meta_window_actor_sync_updates_frozen (self);
|
||||
|
||||
if (is_frozen (self))
|
||||
priv->first_frame_state = INITIALLY_FROZEN;
|
||||
else
|
||||
priv->first_frame_state = DRAWING_FIRST_FRAME;
|
||||
|
||||
/* If a window doesn't start off with updates frozen, we should
|
||||
* we should send a _NET_WM_FRAME_DRAWN immediately after the first drawn.
|
||||
@@ -1594,6 +1664,8 @@ build_and_scan_frame_mask (MetaWindowActor *self,
|
||||
cairo_rectangle_int_t *client_area,
|
||||
cairo_region_t *shape_region)
|
||||
{
|
||||
ClutterBackend *backend = clutter_get_default_backend ();
|
||||
CoglContext *ctx = clutter_backend_get_cogl_context (backend);
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
guchar *mask_data;
|
||||
guint tex_width, tex_height;
|
||||
@@ -1656,10 +1728,7 @@ build_and_scan_frame_mask (MetaWindowActor *self,
|
||||
|
||||
if (meta_texture_rectangle_check (paint_tex))
|
||||
{
|
||||
ClutterBackend *backend = clutter_get_default_backend ();
|
||||
CoglContext *context = clutter_backend_get_cogl_context (backend);
|
||||
|
||||
mask_texture = COGL_TEXTURE (cogl_texture_rectangle_new_with_size (context, tex_width, tex_height));
|
||||
mask_texture = COGL_TEXTURE (cogl_texture_rectangle_new_with_size (ctx, tex_width, tex_height));
|
||||
cogl_texture_set_components (mask_texture, COGL_TEXTURE_COMPONENTS_A);
|
||||
cogl_texture_set_region (mask_texture,
|
||||
0, 0, /* src_x/y */
|
||||
@@ -1671,15 +1740,9 @@ build_and_scan_frame_mask (MetaWindowActor *self,
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Note: we don't allow slicing for this texture because we
|
||||
* need to use it with multi-texturing which doesn't support
|
||||
* sliced textures */
|
||||
mask_texture = cogl_texture_new_from_data (tex_width, tex_height,
|
||||
COGL_TEXTURE_NO_SLICING,
|
||||
COGL_PIXEL_FORMAT_A_8,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
stride,
|
||||
mask_data);
|
||||
mask_texture = COGL_TEXTURE (cogl_texture_2d_new_from_data (ctx, tex_width, tex_height,
|
||||
COGL_PIXEL_FORMAT_A_8,
|
||||
stride, mask_data, NULL));
|
||||
}
|
||||
|
||||
meta_shaped_texture_set_mask_texture (stex, mask_texture);
|
||||
@@ -1908,6 +1971,12 @@ meta_window_actor_post_paint (MetaWindowActor *self)
|
||||
do_send_frame_drawn (self, priv->frames->data);
|
||||
priv->needs_frame_drawn = FALSE;
|
||||
}
|
||||
|
||||
if (priv->first_frame_state == DRAWING_FIRST_FRAME)
|
||||
{
|
||||
priv->first_frame_state = EMITTED_FIRST_FRAME;
|
||||
g_signal_emit (self, signals[FIRST_FRAME], 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2020,7 +2089,7 @@ meta_window_actor_update_opacity (MetaWindowActor *self)
|
||||
clutter_actor_set_opacity (CLUTTER_ACTOR (priv->surface), window->opacity);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
meta_window_actor_set_updates_frozen (MetaWindowActor *self,
|
||||
gboolean updates_frozen)
|
||||
{
|
||||
@@ -2037,3 +2106,12 @@ meta_window_actor_set_updates_frozen (MetaWindowActor *self,
|
||||
meta_window_actor_thaw (self);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_actor_sync_updates_frozen (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
MetaWindow *window = priv->window;
|
||||
|
||||
meta_window_actor_set_updates_frozen (self, meta_window_updates_are_frozen (window));
|
||||
}
|
||||
|
@@ -1,12 +1,22 @@
|
||||
|
||||
pkglibdir=@MUTTER_PLUGIN_DIR@
|
||||
pkglibdir = $(MUTTER_PLUGIN_DIR)
|
||||
|
||||
INCLUDES=@MUTTER_CFLAGS@ -I $(top_srcdir)/src -DMUTTER_LIBEXECDIR=\"$(libexecdir)\" -DHOST_ALIAS=\"@HOST_ALIAS@\" -DMUTTER_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\" -DMUTTER_PKGDATADIR=\"$(pkgdatadir)\" -DMUTTER_DATADIR=\"$(datadir)\" -DG_LOG_DOMAIN=\"mutter\" -DSN_API_NOT_YET_FROZEN=1 -DMUTTER_MAJOR_VERSION=$(MUTTER_MAJOR_VERSION) -DMUTTER_MINOR_VERSION=$(MUTTER_MINOR_VERSION) -DMUTTER_MICRO_VERSION=$(MUTTER_MICRO_VERSION) -DMUTTER_PLUGIN_API_VERSION=$(MUTTER_PLUGIN_API_VERSION) -DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\"
|
||||
AM_CPPFLAGS = \
|
||||
$(MUTTER_CFLAGS) \
|
||||
-I$(top_builddir)/src \
|
||||
-I$(top_srcdir)/src \
|
||||
-DMUTTER_LIBEXECDIR=\"$(libexecdir)\" \
|
||||
-DMUTTER_LOCALEDIR=\"$(localedir)\" \
|
||||
-DMUTTER_PKGDATADIR=\"$(pkgdatadir)\" \
|
||||
-DMUTTER_DATADIR=\"$(datadir)\" \
|
||||
-DG_LOG_DOMAIN=\"mutter\" \
|
||||
-DSN_API_NOT_YET_FROZEN=1 \
|
||||
-DMUTTER_PLUGIN_DIR=\"$(MUTTER_PLUGIN_DIR)\"
|
||||
|
||||
default_la_CFLAGS = -fPIC
|
||||
default_la_SOURCES = default.c
|
||||
default_la_LDFLAGS = -module -avoid-version -no-undefined
|
||||
default_la_LIBADD = @CLUTTER_LIBS@
|
||||
default_la_LIBADD = $(CLUTTER_LIBS)
|
||||
|
||||
pkglib_LTLIBRARIES = default.la
|
||||
|
||||
|
120
src/core/bell.c
120
src/core/bell.c
@@ -69,12 +69,9 @@
|
||||
*
|
||||
* If the configure script found we had no XKB, this does not exist.
|
||||
*/
|
||||
#ifdef HAVE_XKB
|
||||
static void
|
||||
bell_flash_fullscreen (MetaDisplay *display,
|
||||
XkbAnyEvent *xkb_ev)
|
||||
bell_flash_fullscreen (MetaDisplay *display)
|
||||
{
|
||||
g_assert (xkb_ev->xkb_type == XkbBellNotify);
|
||||
meta_compositor_flash_screen (display->compositor, display->screen);
|
||||
}
|
||||
|
||||
@@ -139,30 +136,17 @@ bell_flash_window_frame (MetaWindow *window)
|
||||
* @display: The display the bell event came in on
|
||||
* @xkb_ev: The bell event we just received
|
||||
*
|
||||
* Flashes the frame of the focussed window. If there is no focussed window,
|
||||
* Flashes the frame of the focused window. If there is no focused window,
|
||||
* flashes the screen.
|
||||
*/
|
||||
static void
|
||||
bell_flash_frame (MetaDisplay *display,
|
||||
XkbAnyEvent *xkb_ev)
|
||||
MetaWindow *window)
|
||||
{
|
||||
XkbBellNotifyEvent *xkb_bell_event = (XkbBellNotifyEvent *) xkb_ev;
|
||||
MetaWindow *window;
|
||||
|
||||
g_assert (xkb_ev->xkb_type == XkbBellNotify);
|
||||
window = meta_display_lookup_x_window (display, xkb_bell_event->window);
|
||||
if (!window && (display->focus_window))
|
||||
{
|
||||
window = display->focus_window;
|
||||
}
|
||||
if (window && window->frame)
|
||||
{
|
||||
bell_flash_window_frame (window);
|
||||
}
|
||||
else /* revert to fullscreen flash if there's no focussed window */
|
||||
{
|
||||
bell_flash_fullscreen (display, xkb_ev);
|
||||
}
|
||||
bell_flash_window_frame (window);
|
||||
else
|
||||
bell_flash_fullscreen (display);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -172,69 +156,73 @@ bell_flash_frame (MetaDisplay *display,
|
||||
*
|
||||
* Gives the user some kind of visual bell substitute, in response to a
|
||||
* bell event. What this is depends on the "visual bell type" pref.
|
||||
*
|
||||
* If the configure script found we had no XKB, this does not exist.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Bug: This should be merged with meta_bell_notify().
|
||||
*/
|
||||
static void
|
||||
bell_visual_notify (MetaDisplay *display,
|
||||
XkbAnyEvent *xkb_ev)
|
||||
MetaWindow *window)
|
||||
{
|
||||
switch (meta_prefs_get_visual_bell_type ())
|
||||
{
|
||||
case G_DESKTOP_VISUAL_BELL_FULLSCREEN_FLASH:
|
||||
bell_flash_fullscreen (display, xkb_ev);
|
||||
bell_flash_fullscreen (display);
|
||||
break;
|
||||
case G_DESKTOP_VISUAL_BELL_FRAME_FLASH:
|
||||
bell_flash_frame (display, xkb_ev); /* does nothing yet */
|
||||
bell_flash_frame (display, window);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
bell_audible_notify (MetaDisplay *display,
|
||||
MetaWindow *window)
|
||||
{
|
||||
#ifdef HAVE_LIBCANBERRA
|
||||
ca_proplist *p;
|
||||
int res;
|
||||
|
||||
ca_proplist_create (&p);
|
||||
ca_proplist_sets (p, CA_PROP_EVENT_ID, "bell-window-system");
|
||||
ca_proplist_sets (p, CA_PROP_EVENT_DESCRIPTION, _("Bell event"));
|
||||
ca_proplist_sets (p, CA_PROP_CANBERRA_CACHE_CONTROL, "permanent");
|
||||
|
||||
if (window)
|
||||
{
|
||||
ca_proplist_sets (p, CA_PROP_WINDOW_NAME, window->title);
|
||||
ca_proplist_setf (p, CA_PROP_WINDOW_X11_XID, "%lu", (unsigned long)window->xwindow);
|
||||
ca_proplist_sets (p, CA_PROP_APPLICATION_NAME, window->res_name);
|
||||
ca_proplist_setf (p, CA_PROP_APPLICATION_PROCESS_ID, "%d", window->net_wm_pid);
|
||||
}
|
||||
|
||||
res = ca_context_play_full (ca_gtk_context_get (), 1, p, NULL, NULL);
|
||||
|
||||
ca_proplist_destroy (p);
|
||||
|
||||
return res == CA_SUCCESS || res == CA_ERROR_DISABLED;
|
||||
#endif /* HAVE_LIBCANBERRA */
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_bell_notify (MetaDisplay *display,
|
||||
XkbAnyEvent *xkb_ev)
|
||||
{
|
||||
MetaWindow *window;
|
||||
XkbBellNotifyEvent *xkb_bell_event = (XkbBellNotifyEvent*) xkb_ev;
|
||||
|
||||
window = meta_display_lookup_x_window (display, xkb_bell_event->window);
|
||||
if (!window && display->focus_window && display->focus_window->frame)
|
||||
window = display->focus_window;
|
||||
|
||||
/* flash something */
|
||||
if (meta_prefs_get_visual_bell ())
|
||||
bell_visual_notify (display, xkb_ev);
|
||||
bell_visual_notify (display, window);
|
||||
|
||||
#ifdef HAVE_LIBCANBERRA
|
||||
if (meta_prefs_bell_is_audible ())
|
||||
{
|
||||
ca_proplist *p;
|
||||
XkbBellNotifyEvent *xkb_bell_event = (XkbBellNotifyEvent*) xkb_ev;
|
||||
MetaWindow *window;
|
||||
int res;
|
||||
|
||||
ca_proplist_create (&p);
|
||||
ca_proplist_sets (p, CA_PROP_EVENT_ID, "bell-window-system");
|
||||
ca_proplist_sets (p, CA_PROP_EVENT_DESCRIPTION, _("Bell event"));
|
||||
ca_proplist_sets (p, CA_PROP_CANBERRA_CACHE_CONTROL, "permanent");
|
||||
|
||||
window = meta_display_lookup_x_window (display, xkb_bell_event->window);
|
||||
if (!window && (display->focus_window) && (display->focus_window->frame))
|
||||
window = display->focus_window;
|
||||
|
||||
if (window)
|
||||
if (!bell_audible_notify (display, window))
|
||||
{
|
||||
ca_proplist_sets (p, CA_PROP_WINDOW_NAME, window->title);
|
||||
ca_proplist_setf (p, CA_PROP_WINDOW_X11_XID, "%lu", (unsigned long)window->xwindow);
|
||||
ca_proplist_sets (p, CA_PROP_APPLICATION_NAME, window->res_name);
|
||||
ca_proplist_setf (p, CA_PROP_APPLICATION_PROCESS_ID, "%d", window->net_wm_pid);
|
||||
}
|
||||
|
||||
/* First, we try to play a real sound ... */
|
||||
res = ca_context_play_full (ca_gtk_context_get (), 1, p, NULL, NULL);
|
||||
|
||||
ca_proplist_destroy (p);
|
||||
|
||||
if (res != CA_SUCCESS && res != CA_ERROR_DISABLED)
|
||||
{
|
||||
/* ...and in case that failed we use the classic X11 bell. */
|
||||
/* Force a classic bell if the libcanberra bell failed. */
|
||||
XkbForceDeviceBell (display->xdisplay,
|
||||
xkb_bell_event->device,
|
||||
xkb_bell_event->bell_class,
|
||||
@@ -242,14 +230,11 @@ meta_bell_notify (MetaDisplay *display,
|
||||
xkb_bell_event->percent);
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_LIBCANBERRA */
|
||||
}
|
||||
#endif /* HAVE_XKB */
|
||||
|
||||
void
|
||||
meta_bell_set_audible (MetaDisplay *display, gboolean audible)
|
||||
{
|
||||
#ifdef HAVE_XKB
|
||||
#ifdef HAVE_LIBCANBERRA
|
||||
/* When we are playing sounds using libcanberra support, we handle the
|
||||
* bell whether its an audible bell or a visible bell */
|
||||
@@ -262,13 +247,11 @@ meta_bell_set_audible (MetaDisplay *display, gboolean audible)
|
||||
XkbUseCoreKbd,
|
||||
XkbAudibleBellMask,
|
||||
enable_system_bell ? XkbAudibleBellMask : 0);
|
||||
#endif /* HAVE_XKB */
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_bell_init (MetaDisplay *display)
|
||||
{
|
||||
#ifdef HAVE_XKB
|
||||
int xkb_base_error_type, xkb_opcode;
|
||||
|
||||
if (!XkbQueryExtension (display->xdisplay, &xkb_opcode,
|
||||
@@ -298,20 +281,17 @@ meta_bell_init (MetaDisplay *display)
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_bell_shutdown (MetaDisplay *display)
|
||||
{
|
||||
#ifdef HAVE_XKB
|
||||
/* TODO: persist initial bell state in display, reset here */
|
||||
XkbChangeEnabledControls (display->xdisplay,
|
||||
XkbUseCoreKbd,
|
||||
XkbAudibleBellMask,
|
||||
XkbAudibleBellMask);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -18,13 +18,10 @@
|
||||
*/
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#ifdef HAVE_XKB
|
||||
#include <X11/XKBlib.h>
|
||||
#endif
|
||||
#include "display-private.h"
|
||||
#include "frame.h"
|
||||
|
||||
#ifdef HAVE_XKB
|
||||
/**
|
||||
* meta_bell_notify:
|
||||
* @display: The display the bell event came in on
|
||||
@@ -37,7 +34,6 @@
|
||||
* If the configure script found we had no XKB, this does not exist.
|
||||
*/
|
||||
void meta_bell_notify (MetaDisplay *display, XkbAnyEvent *xkb_ev);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* meta_bell_set_audible:
|
||||
@@ -61,12 +57,6 @@ void meta_bell_set_audible (MetaDisplay *display, gboolean audible);
|
||||
* to send us bell notifications, and then also switching
|
||||
* off the audible bell if we're using a visual one ourselves.
|
||||
*
|
||||
* Unlike most X extensions we use, we only initialise XKB here
|
||||
* (rather than in main()). It's possible that XKB is not
|
||||
* installed at all, but if that was known at build time
|
||||
* we will have HAVE_XKB undefined, which will cause this
|
||||
* function to be a no-op.
|
||||
*
|
||||
* \bug There is a line of code that's never run that tells
|
||||
* XKB to reset the bell status after we quit. Bill H said
|
||||
* (<http://bugzilla.gnome.org/show_bug.cgi?id=99886#c12>)
|
||||
|
@@ -546,6 +546,26 @@ compare_rect_areas (gconstpointer a, gconstpointer b)
|
||||
return b_area - a_area; /* positive ret value denotes b > a, ... */
|
||||
}
|
||||
|
||||
/* ... and another helper for get_minimal_spanning_set_for_region()... */
|
||||
static gboolean
|
||||
check_strut_align (MetaStrut *strut, const MetaRectangle *rect)
|
||||
{
|
||||
/* Check whether @strut actually aligns to the side of @rect it claims */
|
||||
switch (strut->side)
|
||||
{
|
||||
case META_SIDE_TOP:
|
||||
return BOX_TOP (strut->rect) <= BOX_TOP (*rect);
|
||||
case META_SIDE_BOTTOM:
|
||||
return BOX_BOTTOM (strut->rect) >= BOX_BOTTOM (*rect);
|
||||
case META_SIDE_LEFT:
|
||||
return BOX_LEFT (strut->rect) <= BOX_LEFT (*rect);
|
||||
case META_SIDE_RIGHT:
|
||||
return BOX_RIGHT (strut->rect) >= BOX_RIGHT (*rect);
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_rectangle_get_minimal_spanning_set_for_region:
|
||||
* @basic_rect: Input rectangle
|
||||
@@ -630,7 +650,8 @@ meta_rectangle_get_minimal_spanning_set_for_region (
|
||||
for (strut_iter = all_struts; strut_iter; strut_iter = strut_iter->next)
|
||||
{
|
||||
GList *rect_iter;
|
||||
MetaRectangle *strut_rect = &((MetaStrut*)strut_iter->data)->rect;
|
||||
MetaStrut *strut = (MetaStrut*)strut_iter->data;
|
||||
MetaRectangle *strut_rect = &strut->rect;
|
||||
|
||||
tmp_list = ret;
|
||||
ret = NULL;
|
||||
@@ -638,7 +659,9 @@ meta_rectangle_get_minimal_spanning_set_for_region (
|
||||
while (rect_iter)
|
||||
{
|
||||
MetaRectangle *rect = (MetaRectangle*) rect_iter->data;
|
||||
if (!meta_rectangle_overlap (rect, strut_rect))
|
||||
|
||||
if (!meta_rectangle_overlap (strut_rect, rect) ||
|
||||
!check_strut_align (strut, basic_rect))
|
||||
ret = g_list_prepend (ret, rect);
|
||||
else
|
||||
{
|
||||
|
@@ -404,31 +404,6 @@ setup_constraint_info (ConstraintInfo *info,
|
||||
meta_workspace_get_onmonitor_region (cur_workspace,
|
||||
monitor_info->number);
|
||||
|
||||
/* Workaround braindead legacy apps that don't know how to
|
||||
* fullscreen themselves properly - don't get fooled by
|
||||
* windows which hide their titlebar when maximized or which are
|
||||
* client decorated; that's not the same as fullscreen, even
|
||||
* if there are no struts making the workarea smaller than
|
||||
* the monitor.
|
||||
*/
|
||||
if (meta_prefs_get_force_fullscreen() &&
|
||||
window->client_type != META_WINDOW_CLIENT_TYPE_WAYLAND &&
|
||||
!window->hide_titlebar_when_maximized &&
|
||||
(window->decorated || !meta_window_is_client_decorated (window)) &&
|
||||
meta_rectangle_equal (new, &monitor_info->rect) &&
|
||||
window->has_fullscreen_func &&
|
||||
!window->fullscreen)
|
||||
{
|
||||
/*
|
||||
meta_topic (META_DEBUG_GEOMETRY,
|
||||
*/
|
||||
meta_warning (
|
||||
"Treating resize request of legacy application %s as a "
|
||||
"fullscreen request\n",
|
||||
window->desc);
|
||||
meta_window_make_fullscreen_internal (window);
|
||||
}
|
||||
|
||||
/* Log all this information for debugging */
|
||||
meta_topic (META_DEBUG_GEOMETRY,
|
||||
"Setting up constraint info:\n"
|
||||
@@ -613,7 +588,7 @@ update_onscreen_requirements (MetaWindow *window,
|
||||
window->require_fully_onscreen =
|
||||
meta_rectangle_contained_in_region (info->usable_screen_region,
|
||||
&info->current);
|
||||
if (old ^ window->require_fully_onscreen)
|
||||
if (old != window->require_fully_onscreen)
|
||||
meta_topic (META_DEBUG_GEOMETRY,
|
||||
"require_fully_onscreen for %s toggled to %s\n",
|
||||
window->desc,
|
||||
@@ -626,7 +601,7 @@ update_onscreen_requirements (MetaWindow *window,
|
||||
window->require_on_single_monitor =
|
||||
meta_rectangle_contained_in_region (info->usable_monitor_region,
|
||||
&info->current);
|
||||
if (old ^ window->require_on_single_monitor)
|
||||
if (old != window->require_on_single_monitor)
|
||||
meta_topic (META_DEBUG_GEOMETRY,
|
||||
"require_on_single_monitor for %s toggled to %s\n",
|
||||
window->desc,
|
||||
@@ -645,7 +620,7 @@ update_onscreen_requirements (MetaWindow *window,
|
||||
window->require_titlebar_visible =
|
||||
meta_rectangle_overlaps_with_region (info->usable_screen_region,
|
||||
&titlebar_rect);
|
||||
if (old ^ window->require_titlebar_visible)
|
||||
if (old != window->require_titlebar_visible)
|
||||
meta_topic (META_DEBUG_GEOMETRY,
|
||||
"require_titlebar_visible for %s toggled to %s\n",
|
||||
window->desc,
|
||||
|
@@ -392,6 +392,22 @@ meta_core_show_window_menu (Display *xdisplay,
|
||||
meta_window_show_menu (window, menu, root_x, root_y);
|
||||
}
|
||||
|
||||
void
|
||||
meta_core_show_window_menu_for_rect (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
MetaWindowMenuType menu,
|
||||
MetaRectangle *rect,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaWindow *window = get_window (xdisplay, frame_xwindow);
|
||||
|
||||
if (meta_prefs_get_raise_on_click ())
|
||||
meta_window_raise (window);
|
||||
meta_window_focus (window, timestamp);
|
||||
|
||||
meta_window_show_menu_for_rect (window, menu, rect);
|
||||
}
|
||||
|
||||
const char*
|
||||
meta_core_get_workspace_name_with_index (Display *xdisplay,
|
||||
Window xroot,
|
||||
@@ -479,46 +495,5 @@ meta_core_set_screen_cursor (Display *xdisplay,
|
||||
void
|
||||
meta_invalidate_default_icons (void)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
GSList *windows;
|
||||
GSList *l;
|
||||
|
||||
if (display == NULL)
|
||||
return; /* We can validly be called before the display is opened. */
|
||||
|
||||
windows = meta_display_list_windows (display, META_LIST_DEFAULT);
|
||||
for (l = windows; l != NULL; l = l->next)
|
||||
{
|
||||
MetaWindow *window = (MetaWindow*)l->data;
|
||||
|
||||
if (window->icon_cache.origin == USING_FALLBACK_ICON)
|
||||
{
|
||||
meta_icon_cache_free (&(window->icon_cache));
|
||||
meta_window_update_icon_now (window);
|
||||
}
|
||||
}
|
||||
|
||||
g_slist_free (windows);
|
||||
}
|
||||
|
||||
void
|
||||
meta_core_add_old_event_mask (Display *xdisplay,
|
||||
Window xwindow,
|
||||
XIEventMask *mask)
|
||||
{
|
||||
XIEventMask *prev;
|
||||
gint n_masks, i, j;
|
||||
|
||||
prev = XIGetSelectedEvents (xdisplay, xwindow, &n_masks);
|
||||
|
||||
for (i = 0; i < n_masks; i++)
|
||||
{
|
||||
if (prev[i].deviceid != XIAllMasterDevices)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < MIN (mask->mask_len, prev[i].mask_len); j++)
|
||||
mask->mask[j] |= prev[i].mask[j];
|
||||
}
|
||||
|
||||
XFree (prev);
|
||||
/* XXX: Actually invalidate the icons when they're used. */
|
||||
}
|
||||
|
@@ -26,6 +26,7 @@
|
||||
/* Don't include core headers here */
|
||||
#include <gdk/gdkx.h>
|
||||
#include <meta/common.h>
|
||||
#include <meta/boxes.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
@@ -138,6 +139,12 @@ void meta_core_show_window_menu (Display *xdisplay,
|
||||
int root_y,
|
||||
guint32 timestamp);
|
||||
|
||||
void meta_core_show_window_menu_for_rect (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
MetaWindowMenuType menu,
|
||||
MetaRectangle *rect,
|
||||
guint32 timestamp);
|
||||
|
||||
gboolean meta_core_begin_grab_op (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
MetaGrabOp op,
|
||||
@@ -162,8 +169,4 @@ void meta_core_set_screen_cursor (Display *xdisplay,
|
||||
|
||||
void meta_invalidate_default_icons (void);
|
||||
|
||||
void meta_core_add_old_event_mask (Display *xdisplay,
|
||||
Window xwindow,
|
||||
XIEventMask *mask);
|
||||
|
||||
#endif
|
||||
|
@@ -37,8 +37,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "wayland/meta-wayland-surface.h"
|
||||
|
||||
static void
|
||||
dialog_exited (GPid pid, int status, gpointer user_data)
|
||||
{
|
||||
|
@@ -35,6 +35,7 @@
|
||||
#include <meta/boxes.h>
|
||||
#include <meta/display.h>
|
||||
#include "keybindings-private.h"
|
||||
#include "meta-gesture-tracker-private.h"
|
||||
#include <meta/prefs.h>
|
||||
#include <meta/barrier.h>
|
||||
#include <clutter/clutter.h>
|
||||
@@ -78,6 +79,24 @@ typedef enum {
|
||||
META_TILE_MAXIMIZED
|
||||
} MetaTileMode;
|
||||
|
||||
typedef enum {
|
||||
/* Normal interaction where you're interacting with windows.
|
||||
* Events go to windows normally. */
|
||||
META_EVENT_ROUTE_NORMAL,
|
||||
|
||||
/* In a compositor grab operation. All events go to the
|
||||
* compositor plugin. */
|
||||
META_EVENT_ROUTE_COMPOSITOR_GRAB,
|
||||
|
||||
/* A Wayland application has a popup open. All events go to
|
||||
* the Wayland application. */
|
||||
META_EVENT_ROUTE_WAYLAND_POPUP,
|
||||
|
||||
/* In a window operation like moving or resizing. All events
|
||||
* goes to MetaWindow, but not to the actual client window. */
|
||||
META_EVENT_ROUTE_WINDOW_OP,
|
||||
} MetaEventRoute;
|
||||
|
||||
struct _MetaDisplay
|
||||
{
|
||||
GObject parent_instance;
|
||||
@@ -145,8 +164,6 @@ struct _MetaDisplay
|
||||
GHashTable *xids;
|
||||
GHashTable *wayland_windows;
|
||||
|
||||
int server_grab_count;
|
||||
|
||||
/* serials of leave/unmap events that may
|
||||
* correspond to an enter event we should
|
||||
* ignore
|
||||
@@ -175,13 +192,12 @@ struct _MetaDisplay
|
||||
guint autoraise_timeout_id;
|
||||
MetaWindow* autoraise_window;
|
||||
|
||||
/* Alt+click button grabs */
|
||||
ClutterModifierType window_grab_modifiers;
|
||||
/* Event routing */
|
||||
MetaEventRoute event_route;
|
||||
|
||||
/* current window operation */
|
||||
MetaGrabOp grab_op;
|
||||
MetaWindow *grab_window;
|
||||
Window grab_xwindow;
|
||||
int grab_button;
|
||||
int grab_anchor_root_x;
|
||||
int grab_anchor_root_y;
|
||||
@@ -202,34 +218,17 @@ struct _MetaDisplay
|
||||
GTimeVal grab_last_moveresize_time;
|
||||
MetaEdgeResistanceData *grab_edge_resistance_data;
|
||||
unsigned int grab_last_user_action_was_snap;
|
||||
guint32 grab_timestamp;
|
||||
|
||||
/* we use property updates as sentinels for certain window focus events
|
||||
* to avoid some race conditions on EnterNotify events
|
||||
*/
|
||||
int sentinel_counter;
|
||||
|
||||
#ifdef HAVE_XKB
|
||||
int xkb_base_event_type;
|
||||
guint32 last_bell_time;
|
||||
#endif
|
||||
int grab_resize_timeout_id;
|
||||
|
||||
/* Keybindings stuff */
|
||||
GHashTable *key_bindings;
|
||||
GHashTable *key_bindings_index;
|
||||
int min_keycode;
|
||||
int max_keycode;
|
||||
KeySym *keymap;
|
||||
int keysyms_per_keycode;
|
||||
unsigned int ignored_modifier_mask;
|
||||
unsigned int hyper_mask;
|
||||
unsigned int super_mask;
|
||||
unsigned int meta_mask;
|
||||
MetaKeyCombo overlay_key_combo;
|
||||
gboolean overlay_key_only_pressed;
|
||||
MetaKeyCombo *iso_next_group_combos;
|
||||
int n_iso_next_group_combos;
|
||||
MetaKeyBindingManager key_binding_manager;
|
||||
|
||||
/* Monitor cache */
|
||||
unsigned int monitor_cache_invalidated : 1;
|
||||
@@ -254,6 +253,9 @@ struct _MetaDisplay
|
||||
/* Managed by compositor.c */
|
||||
MetaCompositor *compositor;
|
||||
|
||||
MetaGestureTracker *gesture_tracker;
|
||||
ClutterEventSequence *pointer_emulating_sequence;
|
||||
|
||||
int composite_event_base;
|
||||
int composite_error_base;
|
||||
int composite_major_version;
|
||||
@@ -312,8 +314,6 @@ struct _MetaDisplayClass
|
||||
gboolean meta_display_open (void);
|
||||
void meta_display_close (MetaDisplay *display,
|
||||
guint32 timestamp);
|
||||
void meta_display_grab (MetaDisplay *display);
|
||||
void meta_display_ungrab (MetaDisplay *display);
|
||||
|
||||
void meta_display_unmanage_windows_for_screen (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
@@ -398,14 +398,8 @@ int meta_resize_gravity_from_grab_op (MetaGrabOp op);
|
||||
|
||||
gboolean meta_grab_op_is_moving (MetaGrabOp op);
|
||||
gboolean meta_grab_op_is_resizing (MetaGrabOp op);
|
||||
gboolean meta_grab_op_is_moving_or_resizing (MetaGrabOp op);
|
||||
gboolean meta_grab_op_is_mouse (MetaGrabOp op);
|
||||
gboolean meta_grab_op_is_keyboard (MetaGrabOp op);
|
||||
gboolean meta_grab_op_should_block_wayland (MetaGrabOp op);
|
||||
|
||||
void meta_display_devirtualize_modifiers (MetaDisplay *display,
|
||||
MetaVirtualModifier modifiers,
|
||||
unsigned int *mask);
|
||||
|
||||
void meta_display_increment_focus_sentinel (MetaDisplay *display);
|
||||
void meta_display_decrement_focus_sentinel (MetaDisplay *display);
|
||||
@@ -443,4 +437,20 @@ void meta_display_sanity_check_timestamps (MetaDisplay *display,
|
||||
gboolean meta_display_timestamp_too_old (MetaDisplay *display,
|
||||
guint32 *timestamp);
|
||||
|
||||
void meta_display_remove_pending_pings_for_window (MetaDisplay *display,
|
||||
MetaWindow *window);
|
||||
|
||||
MetaGestureTracker * meta_display_get_gesture_tracker (MetaDisplay *display);
|
||||
|
||||
gboolean meta_display_show_restart_message (MetaDisplay *display,
|
||||
const char *message);
|
||||
gboolean meta_display_request_restart (MetaDisplay *display);
|
||||
|
||||
void meta_restart_init (void);
|
||||
void meta_restart_finish (void);
|
||||
|
||||
void meta_display_cancel_touch (MetaDisplay *display);
|
||||
|
||||
gboolean meta_display_windows_are_interactable (MetaDisplay *display);
|
||||
|
||||
#endif
|
||||
|
1097
src/core/display.c
1097
src/core/display.c
File diff suppressed because it is too large
Load Diff
1959
src/core/events.c
1959
src/core/events.c
File diff suppressed because it is too large
Load Diff
@@ -29,4 +29,3 @@ void meta_display_init_events (MetaDisplay *display);
|
||||
void meta_display_free_events (MetaDisplay *display);
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -26,14 +26,11 @@
|
||||
#include "bell.h"
|
||||
#include <meta/errors.h>
|
||||
#include "keybindings-private.h"
|
||||
#include "backends/x11/meta-backend-x11.h"
|
||||
|
||||
#define EVENT_MASK (SubstructureRedirectMask | \
|
||||
StructureNotifyMask | SubstructureNotifyMask | \
|
||||
ExposureMask | \
|
||||
ButtonPressMask | ButtonReleaseMask | \
|
||||
PointerMotionMask | PointerMotionHintMask | \
|
||||
EnterWindowMask | LeaveWindowMask | \
|
||||
FocusChangeMask)
|
||||
ExposureMask | FocusChangeMask)
|
||||
|
||||
void
|
||||
meta_window_ensure_frame (MetaWindow *window)
|
||||
@@ -109,6 +106,19 @@ meta_window_ensure_frame (MetaWindow *window)
|
||||
XChangeWindowAttributes (window->display->xdisplay,
|
||||
frame->xwindow, CWEventMask, &attrs);
|
||||
|
||||
{
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||
|
||||
XISetMask (mask.mask, XI_ButtonPress);
|
||||
XISetMask (mask.mask, XI_ButtonRelease);
|
||||
XISetMask (mask.mask, XI_Motion);
|
||||
XISetMask (mask.mask, XI_Enter);
|
||||
XISetMask (mask.mask, XI_Leave);
|
||||
|
||||
XISelectEvents (window->display->xdisplay, frame->xwindow, &mask, 1);
|
||||
}
|
||||
|
||||
meta_display_register_x_window (window->display, &frame->xwindow, window);
|
||||
|
||||
meta_error_trap_push (window->display);
|
||||
@@ -141,7 +151,6 @@ meta_window_ensure_frame (MetaWindow *window)
|
||||
* style and background.
|
||||
*/
|
||||
meta_ui_update_frame_style (window->screen->ui, frame->xwindow);
|
||||
meta_ui_reset_frame_bg (window->screen->ui, frame->xwindow);
|
||||
|
||||
if (window->title)
|
||||
meta_ui_set_frame_title (window->screen->ui,
|
||||
@@ -150,10 +159,16 @@ meta_window_ensure_frame (MetaWindow *window)
|
||||
|
||||
meta_ui_map_frame (frame->window->screen->ui, frame->xwindow);
|
||||
|
||||
/* Since the backend takes keygrabs on another connection, make sure
|
||||
* to sync the GTK+ connection to ensure that the frame window has
|
||||
* been created on the server at this point. */
|
||||
XSync (window->display->xdisplay, False);
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
if (META_IS_BACKEND_X11 (backend))
|
||||
{
|
||||
/* Since the backend takes keygrabs on another connection, make sure
|
||||
* to sync the GTK+ connection to ensure that the frame window has
|
||||
* been created on the server at this point. */
|
||||
XSync (window->display->xdisplay, False);
|
||||
}
|
||||
}
|
||||
|
||||
/* Move keybindings to frame instead of window */
|
||||
meta_window_grab_keys (window);
|
||||
@@ -356,15 +371,6 @@ meta_frame_sync_to_window (MetaFrame *frame,
|
||||
frame->rect.x + frame->rect.width,
|
||||
frame->rect.y + frame->rect.height);
|
||||
|
||||
/* set bg to none to avoid flicker */
|
||||
if (need_resize)
|
||||
{
|
||||
meta_ui_unflicker_frame_bg (frame->window->screen->ui,
|
||||
frame->xwindow,
|
||||
frame->rect.width,
|
||||
frame->rect.height);
|
||||
}
|
||||
|
||||
meta_ui_move_resize_frame (frame->window->screen->ui,
|
||||
frame->xwindow,
|
||||
frame->rect.x,
|
||||
@@ -374,9 +380,6 @@ meta_frame_sync_to_window (MetaFrame *frame,
|
||||
|
||||
if (need_resize)
|
||||
{
|
||||
meta_ui_reset_frame_bg (frame->window->screen->ui,
|
||||
frame->xwindow);
|
||||
|
||||
/* If we're interactively resizing the frame, repaint
|
||||
* it immediately so we don't start to lag.
|
||||
*/
|
||||
|
@@ -29,6 +29,7 @@
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <meta/keybindings.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
typedef struct _MetaKeyHandler MetaKeyHandler;
|
||||
struct _MetaKeyHandler
|
||||
@@ -80,9 +81,6 @@ typedef struct
|
||||
*/
|
||||
GSList *combos;
|
||||
|
||||
/* for keybindings that can have shift or not like Alt+Tab */
|
||||
gboolean add_shift:1;
|
||||
|
||||
/* for keybindings that apply only to a window */
|
||||
gboolean per_window:1;
|
||||
|
||||
@@ -90,6 +88,23 @@ typedef struct
|
||||
gboolean builtin:1;
|
||||
} MetaKeyPref;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GHashTable *key_bindings;
|
||||
GHashTable *key_bindings_index;
|
||||
xkb_mod_mask_t ignored_modifier_mask;
|
||||
xkb_mod_mask_t hyper_mask;
|
||||
xkb_mod_mask_t super_mask;
|
||||
xkb_mod_mask_t meta_mask;
|
||||
MetaKeyCombo overlay_key_combo;
|
||||
gboolean overlay_key_only_pressed;
|
||||
MetaKeyCombo *iso_next_group_combos;
|
||||
int n_iso_next_group_combos;
|
||||
|
||||
/* Alt+click button grabs */
|
||||
ClutterModifierType window_grab_modifiers;
|
||||
} MetaKeyBindingManager;
|
||||
|
||||
void meta_display_init_keys (MetaDisplay *display);
|
||||
void meta_display_shutdown_keys (MetaDisplay *display);
|
||||
void meta_screen_grab_keys (MetaScreen *screen);
|
||||
@@ -103,8 +118,8 @@ void meta_window_ungrab_all_keys (MetaWindow *window,
|
||||
gboolean meta_keybindings_process_event (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
const ClutterEvent *event);
|
||||
void meta_display_process_mapping_event (MetaDisplay *display,
|
||||
XEvent *event);
|
||||
|
||||
ClutterModifierType meta_display_get_window_grab_modifiers (MetaDisplay *display);
|
||||
|
||||
gboolean meta_prefs_add_keybinding (const char *name,
|
||||
GSettings *settings,
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -52,6 +52,7 @@
|
||||
#include "ui.h"
|
||||
#include <meta/prefs.h>
|
||||
#include <meta/compositor.h>
|
||||
#include <meta/meta-backend.h>
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <glib-unix.h>
|
||||
@@ -77,8 +78,9 @@
|
||||
|
||||
#include "x11/session.h"
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
#include "wayland/meta-wayland.h"
|
||||
#include "backends/meta-backend.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The exit code we'll return to our parent process when we eventually die.
|
||||
@@ -94,26 +96,6 @@ static GMainLoop *meta_main_loop = NULL;
|
||||
static void prefs_changed_callback (MetaPreference pref,
|
||||
gpointer data);
|
||||
|
||||
/**
|
||||
* log_handler:
|
||||
* @log_domain: the domain the error occurred in (we ignore this)
|
||||
* @log_level: the log level so that we can filter out less
|
||||
* important messages
|
||||
* @message: the message to log
|
||||
* @user_data: arbitrary data (we ignore this)
|
||||
*
|
||||
* Prints log messages. If Mutter was compiled with backtrace support,
|
||||
* also prints a backtrace (see meta_print_backtrace()).
|
||||
*/
|
||||
static void
|
||||
log_handler (const gchar *log_domain,
|
||||
GLogLevelFlags log_level,
|
||||
const gchar *message,
|
||||
gpointer user_data)
|
||||
{
|
||||
meta_warning ("Log level %d: %s\n", log_level, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_print_compilation_info:
|
||||
*
|
||||
@@ -180,7 +162,9 @@ static gchar *opt_client_id;
|
||||
static gboolean opt_replace_wm;
|
||||
static gboolean opt_disable_sm;
|
||||
static gboolean opt_sync;
|
||||
#ifdef HAVE_WAYLAND
|
||||
static gboolean opt_wayland;
|
||||
#endif
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
static gboolean opt_display_server;
|
||||
#endif
|
||||
@@ -221,12 +205,14 @@ static GOptionEntry meta_options[] = {
|
||||
N_("Make X calls synchronous"),
|
||||
NULL
|
||||
},
|
||||
#ifdef HAVE_WAYLAND
|
||||
{
|
||||
"wayland", 0, 0, G_OPTION_ARG_NONE,
|
||||
&opt_wayland,
|
||||
N_("Run as a wayland compositor"),
|
||||
NULL
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
{
|
||||
"display-server", 0, 0, G_OPTION_ARG_NONE,
|
||||
@@ -291,8 +277,10 @@ meta_finalize (void)
|
||||
meta_display_close (display,
|
||||
CurrentTime); /* I doubt correct timestamps matter here */
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
if (meta_is_wayland_compositor ())
|
||||
meta_wayland_finalize ();
|
||||
#endif
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -339,9 +327,13 @@ meta_init (void)
|
||||
#if defined(CLUTTER_WINDOWING_EGL) && defined(HAVE_NATIVE_BACKEND)
|
||||
if (opt_display_server)
|
||||
clutter_set_windowing_backend (CLUTTER_WINDOWING_EGL);
|
||||
else
|
||||
#endif
|
||||
clutter_set_windowing_backend (CLUTTER_WINDOWING_X11);
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
meta_set_is_wayland_compositor (opt_wayland);
|
||||
#endif
|
||||
|
||||
if (g_get_home_dir ())
|
||||
if (chdir (g_get_home_dir ()) < 0)
|
||||
@@ -354,15 +346,24 @@ meta_init (void)
|
||||
g_irepository_prepend_search_path (MUTTER_PKGLIBDIR);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
/* NB: When running as a hybrid wayland compositor we run our own headless X
|
||||
* server so the user can't control the X display to connect too. */
|
||||
meta_wayland_init ();
|
||||
}
|
||||
else
|
||||
meta_wayland_pre_clutter_init ();
|
||||
#endif
|
||||
|
||||
/* NB: When running as a hybrid wayland compositor we run our own headless X
|
||||
* server so the user can't control the X display to connect too. */
|
||||
if (!meta_is_wayland_compositor ())
|
||||
meta_select_display (opt_display_name);
|
||||
|
||||
meta_clutter_init ();
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
/* Bring up Wayland. This also launches Xwayland and sets DISPLAY as well... */
|
||||
if (meta_is_wayland_compositor ())
|
||||
meta_wayland_init ();
|
||||
#endif
|
||||
|
||||
meta_set_syncing (opt_sync || (g_getenv ("MUTTER_SYNC") != NULL));
|
||||
|
||||
if (opt_replace_wm)
|
||||
@@ -375,17 +376,7 @@ meta_init (void)
|
||||
|
||||
meta_ui_init ();
|
||||
|
||||
/* If we are running with wayland then we don't wait until we have
|
||||
* an X connection before initializing clutter we instead initialize
|
||||
* it earlier since we need to initialize the GL driver so the driver
|
||||
* can register any needed wayland extensions. */
|
||||
if (!meta_is_wayland_compositor ())
|
||||
{
|
||||
/*
|
||||
* Clutter can only be initialized after the UI.
|
||||
*/
|
||||
meta_clutter_init ();
|
||||
}
|
||||
meta_restart_init ();
|
||||
|
||||
/*
|
||||
* XXX: We cannot handle high dpi scaling yet, so fix the scale to 1
|
||||
@@ -444,24 +435,10 @@ meta_register_with_session (void)
|
||||
int
|
||||
meta_run (void)
|
||||
{
|
||||
const gchar *log_domains[] = {
|
||||
NULL, G_LOG_DOMAIN, "Gtk", "Gdk", "GLib",
|
||||
"Pango", "GLib-GObject", "GThread"
|
||||
};
|
||||
guint i;
|
||||
|
||||
/* Load prefs */
|
||||
meta_prefs_init ();
|
||||
meta_prefs_add_listener (prefs_changed_callback, NULL);
|
||||
|
||||
for (i=0; i<G_N_ELEMENTS(log_domains); i++)
|
||||
g_log_set_handler (log_domains[i],
|
||||
G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,
|
||||
log_handler, NULL);
|
||||
|
||||
if (g_getenv ("MUTTER_G_FATAL_WARNINGS") != NULL)
|
||||
g_log_set_always_fatal (G_LOG_LEVEL_MASK);
|
||||
|
||||
meta_ui_set_current_theme (meta_prefs_get_theme ());
|
||||
|
||||
/* Try to find some theme that'll work if the theme preference
|
||||
|
@@ -309,9 +309,16 @@ accelerator_parse (const gchar *accelerator,
|
||||
keyval = xkb_keysym_from_name (accelerator, XKB_KEYSYM_CASE_INSENSITIVE);
|
||||
if (keyval == XKB_KEY_NoSymbol)
|
||||
{
|
||||
error = TRUE;
|
||||
goto out;
|
||||
}
|
||||
char *with_xf86 = g_strconcat ("XF86", accelerator, NULL);
|
||||
keyval = xkb_keysym_from_name (with_xf86, XKB_KEYSYM_CASE_INSENSITIVE);
|
||||
g_free (with_xf86);
|
||||
|
||||
if (keyval == XKB_KEY_NoSymbol)
|
||||
{
|
||||
error = TRUE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
accelerator += len;
|
||||
|
75
src/core/meta-gesture-tracker-private.h
Normal file
75
src/core/meta-gesture-tracker-private.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/* -*- 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>
|
||||
*/
|
||||
|
||||
#ifndef META_GESTURE_TRACKER_PRIVATE_H
|
||||
#define META_GESTURE_TRACKER_PRIVATE_H
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <clutter/clutter.h>
|
||||
#include <meta/window.h>
|
||||
|
||||
#define META_TYPE_GESTURE_TRACKER (meta_gesture_tracker_get_type ())
|
||||
#define META_GESTURE_TRACKER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_GESTURE_TRACKER, MetaGestureTracker))
|
||||
#define META_GESTURE_TRACKER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_GESTURE_TRACKER, MetaGestureTrackerClass))
|
||||
#define META_IS_GESTURE_TRACKER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_GESTURE_TRACKER))
|
||||
#define META_IS_GESTURE_TRACKER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_GESTURE_TRACKER))
|
||||
#define META_GESTURE_TRACKER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_GESTURE_TRACKER, MetaGestureTrackerClass))
|
||||
|
||||
typedef struct _MetaGestureTracker MetaGestureTracker;
|
||||
typedef struct _MetaGestureTrackerClass MetaGestureTrackerClass;
|
||||
|
||||
typedef enum {
|
||||
META_SEQUENCE_NONE,
|
||||
META_SEQUENCE_ACCEPTED,
|
||||
META_SEQUENCE_REJECTED,
|
||||
META_SEQUENCE_PENDING_END
|
||||
} MetaSequenceState;
|
||||
|
||||
struct _MetaGestureTracker
|
||||
{
|
||||
GObject parent_instance;
|
||||
};
|
||||
|
||||
struct _MetaGestureTrackerClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (* state_changed) (MetaGestureTracker *tracker,
|
||||
ClutterEventSequence *sequence,
|
||||
MetaSequenceState state);
|
||||
};
|
||||
|
||||
GType meta_gesture_tracker_get_type (void) G_GNUC_CONST;
|
||||
|
||||
MetaGestureTracker * meta_gesture_tracker_new (void);
|
||||
|
||||
gboolean meta_gesture_tracker_handle_event (MetaGestureTracker *tracker,
|
||||
const ClutterEvent *event);
|
||||
gboolean meta_gesture_tracker_set_sequence_state (MetaGestureTracker *tracker,
|
||||
ClutterEventSequence *sequence,
|
||||
MetaSequenceState state);
|
||||
MetaSequenceState meta_gesture_tracker_get_sequence_state (MetaGestureTracker *tracker,
|
||||
ClutterEventSequence *sequence);
|
||||
gint meta_gesture_tracker_get_n_current_touches (MetaGestureTracker *tracker);
|
||||
|
||||
#endif /* META_GESTURE_TRACKER_PRIVATE_H */
|
582
src/core/meta-gesture-tracker.c
Normal file
582
src/core/meta-gesture-tracker.c
Normal file
@@ -0,0 +1,582 @@
|
||||
/*
|
||||
* 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>
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:gesture-tracker
|
||||
* @Title: MetaGestureTracker
|
||||
* @Short_Description: Manages gestures on windows/desktop
|
||||
*
|
||||
* Forwards touch events to clutter actors, and accepts/rejects touch sequences
|
||||
* based on the outcome of those.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "meta-gesture-tracker-private.h"
|
||||
#include "meta-surface-actor.h"
|
||||
|
||||
#define DISTANCE_THRESHOLD 30
|
||||
|
||||
typedef struct _MetaGestureTrackerPrivate MetaGestureTrackerPrivate;
|
||||
typedef struct _GestureActionData GestureActionData;
|
||||
typedef struct _MetaSequenceInfo MetaSequenceInfo;
|
||||
|
||||
struct _MetaSequenceInfo
|
||||
{
|
||||
MetaGestureTracker *tracker;
|
||||
ClutterEventSequence *sequence;
|
||||
MetaSequenceState state;
|
||||
guint autodeny_timeout_id;
|
||||
gfloat start_x;
|
||||
gfloat start_y;
|
||||
};
|
||||
|
||||
struct _GestureActionData
|
||||
{
|
||||
ClutterGestureAction *gesture;
|
||||
MetaSequenceState state;
|
||||
guint gesture_begin_id;
|
||||
guint gesture_end_id;
|
||||
guint gesture_cancel_id;
|
||||
};
|
||||
|
||||
struct _MetaGestureTrackerPrivate
|
||||
{
|
||||
GHashTable *sequences; /* Hashtable of ClutterEventSequence->MetaSequenceInfo */
|
||||
|
||||
MetaSequenceState stage_state;
|
||||
GArray *stage_gestures; /* Array of GestureActionData */
|
||||
GList *listeners; /* List of ClutterGestureAction */
|
||||
guint autodeny_timeout;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_AUTODENY_TIMEOUT,
|
||||
LAST_PROP,
|
||||
};
|
||||
|
||||
static GParamSpec *obj_props[LAST_PROP];
|
||||
|
||||
enum {
|
||||
STATE_CHANGED,
|
||||
N_SIGNALS
|
||||
};
|
||||
|
||||
static guint signals[N_SIGNALS] = { 0 };
|
||||
|
||||
#define DEFAULT_AUTODENY_TIMEOUT 150
|
||||
|
||||
static void meta_gesture_tracker_untrack_stage (MetaGestureTracker *tracker);
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaGestureTracker, meta_gesture_tracker, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
meta_gesture_tracker_finalize (GObject *object)
|
||||
{
|
||||
MetaGestureTrackerPrivate *priv;
|
||||
|
||||
priv = meta_gesture_tracker_get_instance_private (META_GESTURE_TRACKER (object));
|
||||
|
||||
g_hash_table_destroy (priv->sequences);
|
||||
g_array_free (priv->stage_gestures, TRUE);
|
||||
g_list_free (priv->listeners);
|
||||
|
||||
G_OBJECT_CLASS (meta_gesture_tracker_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_gesture_tracker_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaGestureTrackerPrivate *priv;
|
||||
|
||||
priv = meta_gesture_tracker_get_instance_private (META_GESTURE_TRACKER (object));
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_AUTODENY_TIMEOUT:
|
||||
priv->autodeny_timeout = g_value_get_uint (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_gesture_tracker_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaGestureTrackerPrivate *priv;
|
||||
|
||||
priv = meta_gesture_tracker_get_instance_private (META_GESTURE_TRACKER (object));
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_AUTODENY_TIMEOUT:
|
||||
g_value_set_uint (value, priv->autodeny_timeout);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_gesture_tracker_class_init (MetaGestureTrackerClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = meta_gesture_tracker_finalize;
|
||||
object_class->set_property = meta_gesture_tracker_set_property;
|
||||
object_class->get_property = meta_gesture_tracker_get_property;
|
||||
|
||||
obj_props[PROP_AUTODENY_TIMEOUT] = g_param_spec_uint ("autodeny-timeout",
|
||||
"Auto-deny timeout",
|
||||
"Auto-deny timeout",
|
||||
0, G_MAXUINT, DEFAULT_AUTODENY_TIMEOUT,
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
g_object_class_install_properties (object_class, LAST_PROP, obj_props);
|
||||
|
||||
signals[STATE_CHANGED] =
|
||||
g_signal_new ("state-changed",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (MetaGestureTrackerClass, state_changed),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_UINT);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
autodeny_sequence (gpointer user_data)
|
||||
{
|
||||
MetaSequenceInfo *info = user_data;
|
||||
|
||||
/* Deny the sequence automatically after the given timeout */
|
||||
if (info->state == META_SEQUENCE_NONE)
|
||||
meta_gesture_tracker_set_sequence_state (info->tracker, info->sequence,
|
||||
META_SEQUENCE_REJECTED);
|
||||
|
||||
info->autodeny_timeout_id = 0;
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static MetaSequenceInfo *
|
||||
meta_sequence_info_new (MetaGestureTracker *tracker,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
MetaGestureTrackerPrivate *priv;
|
||||
MetaSequenceInfo *info;
|
||||
guint ms;
|
||||
|
||||
priv = meta_gesture_tracker_get_instance_private (tracker);
|
||||
ms = priv->autodeny_timeout;
|
||||
|
||||
info = g_slice_new0 (MetaSequenceInfo);
|
||||
info->tracker = tracker;
|
||||
info->sequence = event->touch.sequence;
|
||||
info->state = META_SEQUENCE_NONE;
|
||||
info->autodeny_timeout_id = g_timeout_add (ms, autodeny_sequence, info);
|
||||
|
||||
clutter_event_get_coords (event, &info->start_x, &info->start_y);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_sequence_info_free (MetaSequenceInfo *info)
|
||||
{
|
||||
if (info->autodeny_timeout_id)
|
||||
g_source_remove (info->autodeny_timeout_id);
|
||||
|
||||
if (info->state == META_SEQUENCE_NONE)
|
||||
meta_gesture_tracker_set_sequence_state (info->tracker, info->sequence,
|
||||
META_SEQUENCE_REJECTED);
|
||||
g_slice_free (MetaSequenceInfo, info);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
state_is_applicable (MetaSequenceState prev_state,
|
||||
MetaSequenceState state)
|
||||
{
|
||||
if (prev_state == META_SEQUENCE_PENDING_END)
|
||||
return FALSE;
|
||||
|
||||
/* Don't allow reverting to none */
|
||||
if (state == META_SEQUENCE_NONE)
|
||||
return FALSE;
|
||||
|
||||
/* PENDING_END state is final */
|
||||
if (prev_state == META_SEQUENCE_PENDING_END)
|
||||
return FALSE;
|
||||
|
||||
/* Sequences must be accepted/denied before PENDING_END */
|
||||
if (prev_state == META_SEQUENCE_NONE &&
|
||||
state == META_SEQUENCE_PENDING_END)
|
||||
return FALSE;
|
||||
|
||||
/* Make sequences stick to their accepted/denied state */
|
||||
if (state != META_SEQUENCE_PENDING_END &&
|
||||
prev_state != META_SEQUENCE_NONE)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_gesture_tracker_set_state (MetaGestureTracker *tracker,
|
||||
MetaSequenceState state)
|
||||
{
|
||||
MetaGestureTrackerPrivate *priv;
|
||||
ClutterEventSequence *sequence;
|
||||
GHashTableIter iter;
|
||||
|
||||
priv = meta_gesture_tracker_get_instance_private (tracker);
|
||||
|
||||
if (priv->stage_state != state &&
|
||||
!state_is_applicable (priv->stage_state, state))
|
||||
return FALSE;
|
||||
|
||||
g_hash_table_iter_init (&iter, priv->sequences);
|
||||
priv->stage_state = state;
|
||||
|
||||
while (g_hash_table_iter_next (&iter, (gpointer*) &sequence, NULL))
|
||||
meta_gesture_tracker_set_sequence_state (tracker, sequence, state);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gesture_begin_cb (ClutterGestureAction *gesture,
|
||||
ClutterActor *actor,
|
||||
MetaGestureTracker *tracker)
|
||||
{
|
||||
MetaGestureTrackerPrivate *priv;
|
||||
|
||||
priv = meta_gesture_tracker_get_instance_private (tracker);
|
||||
|
||||
if (!g_list_find (priv->listeners, gesture) &&
|
||||
meta_gesture_tracker_set_state (tracker, META_SEQUENCE_ACCEPTED))
|
||||
priv->listeners = g_list_prepend (priv->listeners, gesture);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gesture_end_cb (ClutterGestureAction *gesture,
|
||||
ClutterActor *actor,
|
||||
MetaGestureTracker *tracker)
|
||||
{
|
||||
MetaGestureTrackerPrivate *priv;
|
||||
|
||||
priv = meta_gesture_tracker_get_instance_private (tracker);
|
||||
priv->listeners = g_list_remove (priv->listeners, gesture);
|
||||
|
||||
if (!priv->listeners)
|
||||
meta_gesture_tracker_untrack_stage (tracker);
|
||||
}
|
||||
|
||||
static void
|
||||
gesture_cancel_cb (ClutterGestureAction *gesture,
|
||||
ClutterActor *actor,
|
||||
MetaGestureTracker *tracker)
|
||||
{
|
||||
MetaGestureTrackerPrivate *priv;
|
||||
|
||||
priv = meta_gesture_tracker_get_instance_private (tracker);
|
||||
|
||||
if (g_list_find (priv->listeners, gesture))
|
||||
{
|
||||
priv->listeners = g_list_remove (priv->listeners, gesture);
|
||||
|
||||
if (!priv->listeners)
|
||||
meta_gesture_tracker_set_state (tracker, META_SEQUENCE_PENDING_END);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
cancel_and_unref_gesture_cb (ClutterGestureAction *action)
|
||||
{
|
||||
clutter_gesture_action_cancel (action);
|
||||
g_object_unref (action);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
clear_gesture_data (GestureActionData *data)
|
||||
{
|
||||
g_signal_handler_disconnect (data->gesture, data->gesture_begin_id);
|
||||
g_signal_handler_disconnect (data->gesture, data->gesture_end_id);
|
||||
g_signal_handler_disconnect (data->gesture, data->gesture_cancel_id);
|
||||
|
||||
/* Defer cancellation to an idle, as it may happen within event handling */
|
||||
g_idle_add ((GSourceFunc) cancel_and_unref_gesture_cb, data->gesture);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_gesture_tracker_init (MetaGestureTracker *tracker)
|
||||
{
|
||||
MetaGestureTrackerPrivate *priv;
|
||||
|
||||
priv = meta_gesture_tracker_get_instance_private (tracker);
|
||||
priv->sequences = g_hash_table_new_full (NULL, NULL, NULL,
|
||||
(GDestroyNotify) meta_sequence_info_free);
|
||||
priv->stage_gestures = g_array_new (FALSE, FALSE, sizeof (GestureActionData));
|
||||
g_array_set_clear_func (priv->stage_gestures, (GDestroyNotify) clear_gesture_data);
|
||||
}
|
||||
|
||||
MetaGestureTracker *
|
||||
meta_gesture_tracker_new (void)
|
||||
{
|
||||
return g_object_new (META_TYPE_GESTURE_TRACKER, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_gesture_tracker_track_stage (MetaGestureTracker *tracker,
|
||||
ClutterActor *stage)
|
||||
{
|
||||
MetaGestureTrackerPrivate *priv;
|
||||
GList *actions, *l;
|
||||
|
||||
priv = meta_gesture_tracker_get_instance_private (tracker);
|
||||
actions = clutter_actor_get_actions (stage);
|
||||
|
||||
for (l = actions; l; l = l->next)
|
||||
{
|
||||
GestureActionData data;
|
||||
|
||||
if (!CLUTTER_IS_GESTURE_ACTION (l->data))
|
||||
continue;
|
||||
|
||||
data.gesture = g_object_ref (l->data);
|
||||
data.state = META_SEQUENCE_NONE;
|
||||
data.gesture_begin_id =
|
||||
g_signal_connect (data.gesture, "gesture-begin",
|
||||
G_CALLBACK (gesture_begin_cb), tracker);
|
||||
data.gesture_end_id =
|
||||
g_signal_connect (data.gesture, "gesture-end",
|
||||
G_CALLBACK (gesture_end_cb), tracker);
|
||||
data.gesture_cancel_id =
|
||||
g_signal_connect (data.gesture, "gesture-cancel",
|
||||
G_CALLBACK (gesture_cancel_cb), tracker);
|
||||
g_array_append_val (priv->stage_gestures, data);
|
||||
}
|
||||
|
||||
g_list_free (actions);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_gesture_tracker_untrack_stage (MetaGestureTracker *tracker)
|
||||
{
|
||||
MetaGestureTrackerPrivate *priv;
|
||||
|
||||
priv = meta_gesture_tracker_get_instance_private (tracker);
|
||||
priv->stage_state = META_SEQUENCE_NONE;
|
||||
|
||||
g_hash_table_remove_all (priv->sequences);
|
||||
|
||||
if (priv->stage_gestures->len > 0)
|
||||
g_array_remove_range (priv->stage_gestures, 0, priv->stage_gestures->len);
|
||||
|
||||
g_list_free (priv->listeners);
|
||||
priv->listeners = NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_gesture_tracker_handle_event (MetaGestureTracker *tracker,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
MetaGestureTrackerPrivate *priv;
|
||||
ClutterEventSequence *sequence;
|
||||
MetaSequenceState state;
|
||||
MetaSequenceInfo *info;
|
||||
ClutterActor *stage;
|
||||
gfloat x, y;
|
||||
|
||||
sequence = clutter_event_get_event_sequence (event);
|
||||
|
||||
if (!sequence)
|
||||
return FALSE;
|
||||
|
||||
priv = meta_gesture_tracker_get_instance_private (tracker);
|
||||
stage = CLUTTER_ACTOR (clutter_event_get_stage (event));
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_TOUCH_BEGIN:
|
||||
if (g_hash_table_size (priv->sequences) == 0)
|
||||
meta_gesture_tracker_track_stage (tracker, stage);
|
||||
|
||||
info = meta_sequence_info_new (tracker, event);
|
||||
g_hash_table_insert (priv->sequences, sequence, info);
|
||||
|
||||
if (priv->stage_gestures->len == 0)
|
||||
{
|
||||
/* If no gestures are attached, reject the sequence right away */
|
||||
meta_gesture_tracker_set_sequence_state (tracker, sequence,
|
||||
META_SEQUENCE_REJECTED);
|
||||
}
|
||||
else if (priv->stage_state != META_SEQUENCE_NONE)
|
||||
{
|
||||
/* Make the sequence state match the general state */
|
||||
meta_gesture_tracker_set_sequence_state (tracker, sequence,
|
||||
priv->stage_state);
|
||||
}
|
||||
state = info->state;
|
||||
break;
|
||||
case CLUTTER_TOUCH_END:
|
||||
info = g_hash_table_lookup (priv->sequences, sequence);
|
||||
|
||||
if (!info)
|
||||
return FALSE;
|
||||
|
||||
/* If nothing was done yet about the sequence, reject it so X11
|
||||
* clients may see it
|
||||
*/
|
||||
if (info->state == META_SEQUENCE_NONE)
|
||||
meta_gesture_tracker_set_sequence_state (tracker, sequence,
|
||||
META_SEQUENCE_REJECTED);
|
||||
|
||||
state = info->state;
|
||||
g_hash_table_remove (priv->sequences, sequence);
|
||||
|
||||
if (g_hash_table_size (priv->sequences) == 0)
|
||||
meta_gesture_tracker_untrack_stage (tracker);
|
||||
break;
|
||||
case CLUTTER_TOUCH_UPDATE:
|
||||
info = g_hash_table_lookup (priv->sequences, sequence);
|
||||
|
||||
if (!info)
|
||||
return FALSE;
|
||||
|
||||
clutter_event_get_coords (event, &x, &y);
|
||||
|
||||
if (info->state == META_SEQUENCE_NONE &&
|
||||
(ABS (info->start_x - x) > DISTANCE_THRESHOLD ||
|
||||
ABS (info->start_y - y) > DISTANCE_THRESHOLD))
|
||||
meta_gesture_tracker_set_sequence_state (tracker, sequence,
|
||||
META_SEQUENCE_REJECTED);
|
||||
state = info->state;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* As soon as a sequence is accepted, we replay it to
|
||||
* the stage as a captured event, and make sure it's never
|
||||
* propagated anywhere else. Since ClutterGestureAction does
|
||||
* all its event handling from a captured-event handler on
|
||||
* the stage, this effectively acts as a "sequence grab" on
|
||||
* gesture actions.
|
||||
*
|
||||
* Sequences that aren't (yet or never) in an accepted state
|
||||
* will go through, these events will get processed through
|
||||
* the compositor, and eventually through clutter, still
|
||||
* triggering the gestures capturing events on the stage, and
|
||||
* possibly resulting in MetaSequenceState changes.
|
||||
*/
|
||||
if (state == META_SEQUENCE_ACCEPTED)
|
||||
{
|
||||
clutter_actor_event (CLUTTER_ACTOR (clutter_event_get_stage (event)),
|
||||
event, TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_gesture_tracker_set_sequence_state (MetaGestureTracker *tracker,
|
||||
ClutterEventSequence *sequence,
|
||||
MetaSequenceState state)
|
||||
{
|
||||
MetaGestureTrackerPrivate *priv;
|
||||
MetaSequenceInfo *info;
|
||||
|
||||
g_return_val_if_fail (META_IS_GESTURE_TRACKER (tracker), FALSE);
|
||||
|
||||
priv = meta_gesture_tracker_get_instance_private (tracker);
|
||||
info = g_hash_table_lookup (priv->sequences, sequence);
|
||||
|
||||
if (!info)
|
||||
return FALSE;
|
||||
else if (state == info->state)
|
||||
return TRUE;
|
||||
|
||||
if (!state_is_applicable (info->state, state))
|
||||
return FALSE;
|
||||
|
||||
/* Unset autodeny timeout */
|
||||
if (info->autodeny_timeout_id)
|
||||
{
|
||||
g_source_remove (info->autodeny_timeout_id);
|
||||
info->autodeny_timeout_id = 0;
|
||||
}
|
||||
|
||||
info->state = state;
|
||||
g_signal_emit (tracker, signals[STATE_CHANGED], 0, sequence, info->state);
|
||||
|
||||
/* If the sequence was denied, set immediately to PENDING_END after emission */
|
||||
if (state == META_SEQUENCE_REJECTED)
|
||||
{
|
||||
info->state = META_SEQUENCE_PENDING_END;
|
||||
g_signal_emit (tracker, signals[STATE_CHANGED], 0, sequence, info->state);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
MetaSequenceState
|
||||
meta_gesture_tracker_get_sequence_state (MetaGestureTracker *tracker,
|
||||
ClutterEventSequence *sequence)
|
||||
{
|
||||
MetaGestureTrackerPrivate *priv;
|
||||
MetaSequenceInfo *info;
|
||||
|
||||
g_return_val_if_fail (META_IS_GESTURE_TRACKER (tracker), META_SEQUENCE_PENDING_END);
|
||||
|
||||
priv = meta_gesture_tracker_get_instance_private (tracker);
|
||||
info = g_hash_table_lookup (priv->sequences, sequence);
|
||||
|
||||
if (!info)
|
||||
return META_SEQUENCE_PENDING_END;
|
||||
|
||||
return info->state;
|
||||
}
|
||||
|
||||
gint
|
||||
meta_gesture_tracker_get_n_current_touches (MetaGestureTracker *tracker)
|
||||
{
|
||||
MetaGestureTrackerPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (META_IS_GESTURE_TRACKER (tracker), 0);
|
||||
|
||||
priv = meta_gesture_tracker_get_instance_private (tracker);
|
||||
return g_hash_table_size (priv->sequences);
|
||||
}
|
138
src/core/prefs.c
138
src/core/prefs.c
@@ -28,7 +28,6 @@
|
||||
|
||||
#include <config.h>
|
||||
#include <meta/prefs.h>
|
||||
#include "ui.h"
|
||||
#include "util-private.h"
|
||||
#include "meta-plugin-manager.h"
|
||||
#include <glib.h>
|
||||
@@ -67,6 +66,7 @@
|
||||
#define SCHEMA_INTERFACE "org.gnome.desktop.interface"
|
||||
#define SCHEMA_INPUT_SOURCES "org.gnome.desktop.input-sources"
|
||||
#define SCHEMA_XSETTINGS "org.gnome.settings-daemon.plugins.xsettings"
|
||||
#define SCHEMA_MOUSE "org.gnome.settings-daemon.peripherals.mouse"
|
||||
|
||||
#define SETTINGS(s) g_hash_table_lookup (settings_schemas, (s))
|
||||
|
||||
@@ -101,6 +101,7 @@ static gboolean gnome_animations = TRUE;
|
||||
static char *cursor_theme = NULL;
|
||||
static int cursor_size = 24;
|
||||
static int draggable_border_width = 10;
|
||||
static int drag_threshold;
|
||||
static gboolean resize_with_right_button = FALSE;
|
||||
static gboolean edge_tiling = FALSE;
|
||||
static gboolean force_fullscreen = TRUE;
|
||||
@@ -492,6 +493,13 @@ static MetaIntPreference preferences_int[] =
|
||||
},
|
||||
&draggable_border_width
|
||||
},
|
||||
{
|
||||
{ "drag-threshold",
|
||||
SCHEMA_MOUSE,
|
||||
META_PREF_DRAG_THRESHOLD,
|
||||
},
|
||||
&drag_threshold
|
||||
},
|
||||
{ { NULL, 0, 0 }, NULL },
|
||||
};
|
||||
|
||||
@@ -978,6 +986,10 @@ meta_prefs_init (void)
|
||||
g_signal_connect (settings, "changed", G_CALLBACK (settings_changed), NULL);
|
||||
g_hash_table_insert (settings_schemas, g_strdup (SCHEMA_MUTTER), settings);
|
||||
|
||||
settings = g_settings_new (SCHEMA_MOUSE);
|
||||
g_signal_connect (settings, "changed", G_CALLBACK (settings_changed), NULL);
|
||||
g_hash_table_insert (settings_schemas, g_strdup (SCHEMA_MOUSE), settings);
|
||||
|
||||
/* Individual keys we watch outside of our schemas */
|
||||
settings = g_settings_new (SCHEMA_INTERFACE);
|
||||
g_signal_connect (settings, "changed::" KEY_GNOME_ACCESSIBILITY,
|
||||
@@ -1198,8 +1210,9 @@ settings_changed (GSettings *settings,
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Someone added a preference of an unhandled type */
|
||||
g_assert_not_reached ();
|
||||
/* Unknown preference type. This quite likely simply isn't
|
||||
* a preference we track changes to. */
|
||||
return;
|
||||
}
|
||||
|
||||
g_variant_unref (value);
|
||||
@@ -1234,6 +1247,7 @@ xsettings_overrides_changed (GSettings *settings,
|
||||
GVariant *value;
|
||||
GVariantDict overrides;
|
||||
int shell_shows_app_menu = 1;
|
||||
gboolean changed = FALSE;
|
||||
|
||||
if (!g_settings_get_boolean (settings, "active"))
|
||||
goto out;
|
||||
@@ -1247,8 +1261,13 @@ xsettings_overrides_changed (GSettings *settings,
|
||||
"Gtk/ShellShowsAppMenu", "i", &shell_shows_app_menu);
|
||||
g_variant_dict_clear (&overrides);
|
||||
|
||||
changed = (show_fallback_app_menu == !!shell_shows_app_menu);
|
||||
|
||||
out:
|
||||
show_fallback_app_menu = !shell_shows_app_menu;
|
||||
|
||||
if (changed)
|
||||
queue_changed (META_PREF_BUTTON_LAYOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1328,10 +1347,26 @@ meta_prefs_get_cursor_theme (void)
|
||||
return cursor_theme;
|
||||
}
|
||||
|
||||
static int
|
||||
get_scale_factor (void)
|
||||
{
|
||||
GdkScreen *screen;
|
||||
GValue value = G_VALUE_INIT;
|
||||
|
||||
g_value_init (&value, G_TYPE_INT);
|
||||
|
||||
/* XXX: Should this be in ui/ ? Or MetaMonitorManager? */
|
||||
screen = gdk_screen_get_default ();
|
||||
if (gdk_screen_get_setting (screen, "gdk-window-scaling-factor", &value))
|
||||
return g_value_get_int (&value);
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
meta_prefs_get_cursor_size (void)
|
||||
{
|
||||
return cursor_size;
|
||||
return cursor_size * get_scale_factor ();
|
||||
}
|
||||
|
||||
|
||||
@@ -1662,43 +1697,43 @@ button_layout_handler (GVariant *value,
|
||||
g_strfreev (sides);
|
||||
|
||||
/* Invert the button layout for RTL languages */
|
||||
if (meta_ui_get_direction() == META_UI_DIRECTION_RTL)
|
||||
{
|
||||
MetaButtonLayout rtl_layout;
|
||||
int j;
|
||||
if (meta_get_locale_direction() == META_LOCALE_DIRECTION_RTL)
|
||||
{
|
||||
MetaButtonLayout rtl_layout;
|
||||
int j;
|
||||
|
||||
for (i = 0; new_layout.left_buttons[i] != META_BUTTON_FUNCTION_LAST; i++);
|
||||
for (j = 0; j < i; j++)
|
||||
{
|
||||
rtl_layout.right_buttons[j] = new_layout.left_buttons[i - j - 1];
|
||||
if (j == 0)
|
||||
rtl_layout.right_buttons_has_spacer[i - 1] = new_layout.left_buttons_has_spacer[i - j - 1];
|
||||
else
|
||||
rtl_layout.right_buttons_has_spacer[j - 1] = new_layout.left_buttons_has_spacer[i - j - 1];
|
||||
}
|
||||
for (; j < MAX_BUTTONS_PER_CORNER; j++)
|
||||
{
|
||||
rtl_layout.right_buttons[j] = META_BUTTON_FUNCTION_LAST;
|
||||
rtl_layout.right_buttons_has_spacer[j] = FALSE;
|
||||
}
|
||||
for (i = 0; new_layout.left_buttons[i] != META_BUTTON_FUNCTION_LAST; i++);
|
||||
for (j = 0; j < i; j++)
|
||||
{
|
||||
rtl_layout.right_buttons[j] = new_layout.left_buttons[i - j - 1];
|
||||
if (j == 0)
|
||||
rtl_layout.right_buttons_has_spacer[i - 1] = new_layout.left_buttons_has_spacer[i - j - 1];
|
||||
else
|
||||
rtl_layout.right_buttons_has_spacer[j - 1] = new_layout.left_buttons_has_spacer[i - j - 1];
|
||||
}
|
||||
for (; j < MAX_BUTTONS_PER_CORNER; j++)
|
||||
{
|
||||
rtl_layout.right_buttons[j] = META_BUTTON_FUNCTION_LAST;
|
||||
rtl_layout.right_buttons_has_spacer[j] = FALSE;
|
||||
}
|
||||
|
||||
for (i = 0; new_layout.right_buttons[i] != META_BUTTON_FUNCTION_LAST; i++);
|
||||
for (j = 0; j < i; j++)
|
||||
{
|
||||
rtl_layout.left_buttons[j] = new_layout.right_buttons[i - j - 1];
|
||||
if (j == 0)
|
||||
rtl_layout.left_buttons_has_spacer[i - 1] = new_layout.right_buttons_has_spacer[i - j - 1];
|
||||
else
|
||||
rtl_layout.left_buttons_has_spacer[j - 1] = new_layout.right_buttons_has_spacer[i - j - 1];
|
||||
}
|
||||
for (; j < MAX_BUTTONS_PER_CORNER; j++)
|
||||
{
|
||||
rtl_layout.left_buttons[j] = META_BUTTON_FUNCTION_LAST;
|
||||
rtl_layout.left_buttons_has_spacer[j] = FALSE;
|
||||
}
|
||||
for (i = 0; new_layout.right_buttons[i] != META_BUTTON_FUNCTION_LAST; i++);
|
||||
for (j = 0; j < i; j++)
|
||||
{
|
||||
rtl_layout.left_buttons[j] = new_layout.right_buttons[i - j - 1];
|
||||
if (j == 0)
|
||||
rtl_layout.left_buttons_has_spacer[i - 1] = new_layout.right_buttons_has_spacer[i - j - 1];
|
||||
else
|
||||
rtl_layout.left_buttons_has_spacer[j - 1] = new_layout.right_buttons_has_spacer[i - j - 1];
|
||||
}
|
||||
for (; j < MAX_BUTTONS_PER_CORNER; j++)
|
||||
{
|
||||
rtl_layout.left_buttons[j] = META_BUTTON_FUNCTION_LAST;
|
||||
rtl_layout.left_buttons_has_spacer[j] = FALSE;
|
||||
}
|
||||
|
||||
new_layout = rtl_layout;
|
||||
}
|
||||
new_layout = rtl_layout;
|
||||
}
|
||||
|
||||
if (!button_layout_equal (&button_layout, &new_layout))
|
||||
{
|
||||
@@ -1902,6 +1937,9 @@ meta_preference_to_string (MetaPreference pref)
|
||||
case META_PREF_DRAGGABLE_BORDER_WIDTH:
|
||||
return "DRAGGABLE_BORDER_WIDTH";
|
||||
|
||||
case META_PREF_DRAG_THRESHOLD:
|
||||
return "DRAG_TRHESHOLD";
|
||||
|
||||
case META_PREF_DYNAMIC_WORKSPACES:
|
||||
return "DYNAMIC_WORKSPACES";
|
||||
|
||||
@@ -1995,23 +2033,6 @@ update_binding (MetaKeyPref *binding,
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Bug 329676: Bindings which can be shifted must not have no modifiers,
|
||||
* nor only SHIFT as a modifier.
|
||||
*/
|
||||
|
||||
if (binding->add_shift &&
|
||||
0 != keysym &&
|
||||
(META_VIRTUAL_SHIFT_MASK == mods || 0 == mods))
|
||||
{
|
||||
meta_warning ("Cannot bind \"%s\" to %s: it needs a modifier "
|
||||
"such as Ctrl or Alt.\n",
|
||||
binding->name, strokes[i]);
|
||||
|
||||
/* Value is kept and will thus be removed next time we save the key.
|
||||
* Changing the key in response to a modification could lead to cyclic calls. */
|
||||
continue;
|
||||
}
|
||||
|
||||
combo = g_malloc0 (sizeof (MetaKeyCombo));
|
||||
combo->keysym = keysym;
|
||||
combo->keycode = keycode;
|
||||
@@ -2187,7 +2208,6 @@ meta_prefs_add_keybinding (const char *name,
|
||||
pref->settings = g_object_ref (settings);
|
||||
pref->action = action;
|
||||
pref->combos = NULL;
|
||||
pref->add_shift = (flags & META_KEY_BINDING_REVERSES) != 0;
|
||||
pref->per_window = (flags & META_KEY_BINDING_PER_WINDOW) != 0;
|
||||
pref->builtin = (flags & META_KEY_BINDING_BUILTIN) != 0;
|
||||
|
||||
@@ -2367,6 +2387,12 @@ meta_prefs_get_draggable_border_width (void)
|
||||
return draggable_border_width;
|
||||
}
|
||||
|
||||
int
|
||||
meta_prefs_get_drag_threshold (void)
|
||||
{
|
||||
return drag_threshold;
|
||||
}
|
||||
|
||||
void
|
||||
meta_prefs_set_force_fullscreen (gboolean whether)
|
||||
{
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user