Compare commits
278 Commits
3.11.5-way
...
3.12.0-way
Author | SHA1 | Date | |
---|---|---|---|
![]() |
eba848e8aa | ||
![]() |
71be7e8493 | ||
![]() |
7484d540cd | ||
![]() |
a55622d924 | ||
![]() |
1cfaf45389 | ||
![]() |
42491f7724 | ||
![]() |
9696e785da | ||
![]() |
0de83ebfb5 | ||
![]() |
337db2a660 | ||
![]() |
054c307353 | ||
![]() |
852589897e | ||
![]() |
46b4d6c0f0 | ||
![]() |
ab2224686a | ||
![]() |
24b08d1a36 | ||
![]() |
0808adefaf | ||
![]() |
14f424cd02 | ||
![]() |
9debd2fb0d | ||
![]() |
57359da9b4 | ||
![]() |
e67abdd3ff | ||
![]() |
ca4777f778 | ||
![]() |
76dc0ca681 | ||
![]() |
8968501031 | ||
![]() |
1b29113150 | ||
![]() |
15c59f9919 | ||
![]() |
a53e094fcd | ||
![]() |
a377a1a110 | ||
![]() |
74a1e00e30 | ||
![]() |
1c41f71eef | ||
![]() |
63350c52cc | ||
![]() |
56e8c3b625 | ||
![]() |
ce3d9fb89f | ||
![]() |
27c018ab98 | ||
![]() |
a1427c7130 | ||
![]() |
91ad92c968 | ||
![]() |
f0c7b518e6 | ||
![]() |
5fa5ace5e6 | ||
![]() |
044c06bff3 | ||
![]() |
a3ccc4fd1c | ||
![]() |
0a20f7458c | ||
![]() |
9c94f8ae47 | ||
![]() |
f940292cfe | ||
![]() |
48a36356dd | ||
![]() |
f05983be42 | ||
![]() |
dfcefd3315 | ||
![]() |
3fe755e684 | ||
![]() |
0eb86de807 | ||
![]() |
ff635bad3b | ||
![]() |
43a409dec4 | ||
![]() |
b087fce062 | ||
![]() |
420f322910 | ||
![]() |
4bf6e0ae8c | ||
![]() |
97872e70a5 | ||
![]() |
be57308663 | ||
![]() |
33f1bd96f5 | ||
![]() |
9ba49358e5 | ||
![]() |
8b2b65246a | ||
![]() |
4fdbb466e1 | ||
![]() |
da48b18188 | ||
![]() |
a5f1790828 | ||
![]() |
6efcf2526d | ||
![]() |
d6a27195d3 | ||
![]() |
8f151842fb | ||
![]() |
6f7023bc6b | ||
![]() |
63b158e4da | ||
![]() |
b3364cad3e | ||
![]() |
3502cfba34 | ||
![]() |
5cc6becb63 | ||
![]() |
ae8f21a3dc | ||
![]() |
0cdf3bd383 | ||
![]() |
3de58189c0 | ||
![]() |
5270c469a3 | ||
![]() |
7504f16e59 | ||
![]() |
cdb7947dd1 | ||
![]() |
cdfc6f5b53 | ||
![]() |
fcb2ab41b2 | ||
![]() |
f5bd7c5f50 | ||
![]() |
cb549154aa | ||
![]() |
ada9610e30 | ||
![]() |
f11bf44525 | ||
![]() |
1f15c85c00 | ||
![]() |
8b4c5459c0 | ||
![]() |
d07d5d1328 | ||
![]() |
535685742a | ||
![]() |
62e45b6d5e | ||
![]() |
3c6dd5bf6d | ||
![]() |
0f85986340 | ||
![]() |
93ac0329db | ||
![]() |
c539dfe0d7 | ||
![]() |
1502d2a79f | ||
![]() |
a9d8107c3d | ||
![]() |
a5d2c51392 | ||
![]() |
d1ea17e6a4 | ||
![]() |
b37ad66e9d | ||
![]() |
c1f15348a5 | ||
![]() |
857561baed | ||
![]() |
a44cc9ef47 | ||
![]() |
d47b7ba038 | ||
![]() |
f21312e2fd | ||
![]() |
394af33607 | ||
![]() |
7314cdac94 | ||
![]() |
81025e37ea | ||
![]() |
1bb9f1e333 | ||
![]() |
b11c75c1c9 | ||
![]() |
757b626aee | ||
![]() |
fb3df5243f | ||
![]() |
e34792d9f0 | ||
![]() |
f397c32192 | ||
![]() |
f79314d7b5 | ||
![]() |
55c61259d8 | ||
![]() |
5298cf0a3a | ||
![]() |
f1dc1a0cbc | ||
![]() |
2cf80bc647 | ||
![]() |
40c15f6e2a | ||
![]() |
a8849621c9 | ||
![]() |
49c0be11d6 | ||
![]() |
9df8e831be | ||
![]() |
84c6b2a3fa | ||
![]() |
06cd669ccb | ||
![]() |
81eb7d9537 | ||
![]() |
dd8d8e436d | ||
![]() |
d6b6b363ad | ||
![]() |
254e2e993c | ||
![]() |
c595a9c29f | ||
![]() |
dfc7f7222b | ||
![]() |
ef278eb547 | ||
![]() |
38e26e5cc3 | ||
![]() |
9773a879c3 | ||
![]() |
abd2abcde6 | ||
![]() |
a8f4651c72 | ||
![]() |
54df7934ea | ||
![]() |
9052efb0d9 | ||
![]() |
b346f98eb0 | ||
![]() |
365af53797 | ||
![]() |
bee59ec0e1 | ||
![]() |
91384a32b4 | ||
![]() |
72bd5fb814 | ||
![]() |
46af3ef9f6 | ||
![]() |
d417c615d5 | ||
![]() |
46cbd0bf48 | ||
![]() |
f3b6fead4d | ||
![]() |
80de8ec643 | ||
![]() |
4f7e2a9f3f | ||
![]() |
701e06d55d | ||
![]() |
94f39a493f | ||
![]() |
ddc171220a | ||
![]() |
0313b38dd6 | ||
![]() |
d41fba6558 | ||
![]() |
770b58b367 | ||
![]() |
77838c2ca3 | ||
![]() |
e56cbfbd0f | ||
![]() |
a27fb19473 | ||
![]() |
674bcef6da | ||
![]() |
86c1c30245 | ||
![]() |
283546b379 | ||
![]() |
98e3e5e50f | ||
![]() |
b6a0d4d368 | ||
![]() |
28859c604f | ||
![]() |
9e51d98f4a | ||
![]() |
268a4c92ba | ||
![]() |
71367e14d5 | ||
![]() |
5c99eae8a9 | ||
![]() |
89aa5df711 | ||
![]() |
b9a5d710b7 | ||
![]() |
65dd54a4db | ||
![]() |
b00fa70d91 | ||
![]() |
360d423faa | ||
![]() |
394b44a2c2 | ||
![]() |
ed6821a819 | ||
![]() |
23b0f7be43 | ||
![]() |
7f195aec7a | ||
![]() |
da13e3d237 | ||
![]() |
75184d4c55 | ||
![]() |
eb75306f8a | ||
![]() |
98c4b82907 | ||
![]() |
640102c03b | ||
![]() |
c0d791cd6e | ||
![]() |
41d5e69de5 | ||
![]() |
2dc7371944 | ||
![]() |
ec2c3e1438 | ||
![]() |
c5c3806a04 | ||
![]() |
ac0c7df4a3 | ||
![]() |
d85845426c | ||
![]() |
060e60f2a0 | ||
![]() |
26cf75d5a4 | ||
![]() |
9f5087e97d | ||
![]() |
45624f2edf | ||
![]() |
153f843ea6 | ||
![]() |
f0cd9b0687 | ||
![]() |
1783bf20ec | ||
![]() |
9b24ae2033 | ||
![]() |
0be4622e14 | ||
![]() |
bcd5446cdc | ||
![]() |
04b5232960 | ||
![]() |
f860df4b2d | ||
![]() |
ff8c4b1bcf | ||
![]() |
337c69e223 | ||
![]() |
14841475b5 | ||
![]() |
7283fb320f | ||
![]() |
020cfa7283 | ||
![]() |
83aca0b53d | ||
![]() |
0b055fae2e | ||
![]() |
bc79259398 | ||
![]() |
7ebf5aa69a | ||
![]() |
7499621ecb | ||
![]() |
4de3f7ca29 | ||
![]() |
17462c21e8 | ||
![]() |
c964ef4e01 | ||
![]() |
0dccc440b6 | ||
![]() |
48f7232492 | ||
![]() |
ff5867e4d3 | ||
![]() |
a5d950f453 | ||
![]() |
7615d17293 | ||
![]() |
374e30043b | ||
![]() |
f771bb88d6 | ||
![]() |
7ef8d21e48 | ||
![]() |
c251eb8ec0 | ||
![]() |
1e6b3faa83 | ||
![]() |
e62fe956fd | ||
![]() |
24c5290d7f | ||
![]() |
00c8d3c897 | ||
![]() |
cc13f8f65e | ||
![]() |
47f4c9db7b | ||
![]() |
4c621cc30f | ||
![]() |
756a412436 | ||
![]() |
be16c2fe71 | ||
![]() |
a364c2a96b | ||
![]() |
414259a7f8 | ||
![]() |
283a81eac0 | ||
![]() |
2a145262c7 | ||
![]() |
57728b4322 | ||
![]() |
ef24fb6296 | ||
![]() |
86f057a712 | ||
![]() |
dcd628d289 | ||
![]() |
6038877c4c | ||
![]() |
4e6321c239 | ||
![]() |
304a525744 | ||
![]() |
f26de405dd | ||
![]() |
ed18580118 | ||
![]() |
b65649186d | ||
![]() |
515dc08a97 | ||
![]() |
2e7a56a28f | ||
![]() |
c485637a61 | ||
![]() |
f9f2a82e18 | ||
![]() |
2f4563132a | ||
![]() |
e3a0f2c546 | ||
![]() |
d39baeb8ad | ||
![]() |
f27f6aab78 | ||
![]() |
a66060e21a | ||
![]() |
11aa3c030b | ||
![]() |
bd1bec5617 | ||
![]() |
d9659d4b36 | ||
![]() |
d043d9943b | ||
![]() |
a0ef7c7142 | ||
![]() |
4efe4483fb | ||
![]() |
aec3edb1cc | ||
![]() |
0c5a6ad775 | ||
![]() |
2be5401b1e | ||
![]() |
f16e9b2ee7 | ||
![]() |
06380938d4 | ||
![]() |
87b20d7f2a | ||
![]() |
593db0baee | ||
![]() |
6b66553493 | ||
![]() |
ddaae9c923 | ||
![]() |
0c7a7d7527 | ||
![]() |
6561b53346 | ||
![]() |
def5e86673 | ||
![]() |
0c213c8fee | ||
![]() |
912a0abd26 | ||
![]() |
d694260ad2 | ||
![]() |
8566566451 | ||
![]() |
0ce64e46e8 | ||
![]() |
a8336669a3 | ||
![]() |
f6db756326 | ||
![]() |
27ab516f41 | ||
![]() |
9542b464bf | ||
![]() |
1ebaaa1950 | ||
![]() |
71efbf0330 | ||
![]() |
a6539463be |
22
.gitignore
vendored
22
.gitignore
vendored
@@ -78,15 +78,12 @@ src/stamp-mutter-marshal.h
|
||||
src/meta-dbus-xrandr.[ch]
|
||||
src/meta-dbus-idle-monitor.[ch]
|
||||
src/mutter-plugins.pc
|
||||
src/wayland/gtk-shell-protocol.c
|
||||
src/wayland/gtk-shell-client-protocol.h
|
||||
src/wayland/gtk-shell-server-protocol.h
|
||||
src/wayland/xdg-shell-protocol.c
|
||||
src/wayland/xdg-shell-client-protocol.h
|
||||
src/wayland/xdg-shell-server-protocol.h
|
||||
src/wayland/xserver-protocol.c
|
||||
src/wayland/xserver-client-protocol.h
|
||||
src/wayland/xserver-server-protocol.h
|
||||
src/gtk-shell-protocol.c
|
||||
src/gtk-shell-server-protocol.h
|
||||
src/xdg-shell-protocol.c
|
||||
src/xdg-shell-server-protocol.h
|
||||
src/xserver-protocol.c
|
||||
src/xserver-server-protocol.h
|
||||
doc/reference/*.args
|
||||
doc/reference/*.bak
|
||||
doc/reference/*.hierarchy
|
||||
@@ -104,3 +101,10 @@ doc/reference/meta-undocumented.txt
|
||||
doc/reference/meta-unused.txt
|
||||
doc/reference/meta-docs.sgml
|
||||
doc/reference/meta.types
|
||||
gtk-doc.m4
|
||||
intltool.m4
|
||||
libtool.m4
|
||||
ltoptions.m4
|
||||
ltsugar.m4
|
||||
ltversion.m4
|
||||
lt~obsolete.m4
|
||||
|
159
COMPLIANCE
159
COMPLIANCE
@@ -1,159 +0,0 @@
|
||||
Metacity Standards Compliance
|
||||
=============================
|
||||
$Id$
|
||||
|
||||
1) Introduction
|
||||
2) EWMH Compliance
|
||||
a. Root Window Properties
|
||||
b. Root Window Messages
|
||||
c. Application Window Properties
|
||||
d. Window Manager Protocols
|
||||
3) ICCCM Compliance
|
||||
|
||||
1) Introduction
|
||||
---------------
|
||||
|
||||
This document details metacity compliance with the relevent standards.
|
||||
The format of this document is as follows:
|
||||
|
||||
[-/+?] Hint Name/Feature Name (Version number)
|
||||
Errata/Comments
|
||||
|
||||
The first character indicates the level of compliance as follows:
|
||||
- none
|
||||
/ partial
|
||||
+ complete
|
||||
? unknown
|
||||
|
||||
The title indicates a feature or a hint in the specification, and the
|
||||
version number indicates the minimum version of the specification
|
||||
supported by metacity. Later versions may be supported if no
|
||||
incompatible changes have been made in the specification.
|
||||
|
||||
2) EWMH Compliance
|
||||
------------------
|
||||
|
||||
The EWMH, or Extended Window Manager Hints is a freedesktop.org-
|
||||
developed standard to support a number of conventions for
|
||||
communication between the window manager and clients. It builds on
|
||||
and extends the ICCCM (See Section 3). A copy of the current EWMH
|
||||
standard is available at http://freedesktop.org/Standards/wm-spec/
|
||||
|
||||
a. Root Window Properties
|
||||
-------------------------
|
||||
|
||||
+ _NET_SUPPORTED (1.3)
|
||||
|
||||
+ _NET_CLIENT_LIST (1.3)
|
||||
|
||||
+ _NET_NUMBER_OF_DESKTOPS (1.3)
|
||||
|
||||
+ _NET_DESKTOP_GEOMETRY (1.3)
|
||||
Metacity does not implement large desktops, so this is kept set to
|
||||
the screen size.
|
||||
|
||||
+ _NET_DESKTOP_VIEWPORT (1.3)
|
||||
Metacity does not implement viewports, so this is a constant (0,0).
|
||||
|
||||
+ _NET_CURRENT_DESKTOP (1.3)
|
||||
|
||||
+ _NET_DESKTOP_NAMES (1.3)
|
||||
|
||||
+ _NET_ACTIVE_WINDOW (1.3)
|
||||
|
||||
+ _NET_WORKAREA (1.3)
|
||||
|
||||
+ _NET_SUPPORTING_WM_CHECK (1.3)
|
||||
|
||||
+ _NET_VIRTUAL_ROOTS (1.3)
|
||||
Metacity does not read or set this property, but it does not use
|
||||
virtual roots to implement virtual desktops, so it complies with the
|
||||
specification.
|
||||
|
||||
+ _NET_DESKTOP_LAYOUT (1.3)
|
||||
|
||||
+ _NET_SHOWING_DESKTOP (1.3)
|
||||
|
||||
b. Root Window Messages
|
||||
-----------------------
|
||||
|
||||
+ _NET_CLOSE_WINDOW (1.3)
|
||||
|
||||
- _NET_MOVERESIZE_WINDOW (1.3)
|
||||
Metacity supports this message, but the specification is unclear on
|
||||
the layout of the detail value, and as such it is #if 0'd in the code
|
||||
|
||||
+ _NET_WM_MOVERESIZE (1.3)
|
||||
|
||||
- _NET_RESTACK_WINDOW (1.3)
|
||||
Metacity will raise or lower windows in response to this message,
|
||||
but the sibling restack modes are not supported, and it is currently
|
||||
#if 0'd in the code.
|
||||
|
||||
+ _NET_REQUEST_FRAME_EXTENTS (1.3)
|
||||
|
||||
c. Application Window Properties
|
||||
--------------------------------
|
||||
|
||||
+ _NET_WM_NAME (1.3)
|
||||
|
||||
+ _NET_WM_VISIBLE_NAME (1.3)
|
||||
Metacity does not set this property, but metacity will never display
|
||||
a name different from _NET_WM_NAME
|
||||
|
||||
+ _NET_WM_ICON_NAME (1.3)
|
||||
|
||||
+ _NET_WM_VISIBLE_ICON_NAME (1.3)
|
||||
Metacity does not set this property, but metacity will never display
|
||||
a name different from _NET_WM_NAME
|
||||
|
||||
+ _NET_WM_DESKTOP (1.3)
|
||||
|
||||
+ _NET_WM_WINDOW_TYPE (1.3)
|
||||
|
||||
/ _NET_WM_STATE (1.3)
|
||||
This property is read and updated according to the specification,
|
||||
but see caveat below.
|
||||
Metacity does not recognize separate vertical and horizontal
|
||||
maximization states. Currently metacity will do a two-dimensional
|
||||
maximization if either property is set.
|
||||
See: http://bugzilla.gnome.org/show_bug.cgi?id=113601
|
||||
Metacity doesn't implement viewports so _NET_WM_STATE_STICKY is
|
||||
unimplemented.
|
||||
|
||||
+ _NET_WM_ALLOWED_ACTIONS (1.3)
|
||||
Metacity keeps this hint up to date. The code is somewhat crufty
|
||||
and should be rewritten, though it is functional.
|
||||
See: http://bugzilla.gnome.org/show_bug.cgi?id=90420
|
||||
|
||||
+ _NET_WM_STRUT (1.3)
|
||||
|
||||
+ _NET_WM_STRUT_PARTIAL (1.3)
|
||||
|
||||
+ _NET_WM_ICON_GEOMETRY (1.3)
|
||||
Metacity uses this property to draw minimize/restore animations
|
||||
|
||||
+ _NET_WM_ICON (1.3)
|
||||
|
||||
+ _NET_WM_PID (1.3)
|
||||
|
||||
+ _NET_WM_HANDLED_ICONS (1.3)
|
||||
Metacity does not read or set this property. However, metacity
|
||||
never manages iconified windows, and so has no need to do so.
|
||||
|
||||
+ _NET_WM_USER_TIME (1.3)
|
||||
Metacity uses this property to prevent applications from stealing
|
||||
focus if supported by the toolkit.
|
||||
|
||||
+ _NET_FRAME_EXTENTS (1.3)
|
||||
If set in response to a _NET_REQUEST_FRAME_EXTENTS message received
|
||||
prior to the window being mapped, this may be an estimate. This is,
|
||||
however, expressly allowed by the specification.
|
||||
|
||||
d. Window Manager Protocols
|
||||
---------------------------
|
||||
+ _NET_WM_PING (1.3)
|
||||
|
||||
3) ICCCM Compliance
|
||||
-------------------
|
||||
TODO
|
298
HACKING
298
HACKING
@@ -1,298 +0,0 @@
|
||||
Intro...
|
||||
|
||||
Window managers have a few ways in which they are significantly different
|
||||
from other applications. This file, combined with the code overview in
|
||||
doc/code-overview.txt, should hopefully provide a series of relatively
|
||||
quick pointers (hopefully only a few minutes each) to some of the places
|
||||
one can look to orient themselves and get started. Some of this will be
|
||||
general to window managers on X, much will be specific to Metacity, and
|
||||
there's probably some information that's common to programs in general but
|
||||
is nonetheless useful.
|
||||
|
||||
Overview
|
||||
Administrative issues
|
||||
Minimal Building/Testing Environment
|
||||
Relevant standards and X properties
|
||||
Debugging and testing
|
||||
Debugging logs
|
||||
Adding information to the log
|
||||
Valgrind
|
||||
Testing Utilities
|
||||
Technical gotchas to keep in mind
|
||||
Other important reading
|
||||
Extra reading
|
||||
Ideas for tasks to work on
|
||||
|
||||
|
||||
Administrative issues
|
||||
Don't commit substantive code in here without asking hp@redhat.com.
|
||||
Adding translations, no-brainer typo fixes, etc. is fine.
|
||||
|
||||
The code could use cleanup in a lot of places, feel free to do so.
|
||||
|
||||
See http://developer.gnome.org/dotplan/for_maintainers.html for
|
||||
information on how to make a release. The only difference from those
|
||||
instructions is that the minor version number of a Metacity release
|
||||
should always be a number from the Fibonacci sequence.
|
||||
|
||||
Minimal Building/Testing Environment
|
||||
You do not need to _install_ a development version of Metacity to
|
||||
build, run and test it; you can run it from some temporary
|
||||
directory. Also, you do not need to build all of Gnome in order to
|
||||
build a development version of Metacity -- odds are, you may be able
|
||||
to build metacity from CVS without building any other modules.
|
||||
|
||||
As long as you have gtk+ >= 3.0 and GIO >= 2.25.10 with your distro
|
||||
(gtk+ >= 2.6 if you manually revert the change from bug 348633), you
|
||||
should be able to install your distro's development packages
|
||||
(e.g. gtk2-devel, glib-devel, startup-notification-devel on
|
||||
Fedora; also, remember to install the gnome-common package which is
|
||||
needed for building cvs versions of Gnome modules like Metacity) as
|
||||
well as the standard development tools (gcc, autoconf, automake,
|
||||
pkg-config, intltool, and libtool) and be ready to build and test
|
||||
Metacity. Steps to do so:
|
||||
|
||||
$ svn checkout http://svn.gnome.org/svn/metacity/trunk metacity
|
||||
$ cd metacity
|
||||
$ ./autogen.sh --prefix /usr
|
||||
$ make
|
||||
$ ./src/metacity --replace
|
||||
|
||||
Again, note that you do not need to run 'make install'.
|
||||
|
||||
Relevant standards and X properties
|
||||
There are two documents that describe some basics about how window
|
||||
managers should behave: the ICCCM (Inter-Client Communication Conventions
|
||||
Manual) and EWMH (Extended Window Manager Hints). You can find these at
|
||||
the following locations:
|
||||
ICCCM - http://tronche.com/gui/x/icccm/
|
||||
EWMH - :pserver:anoncvs@pdx.freedesktop.org:/cvs
|
||||
The ICCCM is usually available in RPM or DEB format as well. There is
|
||||
actually an online version of the EWMH, but it is almost always woefully
|
||||
out of date. Just get it from cvs with these commands (the backslash
|
||||
means include the stuff from the next line):
|
||||
cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/icccm-extensions login
|
||||
cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/icccm-extensions \
|
||||
checkout wm-spec
|
||||
|
||||
DO NOT GO AND READ THOSE THINGS. THEY ARE REALLY, REALLY BORING.
|
||||
|
||||
If you do, you'll probably end up catching up on your sleep instead of
|
||||
hacking on Metacity. ;-) Instead, just look at the table of contents and
|
||||
glance at a page or two to get an idea of what's in there. Then only
|
||||
refer to it if you see something weird in the code and you don't know
|
||||
what it is but has some funny looking name like you see in one of those
|
||||
two documents.
|
||||
|
||||
You can refer to the COMPLIANCE file for additional information on these
|
||||
specifications and Metacity's compliance therewith.
|
||||
|
||||
One of the major things those documents cover that are useful to learn
|
||||
about immediately are X properties. The right way to learn about those,
|
||||
though, is through hand on experimentation with the xprop command (and
|
||||
then look up things you find from xprop in those two manuals if you're
|
||||
curious enough). First, try running
|
||||
xprop
|
||||
in a terminal and click on one of the windows on your screen. That gives
|
||||
you the x properties for that window. Look through them and get a basic
|
||||
idea of what's there for kicks. Note that you can get rid of some of the
|
||||
verboseness by grepping out the _NET_WM_ICON stuff, i.e.
|
||||
xprop | grep -v _NET_WM_ICON
|
||||
Next, try running
|
||||
xprop -root
|
||||
in a terminal. There's all the properties of the root window (which you
|
||||
can think of as the "main" Xserver window). You can also manually
|
||||
specify individual windows that you want the properties of with
|
||||
xprop -id <id>
|
||||
if you know the id of the window in question. You can get the id of a
|
||||
given window by either running xwininfo, e.g.
|
||||
xwininfo | grep "Window id" | cut -f 4 -d ' '
|
||||
or by looking at the _NET_CLIENT_STACKING property of the root
|
||||
window. Finally, it can also be useful to add "-spy" (without the
|
||||
quotes) to the xprop command to get it to continually monitor that
|
||||
window and report any changes to you.
|
||||
|
||||
Debugging information
|
||||
Trying to run a window manager under a typical debugger, such as gdb,
|
||||
unfortunately just doesn't work very well. So, we have to resort to
|
||||
other methods.
|
||||
|
||||
Debugging logs
|
||||
|
||||
First, note that you can start a new version of metacity to replace the
|
||||
existing one by running
|
||||
metacity --replace
|
||||
(which also comes in handy in the form "./src/metacity --replace" when
|
||||
trying to quickly test a small change while hacking on metacity without
|
||||
doing a full "make install", though I'm going off topic...) This will
|
||||
allow you to see any warnings printed at the terminal. Sometimes it's
|
||||
useful to have these directed to a logfile instead, which you can do by
|
||||
running
|
||||
METACITY_USE_LOGFILE=1 metacity --replace
|
||||
The logfile it uses will be printed in the terminal. Sometimes, it's
|
||||
useful to get more information than just warnings. You can set
|
||||
METACITY_VERBOSE to do that, like so:
|
||||
METACITY_VERBOSE=1 METACITY_USE_LOGFILE=1 metacity --replace
|
||||
(note that METACITY_VERBOSE=1 can be problematic without
|
||||
METACITY_USE_LOGFILE=1; avoid it unless running in from something that
|
||||
won't be managed by the new Metacity--see bug 305091 for more details).
|
||||
There are also other flags, such as METACITY_DEBUG, most of which I
|
||||
haven't tried and don't know what they do. Go to the source code
|
||||
directory and run
|
||||
grep "METACITY_" * | grep getenv
|
||||
to find out what the other ones are.
|
||||
|
||||
Adding information to the log
|
||||
|
||||
Since we can't single step with a debugger, we often have to fall back to
|
||||
the primitive method of getting information we want to know: adding
|
||||
"print" statements. Metacity has a fairly structured way to do this,
|
||||
using the functions meta_warning, meta_topic, and meta_verbose. All
|
||||
three have the same basic format as printf, except that meta_topic also
|
||||
takes a leading enumeration parameter to specify the type of message
|
||||
being shown (makes it easier for grepping in a verbose log). You'll find
|
||||
tons of examples in the source code if you need them; just do a quick
|
||||
grep or look in most any file. Note that meta_topic and meta_verbose
|
||||
messages only appear if verbosity is turned on. I tend to frequently add
|
||||
temporary meta_warning statements (or switch meta_topic or meta_verbose
|
||||
ones to meta_warning ones) and then undo the changes once I've learned
|
||||
the info that I needed.
|
||||
|
||||
There is also a meta_print_backtrace (which again is only active if
|
||||
verbosity is turned on) that can also be useful if you want to learn how
|
||||
a particular line of code gets called. And, of course, there's always
|
||||
g_assert if you want to make sure some section isn't executed (or isn't
|
||||
executed under certain conditions).
|
||||
|
||||
Valgrind
|
||||
|
||||
Valgrind is awesome for finding memory leaks or corruption and
|
||||
uninitialized variables. But I also tend to use it in a non-traditional
|
||||
way as a partial substitute for a normal debugger: it can provide me with
|
||||
a stack trace of where metacity is crashing if I made a change that
|
||||
caused it to do so, which is one of the major uses of debuggers. (And,
|
||||
what makes it cooler than a debugger is that there will also often be
|
||||
warnings pinpointing the cause of the crash from either some kind of
|
||||
simple memory corruption or an uninitialized variable). Sometimes, when
|
||||
I merely want to know what is calling a particular function I'll just
|
||||
throw in an "int i; printf("%d\n", i);" just because valgrind will give
|
||||
me a full stacktrace whenever it sees that uninitialized variable being
|
||||
used (yes, I could use meta_print_backtrace, but that means I have to
|
||||
turn verbosity on).
|
||||
|
||||
To run metacity under valgrind, use options typical for any Gnome
|
||||
program, such as
|
||||
valgrind --log-file=metacity.log --tool=memcheck --num-callers=48 \
|
||||
--leak-check=yes --leak-resolution=high --show-reachable=yes \
|
||||
./src/metacity --replace
|
||||
where, again, the backslashes mean to join all the stuff on the following
|
||||
line with the previous one.
|
||||
|
||||
However, there is a downside. Things run a little bit slowly, and it
|
||||
appears that you'll need about 1.5GB of ram, which unfortunately prevents
|
||||
most people from trying this.
|
||||
|
||||
Testing Utilities
|
||||
|
||||
src/run-metacity.sh
|
||||
The script src/run-metacity.sh is useful to hack on the window manager.
|
||||
It runs metacity in an Xnest. e.g.:
|
||||
CLIENTS=3 ./run-metacity.sh
|
||||
or
|
||||
DEBUG=memprof ./run-metacity.sh
|
||||
or
|
||||
DEBUG_TEST=1 ./run-metacity-sh
|
||||
or whatever.
|
||||
|
||||
metacity-message
|
||||
The tool metacity-message can be used as follows:
|
||||
metacity-message reload-theme
|
||||
metacity-message restart
|
||||
metacity-message enable-keybindings
|
||||
metacity-message disable-keybindings
|
||||
The first of these is useful for testing themes, the second is just
|
||||
another way (besides the --restart flag to metacity itself) of
|
||||
restarting metacity, and the third is useful for testing Metacity when
|
||||
running it under an Xnest (typically, the Metacity under the Xnest
|
||||
wouldn't get keybinding notifications--making keyboard navigation not
|
||||
work--but if you disable the keybindings for the global Metacity then
|
||||
the Metacity under the Xnest can then get those keybinding notifications).
|
||||
|
||||
metacity-window-demo
|
||||
metacity-window-demo is good for trying behavior of various kinds
|
||||
of window without launching a full desktop.
|
||||
|
||||
Technical gotchas to keep in mind
|
||||
Files that include gdk.h or gtk.h are not supposed to include
|
||||
display.h or window.h or other core files. Files in the core
|
||||
(display.[hc], window.[hc]) are not supposed to include gdk.h or
|
||||
gtk.h. Reasons:
|
||||
|
||||
"Basically you don't want GDK most of the time. It adds
|
||||
abstractions that cause problems, because they aren't designed to
|
||||
be used in a WM where we do weird stuff (display grabs, and just
|
||||
being the WM). At best GDK adds inefficiency, at worst it breaks
|
||||
things in weird ways where you have to be a GDK guru to figure
|
||||
them out. Owen also told me that they didn't want to start adding
|
||||
a lot of hacks to GDK to let a WM use it; we both agreed back in
|
||||
the mists of time that metacity would only use it for the "UI"
|
||||
bits as it does.
|
||||
|
||||
Having the split in the source code contains and makes very clear
|
||||
the interface between the WM and GDK/GTK. This keeps people from
|
||||
introducing extra GDK/GTK usage when it isn't needed or
|
||||
appropriate. Also, it speeds up the compilation a bit, though this
|
||||
was perhaps more relevant 5 years ago than it is now.
|
||||
|
||||
There was also a very old worry that the GDK stuff might have to
|
||||
be in a separate process to work right; that turned out to be
|
||||
untrue. Though who knows what issues the CM will introduce."
|
||||
|
||||
Remember that strings stored in X properties are not in UTF-8, and they
|
||||
have to end up in UTF-8 before we try putting them through Pango.
|
||||
|
||||
If you make any X request involving a client window, you have to
|
||||
meta_error_trap_push() around the call; this is not necessary for X
|
||||
requests on the frame windows.
|
||||
|
||||
Remember that not all windows have frames, and window->frame can be NULL.
|
||||
|
||||
Other important reading & where to get started
|
||||
Extra reading
|
||||
|
||||
There are some other important things to read to get oriented as well.
|
||||
These are:
|
||||
http://pobox.com/~hp/features.html
|
||||
rationales.txt
|
||||
doc/code-overview.txt
|
||||
|
||||
It pays to read http://pobox.com/~hp/features.html in order
|
||||
to understand the philosophy of Metacity.
|
||||
|
||||
The rationales.txt file has two things: (1) a list of design choices with
|
||||
links in the form of bugzilla bugs that discuss the issue, and (2) a list
|
||||
outstanding bug categories, each of which is tracked by a particular
|
||||
tracker bug in bugzilla from which you can find several closely related
|
||||
bug reports.
|
||||
|
||||
doc/code-overview.txt provides a fairly good overview of the code,
|
||||
including coverage of the function of the various files, the main
|
||||
structures and their relationships, and places to start looking in the
|
||||
code tailored to general categories of tasks.
|
||||
|
||||
Ideas for tasks to work on
|
||||
|
||||
There are a variety of things you could work on in the code. You may
|
||||
have ideas of your own, but in case you don't, let me provide a list of
|
||||
ideas you could choose from:
|
||||
|
||||
If you're ambitious, there's a list of things Havoc made that he'd really
|
||||
like to see tackled, which you can find at
|
||||
http://log.ometer.com/2004-05.html. Be sure to double check with someone
|
||||
to make sure the item is still relevant if you're interested in one of
|
||||
these. Another place to look for ideas, of course, is bugzilla. One can
|
||||
just do queries and look for things that look fixable.
|
||||
|
||||
However, perhaps the best way of getting ideas of related tasks to work
|
||||
on, is to look at the second half of the rationales.txt file, which tries
|
||||
to group bugs by type.
|
@@ -1,8 +0,0 @@
|
||||
Tomas Frydrych
|
||||
Email: tf linux intel com
|
||||
Userid: tomasf
|
||||
|
||||
Owen Taylor
|
||||
Email: otaylor redhat com
|
||||
Userid: otaylor
|
||||
|
@@ -1,43 +0,0 @@
|
||||
Currently active maintainers
|
||||
--------------------------------
|
||||
|
||||
Elijah Newren
|
||||
Email: newren gmail com
|
||||
Userid: newren
|
||||
|
||||
- Usually won't touch the theme bugs (isn't interested) or the
|
||||
compositor (until open source nvidia drivers are up to snuff).
|
||||
Tends to be most interested in libwnck/gtk interactions, focus
|
||||
issues, constraints problems, and raising/stacking, but works on
|
||||
just about anything other than themes and the compositor.
|
||||
|
||||
Thomas Thurman
|
||||
Email: thomas thurman org uk
|
||||
Userid: tthurman
|
||||
|
||||
- Responsible for all theme bugs and the compositor (thank goodness
|
||||
Thomas got involved, eh?). I'm sure he'll replace this sentence
|
||||
with his interests when he reads it. ;-)
|
||||
|
||||
|
||||
Semi-active maintainers
|
||||
--------------------------------
|
||||
|
||||
Havoc Pennington
|
||||
Email: hp redhat com
|
||||
Userid: hp
|
||||
- Original author. Doesn't patch metacity anymore, but is active in
|
||||
answering questions, responding to bugs, providing very helpful
|
||||
suggestions and insight, and even assisting with debugging.
|
||||
|
||||
|
||||
Important historical figureheads
|
||||
--------------------------------
|
||||
|
||||
Rob Adams (readams readams net)
|
||||
- Was the main maintainer of metacity for a while; particular areas
|
||||
of focus included xinerama, placement, and an older version of the
|
||||
constraints code. Still responds to bugs every once in a while.
|
||||
|
||||
Søren Sandmann (sandmann redhat com)
|
||||
- Wrote most of the current compositing manager code + libcm
|
@@ -1,7 +1,5 @@
|
||||
|
||||
SUBDIRS=src protocol po doc
|
||||
|
||||
EXTRA_DIST = HACKING MAINTAINERS rationales.txt
|
||||
SUBDIRS=src po doc
|
||||
|
||||
DISTCLEANFILES = intltool-extract intltool-merge intltool-update po/stamp-it po/.intltool-merge-cache
|
||||
|
||||
|
44
NEWS
44
NEWS
@@ -1,3 +1,47 @@
|
||||
3.12.0
|
||||
======
|
||||
* Fix grab issue with SSD xwayland windows [Rui; #726123]
|
||||
* Misc. bug fixes [Jasper, Ray, Rui, Florian; #727011]
|
||||
|
||||
Contributors:
|
||||
Rui Matos, Florian Müllner, Jasper St. Pierre, Ray Strode
|
||||
|
||||
3.11.92
|
||||
=======
|
||||
* Fix identification of CSD windows [Owen; #723029]
|
||||
* Update keyboard state unconditionally [Rui; #722847]
|
||||
* Misc bug fixes and cleanups [Owen, Rui, Giovanni, Matthias, Adel, Ryan,
|
||||
Jasper, Marek, Florian; #723580, #726123, #726683]
|
||||
|
||||
Contributors:
|
||||
Giovanni Campagna, Marek Chalupa, Matthias Clasen, Adel Gadllah, Ryan Lortie,
|
||||
Rui Matos, Florian Müllner, Jasper St. Pierre, Owen W. Taylor
|
||||
|
||||
3.11.91
|
||||
=======
|
||||
* Don't use keysym to match keybindings [Rui; #678001]
|
||||
* Fix message tray icons showing up blank (again) [Adel; #725180]
|
||||
* Improve keybinding lookups [Rui; #725588]
|
||||
* Fix dynamic updates of titlebar style properties [Owen; #725751]
|
||||
* Fix positioning of manually positioned windows [Owen; #724049]
|
||||
* Misc bug fixes and cleanups [Jasper, Carlos, Adel, Giovanni, Florian; #720631,
|
||||
#724969, #725216, #724402, #722266, #725338, #725525]
|
||||
|
||||
Contributors:
|
||||
Giovanni Campagna, Adel Gadllah, Carlos Garnacho, Rui Matos, Florian Müllner,
|
||||
Jasper St. Pierre, Owen W. Taylor
|
||||
|
||||
3.11.90
|
||||
=======
|
||||
* Fix double-scaling on high DPI resolutions [Adel; #723931]
|
||||
* Make tile previews a compositor effect [Stefano, Florian; #665758]
|
||||
* Misc. bug fixes and cleanups [Ryan, Giovanni, Jasper, Adel; #722530, #724257,
|
||||
#724258, #720631, #724364, #724472]
|
||||
|
||||
Contributors:
|
||||
Giovanni Campagna, Marek Chalupa, Stefano Facchini, Adel Gadllah,
|
||||
Ryan Lortie, Florian Müllner, Jasper St. Pierre, Rico Tzschichholz
|
||||
|
||||
3.11.5
|
||||
======
|
||||
* Fix CSD titlebars being placed off-screen [Jasper; #719772]
|
||||
|
416
README
416
README
@@ -1,416 +0,0 @@
|
||||
The original codebase named "Metacity" is not a meta-City as in an
|
||||
urban center, but rather Meta-ness as in the state of being
|
||||
meta. i.e. metacity : meta as opacity : opaque. Also it may have
|
||||
something to do with the Meta key on UNIX keyboards.
|
||||
|
||||
Since then, it has been renamed mutter after a rebase on top of
|
||||
clutter as a compositing manager.
|
||||
|
||||
COMPILING MUTTER
|
||||
===
|
||||
|
||||
You need GTK+ 2.2. For startup notification to work you need
|
||||
libstartup-notification at
|
||||
http://www.freedesktop.org/software/startup-notification/ or on the
|
||||
GNOME ftp site.
|
||||
You need Clutter 1.0. You need gobject-introspection 0.6.3.
|
||||
|
||||
REPORTING BUGS AND SUBMITTING PATCHES
|
||||
===
|
||||
|
||||
Report new bugs on http://bugzilla.gnome.org. Please check for
|
||||
duplicates, *especially* if you are reporting a feature request.
|
||||
|
||||
Please do *not* add "me too!" or "yes I really want this!" comments to
|
||||
feature requests in bugzilla. Please read
|
||||
http://pobox.com/~hp/features.html prior to adding any kind of flame
|
||||
about missing features or misfeatures.
|
||||
|
||||
Feel free to send patches too; Metacity is relatively small and
|
||||
simple, so if you find a bug or want to add a feature it should be
|
||||
pretty easy. Send me mail, or put the patch in bugzilla.
|
||||
|
||||
See the HACKING file for some notes on hacking Mutter.
|
||||
|
||||
MUTTER FEATURES
|
||||
===
|
||||
|
||||
- Uses GTK+ 2.0 for drawing window frames. This means colors, fonts,
|
||||
etc. come from GTK+ theme.
|
||||
|
||||
- Does not expose the concept of "window manager" to the user. Some
|
||||
of the features in the GNOME control panel and other parts of the
|
||||
desktop happen to be implemented in metacity, such as changing your
|
||||
window border theme, or changing your window navigation shortcuts,
|
||||
but the user doesn't need to know this.
|
||||
|
||||
- Includes only the window manager; does not try to be a desktop
|
||||
environment. The pager, configuration, etc. are all separate and
|
||||
modular. The "libwnck" library (which I also wrote) is available
|
||||
for writing metacity extensions, pagers, and so on. (But libwnck
|
||||
isn't metacity specific, or GNOME-dependent; it requires only GTK,
|
||||
and should work with KWin, fvwm2, and other EWMH-compliant WMs.)
|
||||
|
||||
- Has a simple theme system and a couple of extra themes come with it.
|
||||
Change themes via gsettings:
|
||||
gsettings set org.gnome.desktop.wm.preferences theme Crux
|
||||
gsettings set org.gnome.desktop.wm.preferences theme Gorilla
|
||||
gsettings set org.gnome.desktop.wm.preferences theme Atlanta
|
||||
gsettings set org.gnome.desktop.wm.preferences theme Bright
|
||||
|
||||
See theme-format.txt for docs on the theme format. Use
|
||||
metacity-theme-viewer to preview themes.
|
||||
|
||||
- Change number of workspaces via gsettings:
|
||||
gsettings set org.gnome.desktop.wm.preferences num-workspaces 5
|
||||
|
||||
Can also change workspaces from GNOME 2 pager.
|
||||
|
||||
- Change focus mode:
|
||||
gsettings set org.gnome.desktop.wm.preferences focus-mode mouse
|
||||
gsettings set org.gnome.desktop.wm.preferences focus-mode sloppy
|
||||
gsettings set org.gnome.desktop.wm.preferences focus-mode click
|
||||
|
||||
- Global keybinding defaults include:
|
||||
|
||||
Alt-Tab forward cycle window focus
|
||||
Alt-Shift-Tab backward cycle focus
|
||||
Alt-Ctrl-Tab forward cycle focus among panels
|
||||
Alt-Ctrl-Shift-Tab backward cycle focus among panels
|
||||
Alt-Escape cycle window focus without a popup thingy
|
||||
Ctrl-Alt-Left Arrow previous workspace
|
||||
Ctrl-Alt-Right Arrow next workspace
|
||||
Ctrl-Alt-D minimize/unminimize all, to show desktop
|
||||
|
||||
Change keybindings for example:
|
||||
|
||||
gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-1 '[<Alt>F1]'
|
||||
|
||||
Also try the GNOME keyboard shortcuts control panel.
|
||||
|
||||
- Window keybindings:
|
||||
|
||||
Alt-space window menu
|
||||
|
||||
Mnemonics work in the menu. That is, Alt-space then underlined
|
||||
letter in the menu item works.
|
||||
|
||||
Choose Move from menu, and arrow keys to move the window.
|
||||
|
||||
While moving, hold down Control to move slower, and
|
||||
Shift to snap to edges.
|
||||
|
||||
Choose Resize from menu, and nothing happens yet, but
|
||||
eventually I might implement something.
|
||||
|
||||
Keybindings for things like maximize window, vertical maximize,
|
||||
etc. can be bound, but may not all exist by default. See
|
||||
metacity.schemas.
|
||||
|
||||
- Window mouse bindings:
|
||||
|
||||
Clicking anywhere on frame with button 1 will raise/focus window
|
||||
|
||||
If you click a window control, such as the close button, then the
|
||||
control will activate on button release if you are still over it
|
||||
on release (as with most GUI toolkits)
|
||||
|
||||
If you click and drag borders with button 1 it resizes the window
|
||||
|
||||
If you click and drag the titlebar with button 1 it moves the
|
||||
window.
|
||||
|
||||
If you click anywhere on the frame with button 2 it lowers the
|
||||
window.
|
||||
|
||||
If you click anywhere on the frame with button 3 it shows the
|
||||
window menu.
|
||||
|
||||
If you hold down Super (windows key) and click inside a window, it
|
||||
will move the window (buttons 1 and 2) or show menu (button 3).
|
||||
Or you can configure a different modifier for this.
|
||||
|
||||
If you pick up a window with button 1 and then switch workspaces
|
||||
the window will come with you to the new workspace, this is
|
||||
a feature copied from Enlightenment.
|
||||
|
||||
If you hold down Shift while moving a window, the window snaps
|
||||
to edges of other windows and the screen.
|
||||
|
||||
- Session management:
|
||||
|
||||
Mutter connects to the session manager and will set itself up to
|
||||
be respawned. It theoretically restores sizes/positions/workspace
|
||||
for session-aware applications.
|
||||
|
||||
- Mutter implements much of the EWMH window manager specification
|
||||
from freedesktop.org, as well as the older ICCCM. Please refer to
|
||||
the COMPLIANCE file for information on mutter compliance with
|
||||
these standards.
|
||||
|
||||
- Uses Pango to render text, so has cool i18n capabilities.
|
||||
Supports UTF-8 window titles and such.
|
||||
|
||||
- There are simple animations for actions such as minimization,
|
||||
to help users see what is happening. Should probably
|
||||
have a few more of these and make them nicer.
|
||||
|
||||
- if you have the proper X setup, set the GDK_USE_XFT=1
|
||||
environment variable to get antialiased window titles.
|
||||
|
||||
- considers the panel when placing windows and maximizing
|
||||
them.
|
||||
|
||||
- handles the window manager selection from the ICCCM. Will exit if
|
||||
another WM claims it, and can claim it from another WM if you pass
|
||||
the --replace argument. So if you're running another
|
||||
ICCCM-compliant WM, you can run "mutter --replace" to replace it
|
||||
with Metacity.
|
||||
|
||||
- does basic colormap handling
|
||||
|
||||
- and much more! well, maybe not a lot more.
|
||||
|
||||
HOW TO ADD EXTERNAL FEATURES
|
||||
===
|
||||
|
||||
You can write a mutter "plugin" such as a pager, window list, icon
|
||||
box, task menu, or even things like "window matching" using the
|
||||
Extended Window Manager Hints. See http://www.freedesktop.org for the
|
||||
EWMH specification. An easy-to-use library called "libwnck" is
|
||||
available that uses the EWMH and is specifically designed for writing
|
||||
WM accessories.
|
||||
|
||||
You might be interested in existing accessories such as "Devil's Pie"
|
||||
by Ross Burton, which add features to Mutter (or other
|
||||
EWMH-compliant WMs).
|
||||
|
||||
MUTTER BUGS, NON-FEATURES, AND CAVEATS
|
||||
===
|
||||
|
||||
See bugzilla: http://bugzilla.gnome.org/query.cgi
|
||||
|
||||
FAQ
|
||||
===
|
||||
|
||||
Q: Will you add my feature?
|
||||
|
||||
A: If it makes sense to turn on unconditionally, or is genuinely a
|
||||
harmless preference that I would not be embarrassed to put in a
|
||||
simple, uncluttered, user-friendly configuration dialog.
|
||||
|
||||
If the only rationale for your feature is that other window
|
||||
managers have it, or that you are personally used to it, or
|
||||
something like that, then I will not be impressed. Metacity is
|
||||
firmly in the "choose good defaults" camp rather than the "offer 6
|
||||
equally broken ways to do it, and let the user pick one" camp.
|
||||
|
||||
This is part of a "no crackrock" policy, despite some exceptions
|
||||
I'm mildly embarrassed about. For example, multiple workspaces
|
||||
probably constitute crackrock, they confuse most users and really
|
||||
are not that useful if you have a decent tasklist and so on. But I
|
||||
am too used to them to turn them off. Or alternatively
|
||||
iconification/tasklist is crack, and workspaces/pager are good. But
|
||||
having both is certainly a bit wrong. Sloppy focus is probably
|
||||
crackrock too.
|
||||
|
||||
But don't think unlimited crack is OK just because I slipped up a
|
||||
little. No slippery slope here.
|
||||
|
||||
Don't let this discourage patches and fixes - I love those. ;-)
|
||||
Just be prepared to hear the above objections if your patch adds
|
||||
some crack-ridden configuration option.
|
||||
|
||||
http://pobox.com/~hp/free-software-ui.html
|
||||
http://pobox.com/~hp/features.html
|
||||
|
||||
Q: Will Mutter be part of GNOME?
|
||||
|
||||
A: It is not officially part of GNOME as of GNOME 2.27. We are
|
||||
hoping to have mutter officially included as of GNOME 2.28.
|
||||
|
||||
Q: Why does Mutter remember the workspace/position of some apps
|
||||
but not others across logout/login?
|
||||
|
||||
A: Mutter only stores sizes/positions for apps that are session
|
||||
managed. As far as I can determine, there is no way to attempt to
|
||||
remember workspace/position for non-session-aware apps without
|
||||
causing a lot of weird effects.
|
||||
|
||||
The reason is that you don't know which non-SM-aware apps were
|
||||
launched by the session. When you initially log in, Metacity sees a
|
||||
bunch of new windows appear. But it can't distinguish between
|
||||
windows that were stored in your session, or windows you just
|
||||
launched after logging in. If Metacity tried to guess that a window
|
||||
was from the session, it could e.g. end up maximizing a dialog, or
|
||||
put a window you just launched on another desktop or in a weird
|
||||
place. And in fact I see a lot of bugs like this in window managers
|
||||
that try to handle non-session-aware apps.
|
||||
|
||||
However, for session-aware apps, Mutter can tell that the
|
||||
application instance is from the session and thus restore it
|
||||
reliably, assuming the app properly restores the windows it had
|
||||
open on session save.
|
||||
|
||||
So the correct way to fix the situation is to make apps
|
||||
session-aware. libSM has come with X for years, it's very
|
||||
standardized, it's shared by GNOME and KDE - even twm is
|
||||
session-aware. So anyone who won't take a patch to add SM is more
|
||||
archaic than twm - and you should flame them. ;-)
|
||||
|
||||
Docs on session management:
|
||||
http://www.fifi.org/doc/xspecs/xsmp.txt.gz
|
||||
http://www.fifi.org/doc/xspecs/SMlib.txt.gz
|
||||
|
||||
See also the ICCCM section on SM. For GNOME apps, use the
|
||||
GnomeClient object. For a simple example of using libSM directly,
|
||||
twm/session.c in the twm source code is pretty easy to understand.
|
||||
|
||||
Q: How about adding viewports in addition to workspaces?
|
||||
|
||||
A: I could conceivably be convinced to use viewports _instead_ of
|
||||
workspaces, though currently I'm not thinking that. But I don't
|
||||
think it makes any sense to have both; it's just confusing. They
|
||||
are functionally equivalent.
|
||||
|
||||
You may think this means that you won't have certain keybindings,
|
||||
or something like that. This is a misconception. The only
|
||||
_fundamental_ difference between viewports and workspaces is that
|
||||
with viewports, windows can "overlap" and appear partially on
|
||||
one and partially on another. All other differences that
|
||||
traditionally exist in other window managers are accidental -
|
||||
the features commonly associated with viewports can be implemented
|
||||
for workspaces, and vice versa.
|
||||
|
||||
So I don't want to have two kinds of
|
||||
workspace/desktop/viewport/whatever, but I'm willing to add
|
||||
features traditionally associated with either kind if those
|
||||
features make sense.
|
||||
|
||||
Q: Why is the panel always on top?
|
||||
|
||||
A: Because it's a better user interface, and until we made this not
|
||||
configurable a bunch of apps were not getting fixed (the app
|
||||
authors were just saying "put your panel on the bottom" instead of
|
||||
properly supporting fullscreen mode, and such).
|
||||
|
||||
rationales.txt has the bugzilla URL for some flamefesting on this,
|
||||
if you want to go back and relive the glory.
|
||||
Read these and the bugzilla stuff before asking/commenting:
|
||||
http://pobox.com/~hp/free-software-ui.html
|
||||
http://pobox.com/~hp/features.html
|
||||
|
||||
Q: Why is there no edge flipping?
|
||||
|
||||
A: This one is also in rationales.txt. Because "ouija board" UI, where
|
||||
you just move the mouse around and the computer guesses what you
|
||||
mean, has a lot of issues. This includes mouse focus, shade-hover
|
||||
mode, edge flipping, autoraise, etc. Metacity has mouse focus and
|
||||
autoraise as a compromise, but these features are all confusing for
|
||||
many users, and cause problems with accessibility, fitt's law, and
|
||||
so on.
|
||||
|
||||
Read these and the bugzilla stuff before asking/commenting:
|
||||
http://pobox.com/~hp/free-software-ui.html
|
||||
http://pobox.com/~hp/features.html
|
||||
|
||||
Q: Why does wireframe move/resize suck?
|
||||
|
||||
A: You can turn it on with the reduced_resources setting.
|
||||
|
||||
But: it has low usability, and is a pain
|
||||
to implement, and there's no reason opaque move/resize should be a
|
||||
problem on any setup that can run a modern desktop worth a darn to
|
||||
begin with.
|
||||
|
||||
Read these and the bugzilla stuff before asking/commenting:
|
||||
http://pobox.com/~hp/free-software-ui.html
|
||||
http://pobox.com/~hp/features.html
|
||||
|
||||
The reason we had to add wireframe anyway was broken
|
||||
proprietary apps that can't handle lots of resize events.
|
||||
|
||||
Q: Why no XYZ?
|
||||
|
||||
A: You are probably getting the idea by now - check rationales.txt,
|
||||
query/search bugzilla, and read http://pobox.com/~hp/features.html
|
||||
and http://pobox.com/~hp/free-software-ui.html
|
||||
|
||||
Then sit down and answer the question for yourself. Is the feature
|
||||
good? What's the rationale for it? Answer "why" not just "why not."
|
||||
Justify in terms of users as a whole, not just users like
|
||||
yourself. How else can you solve the same problem? etc. If that
|
||||
leads you to a strong opinion, then please, post the rationale for
|
||||
discussion to an appropriate bugzilla bug, or to
|
||||
usability@gnome.org.
|
||||
|
||||
Please don't just "me too!" on bugzilla bugs, please don't think
|
||||
flames will get you anywhere, and please don't repeat rationale
|
||||
that's already been offered.
|
||||
|
||||
Q: Your dumb web pages you made me read talk about solving problems in
|
||||
fundamental ways instead of adding preferences or workarounds.
|
||||
What are some examples where metacity has done this?
|
||||
|
||||
A: There are quite a few, though many opportunities remain. Sometimes
|
||||
the real fix involves application changes. The metacity approach is
|
||||
that it's OK to require apps to change, though there are also
|
||||
plenty of workarounds in metacity for battles considered too hard
|
||||
to fight.
|
||||
|
||||
Here are some examples:
|
||||
|
||||
- fullscreen mode was introduced to allow position constraints,
|
||||
panel-on-top, and other such things to apply to normal windows
|
||||
while still allowing video players etc. to "just work"
|
||||
|
||||
- "whether to include minimized windows in Alt+Tab" was solved
|
||||
by putting minimized windows at the *end* of the tab order.
|
||||
|
||||
- Whether to pop up a feedback display during Alt+Tab was solved by
|
||||
having both Alt+Tab and Alt+Esc
|
||||
|
||||
- Whether to have a "kill" feature was solved by automatically
|
||||
detecting and offering to kill stuck apps. Better, metacity
|
||||
actually does "kill -9" on the process, it doesn't just
|
||||
disconnect the process from the X server. You'll appreciate this
|
||||
if you ever did a "kill" on Netscape 4, and watched it keep
|
||||
eating 100% CPU even though the X server had booted it.
|
||||
|
||||
- The workspaces vs. viewports mess was avoided by adding
|
||||
directional navigation and such to workspaces, see discussion
|
||||
earlier in this file.
|
||||
|
||||
- Instead of configurable placement algorithms, there's just one
|
||||
that works fairly well most of the time.
|
||||
|
||||
- To avoid excess CPU use during opaque move/resize, we rate limit
|
||||
the updates to the application window's size.
|
||||
|
||||
- Instead of configurable "show size of window while resizing,"
|
||||
it's only shown for windows where it matters, such as terminals.
|
||||
(Only use-case given for all windows is for web designers
|
||||
choosing their web browser size, but there are web sites and
|
||||
desktop backgrounds that do this for you.)
|
||||
|
||||
- Using startup notification, applications open on the workspace
|
||||
where you launched them, not the active workspace when their
|
||||
window is opened.
|
||||
|
||||
- and much more.
|
||||
|
||||
Q: I think mutter sucks.
|
||||
|
||||
A: Feel free to use any WM you like. The reason metacity follows the
|
||||
ICCCM and EWMH specifications is that it makes metacity a modular,
|
||||
interchangeable part in the desktop. libwnck-based apps such as the
|
||||
GNOME window list will work just fine with any EWMH-compliant WM.
|
||||
|
||||
Q: Did you spend a lot of time on this?
|
||||
|
||||
A: Originally the answer was no. Sadly the answer is now yes.
|
||||
|
||||
Q: How can you claim that you are anti-crack, while still
|
||||
writing a window manager?
|
||||
|
||||
A: I have no comment on that.
|
@@ -1,11 +1,11 @@
|
||||
#!/bin/bash
|
||||
#!/bin/sh
|
||||
# Run this to generate all the initial makefiles, etc.
|
||||
|
||||
srcdir=`dirname $0`
|
||||
test -z "$srcdir" && srcdir=.
|
||||
|
||||
PKG_NAME="mutter"
|
||||
REQUIRED_AUTOMAKE_VERSION=1.13
|
||||
REQUIRED_AUTOMAKE_VERSION=1.10
|
||||
|
||||
(test -f $srcdir/configure.ac \
|
||||
&& test -d $srcdir/src) || {
|
||||
|
15
configure.ac
15
configure.ac
@@ -2,8 +2,8 @@ AC_PREREQ(2.50)
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
m4_define([mutter_major_version], [3])
|
||||
m4_define([mutter_minor_version], [11])
|
||||
m4_define([mutter_micro_version], [5])
|
||||
m4_define([mutter_minor_version], [12])
|
||||
m4_define([mutter_micro_version], [0])
|
||||
|
||||
m4_define([mutter_version],
|
||||
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
||||
@@ -78,7 +78,7 @@ MUTTER_PC_MODULES="
|
||||
cairo >= 1.10.0
|
||||
gsettings-desktop-schemas >= 3.7.3
|
||||
xcomposite >= 0.2 xfixes xrender xdamage xi >= 1.6.0
|
||||
$CLUTTER_PACKAGE >= 1.17.1
|
||||
$CLUTTER_PACKAGE >= 1.17.5
|
||||
cogl-1.0 >= 1.17.1
|
||||
upower-glib >= 0.99.0
|
||||
gnome-desktop-3.0
|
||||
@@ -142,11 +142,6 @@ AM_GLIB_GNU_GETTEXT
|
||||
PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.14.0)
|
||||
PKG_CHECK_MODULES(MUTTER_LAUNCH, libdrm libsystemd-login)
|
||||
|
||||
saved_LIBS="$LIBS"
|
||||
LIBS="$LIBS $MUTTER_LAUNCH"
|
||||
AC_CHECK_FUNCS([sd_session_get_vt])
|
||||
LIBS="$saved_LIBS"
|
||||
|
||||
# Unconditionally use this dir to avoid a circular dep with gnomecc
|
||||
GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings"
|
||||
AC_SUBST(GNOME_KEYBINDINGS_KEYSDIR)
|
||||
@@ -212,9 +207,6 @@ fi
|
||||
|
||||
MUTTER_PC_MODULES="$MUTTER_PC_MODULES xcursor"
|
||||
|
||||
# We always build with wayland enabled
|
||||
AC_DEFINE(HAVE_WAYLAND, , [Building with Wayland support])
|
||||
|
||||
AC_PATH_PROG([WAYLAND_SCANNER],[wayland-scanner],[no])
|
||||
AS_IF([test "x$WAYLAND_SCANNER" = "xno"],
|
||||
AC_MSG_ERROR([Could not find wayland-scanner in your PATH, required for parsing wayland extension protocols]))
|
||||
@@ -461,7 +453,6 @@ doc/reference/meta-docs.sgml
|
||||
src/Makefile
|
||||
src/libmutter-wayland.pc
|
||||
src/compositor/plugins/Makefile
|
||||
protocol/Makefile
|
||||
po/Makefile.in
|
||||
])
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
SUBDIRS = man reference
|
||||
|
||||
EXTRA_DIST=theme-format.txt dialogs.txt code-overview.txt \
|
||||
how-to-get-focus-right.txt
|
||||
how-to-get-focus-right.txt rationales.txt
|
||||
|
@@ -96,8 +96,6 @@ meta_compositor_hide_window
|
||||
meta_compositor_switch_workspace
|
||||
meta_compositor_maximize_window
|
||||
meta_compositor_unmaximize_window
|
||||
meta_compositor_window_mapped
|
||||
meta_compositor_window_unmapped
|
||||
meta_compositor_sync_window_geometry
|
||||
meta_compositor_set_updates_frozen
|
||||
meta_compositor_queue_frame_drawn
|
||||
|
@@ -16,11 +16,11 @@ src/core/monitor.c
|
||||
src/core/mutter.c
|
||||
src/core/prefs.c
|
||||
src/core/screen.c
|
||||
src/core/session.c
|
||||
src/x11/session.c
|
||||
src/core/util.c
|
||||
src/core/window.c
|
||||
src/core/window-props.c
|
||||
src/core/xprops.c
|
||||
src/x11/window-props.c
|
||||
src/x11/xprops.c
|
||||
src/mutter-wayland.desktop.in
|
||||
src/org.gnome.mutter.gschema.xml.in
|
||||
src/org.gnome.mutter.wayland.gschema.xml.in
|
||||
|
@@ -1,7 +0,0 @@
|
||||
NULL =
|
||||
|
||||
EXTRA_DIST = \
|
||||
gtk-shell.xml \
|
||||
xdg-shell.xml \
|
||||
xserver.xml \
|
||||
$(NULL)
|
@@ -29,6 +29,18 @@
|
||||
<KeyListEntry name="move-to-workspace-down"
|
||||
_description="Move window one workspace down" />
|
||||
|
||||
<KeyListEntry name="move-to-monitor-left"
|
||||
_description="Move window one monitor to the left" />
|
||||
|
||||
<KeyListEntry name="move-to-monitor-right"
|
||||
_description="Move window one monitor to the right" />
|
||||
|
||||
<KeyListEntry name="move-to-monitor-up"
|
||||
_description="Move window one monitor up" />
|
||||
|
||||
<KeyListEntry name="move-to-monitor-down"
|
||||
_description="Move window one monitor down" />
|
||||
|
||||
<KeyListEntry name="switch-applications"
|
||||
_description="Switch applications"/>
|
||||
|
||||
|
103
src/Makefile.am
103
src/Makefile.am
@@ -6,6 +6,7 @@ lib_LTLIBRARIES = libmutter-wayland.la
|
||||
SUBDIRS=compositor/plugins
|
||||
|
||||
INCLUDES= \
|
||||
-DCLUTTER_ENABLE_COMPOSITOR_API \
|
||||
-DCLUTTER_ENABLE_EXPERIMENTAL_API \
|
||||
-DCOGL_ENABLE_EXPERIMENTAL_API \
|
||||
-DCOGL_ENABLE_EXPERIMENTAL_2_0_API \
|
||||
@@ -28,11 +29,7 @@ INCLUDES= \
|
||||
-DMUTTER_PLUGIN_API_VERSION=$(MUTTER_PLUGIN_API_VERSION) \
|
||||
-DMUTTER_PKGLIBDIR=\"$(pkglibdir)\" \
|
||||
-DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\" \
|
||||
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\"
|
||||
|
||||
INCLUDES += \
|
||||
-I$(srcdir)/wayland \
|
||||
-I$(builddir)/wayland \
|
||||
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \
|
||||
-DXWAYLAND_PATH='"@XWAYLAND_PATH@"'
|
||||
|
||||
mutter_built_sources = \
|
||||
@@ -40,19 +37,20 @@ mutter_built_sources = \
|
||||
$(dbus_xrandr_built_sources) \
|
||||
mutter-enum-types.h \
|
||||
mutter-enum-types.c \
|
||||
wayland/gtk-shell-protocol.c \
|
||||
wayland/gtk-shell-server-protocol.h \
|
||||
wayland/gtk-shell-client-protocol.h \
|
||||
wayland/xdg-shell-protocol.c \
|
||||
wayland/xdg-shell-server-protocol.h \
|
||||
wayland/xdg-shell-client-protocol.h \
|
||||
wayland/xserver-protocol.c \
|
||||
wayland/xserver-server-protocol.h \
|
||||
wayland/xserver-client-protocol.h
|
||||
gtk-shell-protocol.c \
|
||||
gtk-shell-server-protocol.h \
|
||||
xdg-shell-protocol.c \
|
||||
xdg-shell-server-protocol.h \
|
||||
xserver-protocol.c \
|
||||
xserver-server-protocol.h
|
||||
|
||||
wayland_protocols = \
|
||||
wayland/protocol/gtk-shell.xml \
|
||||
wayland/protocol/xdg-shell.xml \
|
||||
wayland/protocol/xserver.xml
|
||||
|
||||
libmutter_wayland_la_SOURCES = \
|
||||
core/async-getprop.c \
|
||||
core/async-getprop.h \
|
||||
core/above-tab-keycode.c \
|
||||
core/barrier.c \
|
||||
meta/barrier.h \
|
||||
core/bell.c \
|
||||
@@ -83,6 +81,10 @@ libmutter_wayland_la_SOURCES = \
|
||||
compositor/meta-shaped-texture-private.h \
|
||||
compositor/meta-surface-actor.c \
|
||||
compositor/meta-surface-actor.h \
|
||||
compositor/meta-surface-actor-x11.c \
|
||||
compositor/meta-surface-actor-x11.h \
|
||||
compositor/meta-surface-actor-wayland.c \
|
||||
compositor/meta-surface-actor-wayland.h \
|
||||
compositor/meta-texture-rectangle.c \
|
||||
compositor/meta-texture-rectangle.h \
|
||||
compositor/meta-texture-tower.c \
|
||||
@@ -103,7 +105,6 @@ libmutter_wayland_la_SOURCES = \
|
||||
meta/meta-shadow-factory.h \
|
||||
meta/meta-window-actor.h \
|
||||
meta/compositor-mutter.h \
|
||||
core/above-tab-keycode.c \
|
||||
core/constraints.c \
|
||||
core/constraints.h \
|
||||
core/core.c \
|
||||
@@ -111,25 +112,18 @@ libmutter_wayland_la_SOURCES = \
|
||||
core/display.c \
|
||||
core/display-private.h \
|
||||
meta/display.h \
|
||||
ui/draw-workspace.c \
|
||||
ui/draw-workspace.h \
|
||||
core/edge-resistance.c \
|
||||
core/edge-resistance.h \
|
||||
core/edid-parse.c \
|
||||
core/edid.h \
|
||||
core/events.c \
|
||||
core/events.h \
|
||||
core/errors.c \
|
||||
meta/errors.h \
|
||||
core/frame.c \
|
||||
core/frame.h \
|
||||
ui/gradient.c \
|
||||
meta/gradient.h \
|
||||
core/group-private.h \
|
||||
core/group-props.c \
|
||||
core/group-props.h \
|
||||
core/group.c \
|
||||
meta/group.h \
|
||||
core/iconcache.c \
|
||||
core/iconcache.h \
|
||||
core/keybindings.c \
|
||||
core/keybindings-private.h \
|
||||
core/main.c \
|
||||
@@ -152,8 +146,6 @@ libmutter_wayland_la_SOURCES = \
|
||||
core/screen-private.h \
|
||||
meta/screen.h \
|
||||
meta/types.h \
|
||||
core/session.c \
|
||||
core/session.h \
|
||||
core/stack.c \
|
||||
core/stack.h \
|
||||
core/stack-tracker.c \
|
||||
@@ -161,17 +153,11 @@ libmutter_wayland_la_SOURCES = \
|
||||
core/util.c \
|
||||
meta/util.h \
|
||||
core/util-private.h \
|
||||
core/window-props.c \
|
||||
core/window-props.h \
|
||||
core/window-x11.c \
|
||||
core/window-x11.h \
|
||||
core/window.c \
|
||||
core/window-private.h \
|
||||
meta/window.h \
|
||||
core/workspace.c \
|
||||
core/workspace-private.h \
|
||||
core/xprops.c \
|
||||
core/xprops.h \
|
||||
meta/common.h \
|
||||
core/core.h \
|
||||
ui/ui.h \
|
||||
@@ -183,21 +169,31 @@ libmutter_wayland_la_SOURCES = \
|
||||
ui/metaaccellabel.h \
|
||||
ui/resizepopup.c \
|
||||
ui/resizepopup.h \
|
||||
ui/tabpopup.c \
|
||||
ui/tabpopup.h \
|
||||
ui/tile-preview.c \
|
||||
ui/tile-preview.h \
|
||||
ui/theme-parser.c \
|
||||
ui/theme.c \
|
||||
meta/theme.h \
|
||||
ui/theme-private.h \
|
||||
ui/ui.c
|
||||
|
||||
nodist_libmutter_wayland_la_SOURCES = \
|
||||
$(mutter_built_sources)
|
||||
|
||||
libmutter_wayland_la_SOURCES += \
|
||||
ui/ui.c \
|
||||
x11/iconcache.c \
|
||||
x11/iconcache.h \
|
||||
x11/async-getprop.c \
|
||||
x11/async-getprop.h \
|
||||
x11/group-private.h \
|
||||
x11/group-props.c \
|
||||
x11/group-props.h \
|
||||
x11/group.c \
|
||||
meta/group.h \
|
||||
x11/session.c \
|
||||
x11/session.h \
|
||||
x11/window-props.c \
|
||||
x11/window-props.h \
|
||||
x11/window-x11.c \
|
||||
x11/window-x11.h \
|
||||
x11/window-x11-private.h \
|
||||
x11/xprops.c \
|
||||
x11/xprops.h \
|
||||
wayland/meta-wayland.c \
|
||||
wayland/meta-wayland.h \
|
||||
wayland/meta-wayland-private.h \
|
||||
wayland/meta-xwayland-private.h \
|
||||
wayland/meta-xwayland.c \
|
||||
@@ -216,7 +212,12 @@ libmutter_wayland_la_SOURCES += \
|
||||
wayland/meta-wayland-types.h \
|
||||
wayland/meta-wayland-versions.h \
|
||||
wayland/meta-weston-launch.c \
|
||||
wayland/meta-weston-launch.h
|
||||
wayland/meta-weston-launch.h \
|
||||
wayland/window-wayland.c \
|
||||
wayland/window-wayland.h
|
||||
|
||||
nodist_libmutter_wayland_la_SOURCES = \
|
||||
$(mutter_built_sources)
|
||||
|
||||
libmutter_wayland_la_LDFLAGS = -no-undefined
|
||||
libmutter_wayland_la_LIBADD = $(MUTTER_LIBS)
|
||||
@@ -314,7 +315,7 @@ endif
|
||||
|
||||
testboxes_SOURCES = core/testboxes.c
|
||||
testgradient_SOURCES = ui/testgradient.c
|
||||
testasyncgetprop_SOURCES = core/testasyncgetprop.c
|
||||
testasyncgetprop_SOURCES = x11/testasyncgetprop.c
|
||||
|
||||
noinst_PROGRAMS=testboxes testgradient testasyncgetprop
|
||||
|
||||
@@ -365,6 +366,7 @@ EXTRA_DIST=$(desktopfiles_files) \
|
||||
$(desktopfiles_in_files) \
|
||||
$(wmproperties_in_files) \
|
||||
$(xml_in_files) \
|
||||
$(wayland_protocols) \
|
||||
org.gnome.mutter.gschema.xml.in \
|
||||
org.gnome.mutter.wayland.gschema.xml.in \
|
||||
mutter-schemas.convert \
|
||||
@@ -414,12 +416,7 @@ $(dbus_idle_built_sources) : Makefile.am idle-monitor.xml
|
||||
--c-generate-object-manager \
|
||||
$(srcdir)/idle-monitor.xml
|
||||
|
||||
wayland/%-protocol.c : $(top_builddir)/protocol/%.xml
|
||||
mkdir -p wayland
|
||||
%-protocol.c : $(srcdir)/wayland/protocol/%.xml
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
|
||||
wayland/%-server-protocol.h : $(top_builddir)/protocol/%.xml
|
||||
mkdir -p wayland
|
||||
%-server-protocol.h : $(srcdir)/wayland/protocol/%.xml
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) server-header < $< > $@
|
||||
wayland/%-client-protocol.h : $(top_builddir)/protocol/%.xml
|
||||
mkdir -p wayland
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@
|
||||
|
@@ -19,16 +19,10 @@ struct _MetaCompositor
|
||||
|
||||
guint repaint_func_id;
|
||||
|
||||
ClutterActor *shadow_src;
|
||||
|
||||
MetaPlugin *modal_plugin;
|
||||
|
||||
gint64 server_time_query_time;
|
||||
gint64 server_time_offset;
|
||||
|
||||
guint server_time_is_monotonic_time : 1;
|
||||
guint show_redraw : 1;
|
||||
guint debug : 1;
|
||||
guint no_mipmaps : 1;
|
||||
};
|
||||
|
||||
@@ -36,10 +30,9 @@ struct _MetaCompScreen
|
||||
{
|
||||
MetaScreen *screen;
|
||||
|
||||
ClutterActor *stage, *window_group, *top_window_group, *overlay_group;
|
||||
ClutterActor *stage, *window_group, *top_window_group;
|
||||
ClutterActor *background_actor;
|
||||
GList *windows;
|
||||
GHashTable *windows_by_xid;
|
||||
Window output;
|
||||
|
||||
CoglOnscreen *onscreen;
|
||||
@@ -70,6 +63,4 @@ void meta_end_modal_for_plugin (MetaScreen *screen,
|
||||
gint64 meta_compositor_monotonic_time_to_server_time (MetaDisplay *display,
|
||||
gint64 monotonic_time);
|
||||
|
||||
void meta_check_end_modal (MetaScreen *screen);
|
||||
|
||||
#endif /* META_COMPOSITOR_PRIVATE_H */
|
||||
|
@@ -42,15 +42,6 @@
|
||||
* the call, so it may be necessary to readjust the display based on the
|
||||
* old_rect to start the animation.
|
||||
*
|
||||
* meta_compositor_window_mapped() and meta_compositor_window_unmapped() are
|
||||
* notifications when the toplevel window (frame or client window) is mapped or
|
||||
* unmapped. That is, when the result of meta_window_toplevel_is_mapped()
|
||||
* changes. The main use of this is to drop resources when a window is unmapped.
|
||||
* A window will always be mapped before meta_compositor_show_window()
|
||||
* is called and will not be unmapped until after meta_compositor_hide_window()
|
||||
* is called. If the live_hidden_windows preference is set, windows will never
|
||||
* be unmapped.
|
||||
*
|
||||
* # Containers #
|
||||
*
|
||||
* There's two containers in the stage that are used to place window actors, here
|
||||
@@ -74,7 +65,6 @@
|
||||
#include <meta/window.h>
|
||||
#include "compositor-private.h"
|
||||
#include <meta/compositor-mutter.h>
|
||||
#include "xprops.h"
|
||||
#include <meta/prefs.h>
|
||||
#include <meta/main.h>
|
||||
#include <meta/meta-background-actor.h>
|
||||
@@ -85,14 +75,17 @@
|
||||
#include "window-private.h" /* to check window->hidden */
|
||||
#include "display-private.h" /* for meta_display_lookup_x_window() */
|
||||
#include "util-private.h"
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-wayland-pointer.h"
|
||||
#include "meta-wayland-keyboard.h"
|
||||
#include "frame.h"
|
||||
#include <X11/extensions/shape.h>
|
||||
#include <X11/extensions/Xcomposite.h>
|
||||
|
||||
/* #define DEBUG_TRACE g_print */
|
||||
#define DEBUG_TRACE(X)
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
|
||||
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)
|
||||
@@ -117,13 +110,8 @@ meta_finish_workspace_switch (MetaCompScreen *info)
|
||||
for (l = info->windows; l; l = l->next)
|
||||
meta_window_actor_sync_visibility (l->data);
|
||||
|
||||
/*
|
||||
* Fix up stacking order in case the plugin messed it up.
|
||||
*/
|
||||
/* Fix up stacking order. */
|
||||
sync_actor_stacking (info);
|
||||
|
||||
/* printf ("... FINISHED DESKTOP SWITCH\n"); */
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
@@ -149,33 +137,12 @@ meta_compositor_destroy (MetaCompositor *compositor)
|
||||
clutter_threads_remove_repaint_func (compositor->repaint_func_id);
|
||||
}
|
||||
|
||||
static void
|
||||
add_win (MetaWindow *window)
|
||||
{
|
||||
MetaScreen *screen = meta_window_get_screen (window);
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
g_return_if_fail (info != NULL);
|
||||
|
||||
meta_window_actor_new (window);
|
||||
|
||||
sync_actor_stacking (info);
|
||||
}
|
||||
|
||||
static void
|
||||
process_damage (MetaCompositor *compositor,
|
||||
XDamageNotifyEvent *event,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaWindowActor *window_actor;
|
||||
|
||||
if (window == NULL)
|
||||
return;
|
||||
|
||||
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
if (window_actor == NULL)
|
||||
return;
|
||||
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
meta_window_actor_process_x11_damage (window_actor, event);
|
||||
}
|
||||
|
||||
@@ -338,39 +305,36 @@ meta_focus_stage_window (MetaScreen *screen,
|
||||
if (!stage)
|
||||
return;
|
||||
|
||||
if (!meta_is_wayland_compositor ())
|
||||
{
|
||||
window = clutter_x11_get_stage_window (stage);
|
||||
window = clutter_x11_get_stage_window (stage);
|
||||
|
||||
if (window == None)
|
||||
return;
|
||||
if (window == None)
|
||||
return;
|
||||
|
||||
meta_display_set_input_focus_xwindow (screen->display,
|
||||
screen,
|
||||
META_FOCUS_STAGE,
|
||||
window,
|
||||
timestamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_display_set_input_focus_xwindow (screen->display,
|
||||
screen,
|
||||
META_FOCUS_STAGE,
|
||||
None,
|
||||
timestamp);
|
||||
}
|
||||
meta_display_set_input_focus_xwindow (screen->display,
|
||||
screen,
|
||||
window,
|
||||
timestamp);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_stage_is_focused (MetaScreen *screen)
|
||||
{
|
||||
ClutterStage *stage;
|
||||
Window window;
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
return TRUE;
|
||||
|
||||
stage = CLUTTER_STAGE (meta_get_stage_for_screen (screen));
|
||||
if (!stage)
|
||||
return FALSE;
|
||||
|
||||
return (screen->display->focus_type == META_FOCUS_STAGE);
|
||||
window = clutter_x11_get_stage_window (stage);
|
||||
|
||||
if (window == None)
|
||||
return FALSE;
|
||||
|
||||
return (screen->display->focus_xwindow == window);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -383,7 +347,6 @@ begin_modal_x11 (MetaScreen *screen,
|
||||
Display *xdpy = meta_display_get_xdisplay (display);
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
Window grab_window = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
|
||||
Cursor cursor = None;
|
||||
int result;
|
||||
gboolean pointer_grabbed = FALSE;
|
||||
gboolean keyboard_grabbed = FALSE;
|
||||
@@ -403,7 +366,7 @@ begin_modal_x11 (MetaScreen *screen,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
grab_window,
|
||||
timestamp,
|
||||
cursor,
|
||||
None,
|
||||
XIGrabModeAsync, XIGrabModeAsync,
|
||||
False, /* owner_events */
|
||||
&mask);
|
||||
@@ -447,45 +410,6 @@ begin_modal_x11 (MetaScreen *screen,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
begin_modal_wayland (MetaScreen *screen,
|
||||
MetaPlugin *plugin,
|
||||
MetaModalOptions options,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaWaylandCompositor *compositor;
|
||||
gboolean pointer_grabbed = FALSE;
|
||||
gboolean keyboard_grabbed = FALSE;
|
||||
|
||||
compositor = meta_wayland_compositor_get_default ();
|
||||
|
||||
if ((options & META_MODAL_POINTER_ALREADY_GRABBED) == 0)
|
||||
{
|
||||
if (!meta_wayland_pointer_begin_modal (&compositor->seat->pointer))
|
||||
goto fail;
|
||||
|
||||
pointer_grabbed = TRUE;
|
||||
}
|
||||
if ((options & META_MODAL_KEYBOARD_ALREADY_GRABBED) == 0)
|
||||
{
|
||||
if (!meta_wayland_keyboard_begin_modal (&compositor->seat->keyboard,
|
||||
timestamp))
|
||||
goto fail;
|
||||
|
||||
keyboard_grabbed = TRUE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
fail:
|
||||
if (pointer_grabbed)
|
||||
meta_wayland_pointer_end_modal (&compositor->seat->pointer);
|
||||
if (keyboard_grabbed)
|
||||
meta_wayland_keyboard_end_modal (&compositor->seat->keyboard, timestamp);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_begin_modal_for_plugin (MetaScreen *screen,
|
||||
MetaPlugin *plugin,
|
||||
@@ -496,19 +420,14 @@ meta_begin_modal_for_plugin (MetaScreen *screen,
|
||||
* are significant differences in how we handle grabs that make it difficult to
|
||||
* merge the two.
|
||||
*/
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
MetaCompositor *compositor = display->compositor;
|
||||
gboolean ok;
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
|
||||
if (compositor->modal_plugin != NULL || display->grab_op != META_GRAB_OP_NONE)
|
||||
if (is_modal (display) || display->grab_op != META_GRAB_OP_NONE)
|
||||
return FALSE;
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
ok = begin_modal_wayland (screen, plugin, options, timestamp);
|
||||
else
|
||||
ok = begin_modal_x11 (screen, plugin, options, timestamp);
|
||||
if (!ok)
|
||||
return FALSE;
|
||||
if (!meta_is_wayland_compositor ())
|
||||
if (!begin_modal_x11 (screen, plugin, options, timestamp))
|
||||
return FALSE;
|
||||
|
||||
display->grab_op = META_GRAB_OP_COMPOSITOR;
|
||||
display->grab_window = NULL;
|
||||
@@ -516,7 +435,8 @@ meta_begin_modal_for_plugin (MetaScreen *screen,
|
||||
display->grab_have_pointer = TRUE;
|
||||
display->grab_have_keyboard = TRUE;
|
||||
|
||||
compositor->modal_plugin = plugin;
|
||||
if (meta_is_wayland_compositor ())
|
||||
meta_display_sync_wayland_input_focus (display);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -526,25 +446,10 @@ meta_end_modal_for_plugin (MetaScreen *screen,
|
||||
MetaPlugin *plugin,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
Display *xdpy = meta_display_get_xdisplay (display);
|
||||
MetaCompositor *compositor = display->compositor;
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
Display *xdpy = meta_display_get_xdisplay (display);
|
||||
|
||||
g_return_if_fail (compositor->modal_plugin == plugin);
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||
|
||||
meta_wayland_pointer_end_modal (&compositor->seat->pointer);
|
||||
meta_wayland_keyboard_end_modal (&compositor->seat->keyboard,
|
||||
timestamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_POINTER_ID, timestamp);
|
||||
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
|
||||
}
|
||||
g_return_if_fail (is_modal (display));
|
||||
|
||||
display->grab_op = META_GRAB_OP_NONE;
|
||||
display->grab_window = NULL;
|
||||
@@ -552,25 +457,14 @@ meta_end_modal_for_plugin (MetaScreen *screen,
|
||||
display->grab_have_pointer = FALSE;
|
||||
display->grab_have_keyboard = FALSE;
|
||||
|
||||
compositor->modal_plugin = NULL;
|
||||
}
|
||||
|
||||
/* This is used when reloading plugins to make sure we don't have
|
||||
* a left-over modal grab for this screen.
|
||||
*/
|
||||
void
|
||||
meta_check_end_modal (MetaScreen *screen)
|
||||
{
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
MetaCompositor *compositor = display->compositor;
|
||||
|
||||
if (compositor->modal_plugin &&
|
||||
meta_plugin_get_screen (compositor->modal_plugin) == screen)
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
meta_end_modal_for_plugin (screen,
|
||||
compositor->modal_plugin,
|
||||
|
||||
CurrentTime);
|
||||
meta_display_sync_wayland_input_focus (display);
|
||||
}
|
||||
else
|
||||
{
|
||||
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_POINTER_ID, timestamp);
|
||||
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -773,18 +667,25 @@ meta_compositor_unmanage_screen (MetaCompositor *compositor,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Shapes the cow so that the given window is exposed,
|
||||
* when metaWindow is NULL it clears the shape again
|
||||
/**
|
||||
* meta_shape_cow_for_window:
|
||||
* @screen: A #MetaScreen
|
||||
* @window: (allow-none): A #MetaWindow to shape the COW for
|
||||
*
|
||||
* Sets an bounding shape on the COW so that the given window
|
||||
* is exposed. If @window is %NULL it clears the shape again.
|
||||
*
|
||||
* Used so we can unredirect windows, by shaping away the part
|
||||
* of the COW, letting the raw window be seen through below.
|
||||
*/
|
||||
static void
|
||||
meta_shape_cow_for_window (MetaScreen *screen,
|
||||
MetaWindow *metaWindow)
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
Display *xdisplay = meta_display_get_xdisplay (meta_screen_get_display (screen));
|
||||
|
||||
if (metaWindow == NULL)
|
||||
if (window == NULL)
|
||||
XFixesSetWindowShapeRegion (xdisplay, info->output, ShapeBounding, 0, 0, None);
|
||||
else
|
||||
{
|
||||
@@ -793,7 +694,7 @@ meta_shape_cow_for_window (MetaScreen *screen,
|
||||
int width, height;
|
||||
MetaRectangle rect;
|
||||
|
||||
meta_window_get_frame_rect (metaWindow, &rect);
|
||||
meta_window_get_frame_rect (window, &rect);
|
||||
|
||||
window_bounds.x = rect.x;
|
||||
window_bounds.y = rect.y;
|
||||
@@ -844,11 +745,12 @@ meta_compositor_add_window (MetaCompositor *compositor,
|
||||
{
|
||||
MetaScreen *screen = meta_window_get_screen (window);
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
DEBUG_TRACE ("meta_compositor_add_window\n");
|
||||
meta_error_trap_push (display);
|
||||
|
||||
add_win (window);
|
||||
meta_window_actor_new (window);
|
||||
sync_actor_stacking (info);
|
||||
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
@@ -857,17 +759,9 @@ void
|
||||
meta_compositor_remove_window (MetaCompositor *compositor,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaWindowActor *window_actor = NULL;
|
||||
MetaScreen *screen;
|
||||
MetaCompScreen *info;
|
||||
|
||||
DEBUG_TRACE ("meta_compositor_remove_window\n");
|
||||
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
screen = meta_window_get_screen (window);
|
||||
info = meta_screen_get_compositor_data (screen);
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
MetaScreen *screen = meta_window_get_screen (window);
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
if (info->unredirected_window == window)
|
||||
set_unredirected_window (info, NULL);
|
||||
@@ -880,13 +774,7 @@ meta_compositor_set_updates_frozen (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
gboolean updates_frozen)
|
||||
{
|
||||
MetaWindowActor *window_actor;
|
||||
|
||||
DEBUG_TRACE ("meta_compositor_set_updates_frozen\n");
|
||||
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
meta_window_actor_set_updates_frozen (window_actor, updates_frozen);
|
||||
}
|
||||
|
||||
@@ -895,13 +783,7 @@ meta_compositor_queue_frame_drawn (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
gboolean no_delay_frame)
|
||||
{
|
||||
MetaWindowActor *window_actor;
|
||||
|
||||
DEBUG_TRACE ("meta_compositor_queue_frame_drawn\n");
|
||||
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
meta_window_actor_queue_frame_drawn (window_actor, no_delay_frame);
|
||||
}
|
||||
|
||||
@@ -952,6 +834,43 @@ meta_compositor_window_opacity_changed (MetaCompositor *compositor,
|
||||
meta_window_actor_update_opacity (window_actor);
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_window_surface_changed (MetaCompositor *compositor,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaWindowActor *window_actor;
|
||||
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
meta_window_actor_update_surface (window_actor);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
event_is_passive_button_grab (MetaDisplay *display,
|
||||
XIDeviceEvent *device_event)
|
||||
{
|
||||
/* see display.c for which events are passive button
|
||||
grabs (meta_display_grab_window_buttons() and
|
||||
meta_display_handle_events())
|
||||
we need to filter them here because normally they
|
||||
would be sent to gtk+ (they are on gtk+ frame xwindow),
|
||||
but we want to redirect them to clutter
|
||||
*/
|
||||
|
||||
if (device_event->evtype != XI_ButtonPress)
|
||||
return FALSE;
|
||||
|
||||
if (display->window_grab_modifiers == 0)
|
||||
return FALSE;
|
||||
|
||||
if ((device_event->mods.effective & display->window_grab_modifiers) !=
|
||||
display->window_grab_modifiers)
|
||||
return FALSE;
|
||||
|
||||
return device_event->detail < 4;
|
||||
}
|
||||
|
||||
/* Clutter makes the assumption that there is only one X window
|
||||
* per stage, which is a valid assumption to make for a generic
|
||||
* application toolkit. As such, it will ignore any events sent
|
||||
@@ -963,6 +882,7 @@ meta_compositor_window_opacity_changed (MetaCompositor *compositor,
|
||||
*/
|
||||
static void
|
||||
maybe_spoof_event_as_stage_event (MetaCompScreen *info,
|
||||
MetaWindow *window,
|
||||
XEvent *event)
|
||||
{
|
||||
MetaDisplay *display = meta_screen_get_display (info->screen);
|
||||
@@ -971,24 +891,30 @@ maybe_spoof_event_as_stage_event (MetaCompScreen *info,
|
||||
event->xcookie.extension == display->xinput_opcode)
|
||||
{
|
||||
XIEvent *input_event = (XIEvent *) event->xcookie.data;
|
||||
XIDeviceEvent *device_event = ((XIDeviceEvent *) input_event);
|
||||
|
||||
switch (input_event->evtype)
|
||||
{
|
||||
case XI_Motion:
|
||||
case XI_ButtonPress:
|
||||
case XI_ButtonRelease:
|
||||
/* If this is a window frame, and we think GTK+ needs to handle the event,
|
||||
let GTK+ handle it without mangling */
|
||||
if (window && window->frame && device_event->event == window->frame->xwindow &&
|
||||
(meta_grab_op_is_clicking (display->grab_op) ||
|
||||
(display->grab_op == META_GRAB_OP_NONE && !event_is_passive_button_grab (display, device_event))))
|
||||
break;
|
||||
|
||||
case XI_KeyPress:
|
||||
case XI_KeyRelease:
|
||||
{
|
||||
XIDeviceEvent *device_event = ((XIDeviceEvent *) input_event);
|
||||
|
||||
/* If this is a GTK+ widget, like a window menu, let GTK+ handle
|
||||
* it as-is without mangling. */
|
||||
if (meta_ui_window_is_widget (info->screen->ui, device_event->event))
|
||||
break;
|
||||
|
||||
device_event->event = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
|
||||
}
|
||||
device_event->event_x = device_event->root_x;
|
||||
device_event->event_y = device_event->root_y;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -1008,53 +934,26 @@ meta_compositor_process_event (MetaCompositor *compositor,
|
||||
XEvent *event,
|
||||
MetaWindow *window)
|
||||
{
|
||||
if (compositor->modal_plugin && is_grabbed_event (compositor->display, event))
|
||||
MetaDisplay *display = compositor->display;
|
||||
MetaScreen *screen = display->screens->data;
|
||||
MetaCompScreen *info;
|
||||
|
||||
info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
if (is_modal (display) && is_grabbed_event (compositor->display, event))
|
||||
{
|
||||
_meta_plugin_xevent_filter (compositor->modal_plugin, event);
|
||||
meta_plugin_manager_xevent_filter (info->plugin_mgr, event);
|
||||
|
||||
/* We always consume events even if the plugin says it didn't handle them;
|
||||
* exclusive is exclusive */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (window)
|
||||
{
|
||||
MetaCompScreen *info;
|
||||
MetaScreen *screen;
|
||||
if (!meta_is_wayland_compositor ())
|
||||
maybe_spoof_event_as_stage_event (info, window, event);
|
||||
|
||||
screen = meta_window_get_screen (window);
|
||||
info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
if (meta_plugin_manager_xevent_filter (info->plugin_mgr, event))
|
||||
{
|
||||
DEBUG_TRACE ("meta_compositor_process_event (filtered,window==NULL)\n");
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
l = meta_display_get_screens (compositor->display);
|
||||
|
||||
while (l)
|
||||
{
|
||||
MetaScreen *screen = l->data;
|
||||
MetaCompScreen *info;
|
||||
|
||||
info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
maybe_spoof_event_as_stage_event (info, event);
|
||||
|
||||
if (meta_plugin_manager_xevent_filter (info->plugin_mgr, event))
|
||||
{
|
||||
DEBUG_TRACE ("meta_compositor_process_event (filtered,window==NULL)\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
l = l->next;
|
||||
}
|
||||
}
|
||||
if (meta_plugin_manager_xevent_filter (info->plugin_mgr, event))
|
||||
return TRUE;
|
||||
|
||||
if (!meta_is_wayland_compositor () &&
|
||||
event->type == meta_display_get_damage_event_base (compositor->display) + XDamageNotify)
|
||||
@@ -1068,7 +967,6 @@ meta_compositor_process_event (MetaCompositor *compositor,
|
||||
window = meta_display_lookup_x_window (compositor->display, xwin);
|
||||
}
|
||||
|
||||
DEBUG_TRACE ("meta_compositor_process_event (process_damage)\n");
|
||||
process_damage (compositor, (XDamageNotifyEvent *) event, window);
|
||||
}
|
||||
|
||||
@@ -1090,11 +988,7 @@ meta_compositor_filter_keybinding (MetaCompositor *compositor,
|
||||
MetaKeyBinding *binding)
|
||||
{
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
if (info->plugin_mgr)
|
||||
return meta_plugin_manager_filter_keybinding (info->plugin_mgr, binding);
|
||||
|
||||
return FALSE;
|
||||
return meta_plugin_manager_filter_keybinding (info->plugin_mgr, binding);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1103,11 +997,7 @@ meta_compositor_show_window (MetaCompositor *compositor,
|
||||
MetaCompEffect effect)
|
||||
{
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
DEBUG_TRACE ("meta_compositor_show_window\n");
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
meta_window_actor_show (window_actor, effect);
|
||||
meta_window_actor_show (window_actor, effect);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1116,10 +1006,6 @@ meta_compositor_hide_window (MetaCompositor *compositor,
|
||||
MetaCompEffect effect)
|
||||
{
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
DEBUG_TRACE ("meta_compositor_hide_window\n");
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
meta_window_actor_hide (window_actor, effect);
|
||||
}
|
||||
|
||||
@@ -1130,10 +1016,6 @@ meta_compositor_maximize_window (MetaCompositor *compositor,
|
||||
MetaRectangle *new_rect)
|
||||
{
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
DEBUG_TRACE ("meta_compositor_maximize_window\n");
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
meta_window_actor_maximize (window_actor, old_rect, new_rect);
|
||||
}
|
||||
|
||||
@@ -1144,10 +1026,6 @@ meta_compositor_unmaximize_window (MetaCompositor *compositor,
|
||||
MetaRectangle *new_rect)
|
||||
{
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
DEBUG_TRACE ("meta_compositor_unmaximize_window\n");
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
meta_window_actor_unmaximize (window_actor, old_rect, new_rect);
|
||||
}
|
||||
|
||||
@@ -1165,18 +1043,14 @@ meta_compositor_switch_workspace (MetaCompositor *compositor,
|
||||
to_indx = meta_workspace_index (to);
|
||||
from_indx = meta_workspace_index (from);
|
||||
|
||||
DEBUG_TRACE ("meta_compositor_switch_workspace\n");
|
||||
|
||||
if (!info) /* During startup before manage_screen() */
|
||||
return;
|
||||
|
||||
info->switch_workspace_in_progress++;
|
||||
|
||||
if (!info->plugin_mgr ||
|
||||
!meta_plugin_manager_switch_workspace (info->plugin_mgr,
|
||||
from_indx,
|
||||
to_indx,
|
||||
direction))
|
||||
if (!meta_plugin_manager_switch_workspace (info->plugin_mgr,
|
||||
from_indx, to_indx,
|
||||
direction))
|
||||
{
|
||||
info->switch_workspace_in_progress--;
|
||||
|
||||
@@ -1285,8 +1159,6 @@ meta_compositor_sync_stack (MetaCompositor *compositor,
|
||||
GList *old_stack;
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
DEBUG_TRACE ("meta_compositor_sync_stack\n");
|
||||
|
||||
/* This is painful because hidden windows that we are in the process
|
||||
* of animating out of existence. They'll be at the bottom of the
|
||||
* stack of X windows, but we want to leave them in their old position
|
||||
@@ -1369,45 +1241,12 @@ meta_compositor_sync_stack (MetaCompositor *compositor,
|
||||
sync_actor_stacking (info);
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_window_mapped (MetaCompositor *compositor,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
DEBUG_TRACE ("meta_compositor_window_mapped\n");
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
meta_window_actor_mapped (window_actor);
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_window_unmapped (MetaCompositor *compositor,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
DEBUG_TRACE ("meta_compositor_window_unmapped\n");
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
meta_window_actor_unmapped (window_actor);
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_sync_window_geometry (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
gboolean did_placement)
|
||||
{
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
MetaScreen *screen = meta_window_get_screen (window);
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
DEBUG_TRACE ("meta_compositor_sync_window_geometry\n");
|
||||
g_return_if_fail (info);
|
||||
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
meta_window_actor_sync_actor_geometry (window_actor, did_placement);
|
||||
}
|
||||
|
||||
@@ -1439,7 +1278,6 @@ meta_compositor_sync_screen_size (MetaCompositor *compositor,
|
||||
Display *xdisplay;
|
||||
Window xwin;
|
||||
|
||||
DEBUG_TRACE ("meta_compositor_sync_screen_size\n");
|
||||
g_return_if_fail (info);
|
||||
|
||||
xdisplay = meta_display_get_xdisplay (display);
|
||||
@@ -1734,3 +1572,23 @@ meta_compositor_monotonic_time_to_server_time (MetaDisplay *display,
|
||||
else
|
||||
return monotonic_time + compositor->server_time_offset;
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_show_tile_preview (MetaCompositor *compositor,
|
||||
MetaScreen *screen,
|
||||
MetaWindow *window,
|
||||
MetaRectangle *tile_rect,
|
||||
int tile_monitor_number)
|
||||
{
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
meta_plugin_manager_show_tile_preview (info->plugin_mgr,
|
||||
window, tile_rect, tile_monitor_number);
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_hide_tile_preview (MetaCompositor *compositor,
|
||||
MetaScreen *screen)
|
||||
{
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
meta_plugin_manager_hide_tile_preview (info->plugin_mgr);
|
||||
}
|
||||
|
@@ -70,10 +70,16 @@ meta_cullable_cull_out_children (MetaCullable *cullable,
|
||||
while (clutter_actor_iter_prev (&iter, &child))
|
||||
{
|
||||
float x, y;
|
||||
gboolean needs_culling;
|
||||
|
||||
if (!CLUTTER_ACTOR_IS_VISIBLE (child))
|
||||
if (!META_IS_CULLABLE (child))
|
||||
continue;
|
||||
|
||||
needs_culling = (unobscured_region != NULL && clip_region != NULL);
|
||||
|
||||
if (needs_culling && !CLUTTER_ACTOR_IS_VISIBLE (child))
|
||||
needs_culling = FALSE;
|
||||
|
||||
/* If an actor has effects applied, then that can change the area
|
||||
* it paints and the opacity, so we no longer can figure out what
|
||||
* portion of the actor is obscured and what portion of the screen
|
||||
@@ -90,25 +96,29 @@ meta_cullable_cull_out_children (MetaCullable *cullable,
|
||||
* as well for the same reason, but omitted for simplicity in the
|
||||
* hopes that no-one will do that.
|
||||
*/
|
||||
if (clutter_actor_has_effects (child))
|
||||
continue;
|
||||
if (needs_culling && clutter_actor_has_effects (child))
|
||||
needs_culling = FALSE;
|
||||
|
||||
if (!META_IS_CULLABLE (child))
|
||||
continue;
|
||||
if (needs_culling && !meta_actor_is_untransformed (child, NULL, NULL))
|
||||
needs_culling = FALSE;
|
||||
|
||||
if (!meta_actor_is_untransformed (child, NULL, NULL))
|
||||
continue;
|
||||
if (needs_culling)
|
||||
{
|
||||
clutter_actor_get_position (child, &x, &y);
|
||||
|
||||
clutter_actor_get_position (child, &x, &y);
|
||||
/* Temporarily move to the coordinate system of the actor */
|
||||
cairo_region_translate (unobscured_region, - x, - y);
|
||||
cairo_region_translate (clip_region, - x, - y);
|
||||
|
||||
/* Temporarily move to the coordinate system of the actor */
|
||||
cairo_region_translate (unobscured_region, - x, - y);
|
||||
cairo_region_translate (clip_region, - x, - y);
|
||||
meta_cullable_cull_out (META_CULLABLE (child), unobscured_region, clip_region);
|
||||
|
||||
meta_cullable_cull_out (META_CULLABLE (child), unobscured_region, clip_region);
|
||||
|
||||
cairo_region_translate (unobscured_region, x, y);
|
||||
cairo_region_translate (clip_region, x, y);
|
||||
cairo_region_translate (unobscured_region, x, y);
|
||||
cairo_region_translate (clip_region, x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_cullable_cull_out (META_CULLABLE (child), NULL, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -100,7 +100,9 @@ meta_plugin_manager_new (MetaScreen *screen)
|
||||
|
||||
plugin_mgr = g_new0 (MetaPluginManager, 1);
|
||||
plugin_mgr->screen = screen;
|
||||
plugin_mgr->plugin = plugin = g_object_new (plugin_type, "screen", screen, NULL);
|
||||
plugin_mgr->plugin = plugin = g_object_new (plugin_type, NULL);
|
||||
|
||||
_meta_plugin_set_screen (plugin, screen);
|
||||
|
||||
klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
@@ -165,8 +167,6 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
|
||||
retval = TRUE;
|
||||
meta_plugin_manager_kill_window_effects (plugin_mgr,
|
||||
actor);
|
||||
|
||||
_meta_plugin_effect_started (plugin);
|
||||
klass->minimize (plugin, actor);
|
||||
}
|
||||
break;
|
||||
@@ -176,8 +176,6 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
|
||||
retval = TRUE;
|
||||
meta_plugin_manager_kill_window_effects (plugin_mgr,
|
||||
actor);
|
||||
|
||||
_meta_plugin_effect_started (plugin);
|
||||
klass->map (plugin, actor);
|
||||
}
|
||||
break;
|
||||
@@ -185,7 +183,6 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
|
||||
if (klass->destroy)
|
||||
{
|
||||
retval = TRUE;
|
||||
_meta_plugin_effect_started (plugin);
|
||||
klass->destroy (plugin, actor);
|
||||
}
|
||||
break;
|
||||
@@ -230,8 +227,6 @@ meta_plugin_manager_event_maximize (MetaPluginManager *plugin_mgr,
|
||||
retval = TRUE;
|
||||
meta_plugin_manager_kill_window_effects (plugin_mgr,
|
||||
actor);
|
||||
|
||||
_meta_plugin_effect_started (plugin);
|
||||
klass->maximize (plugin, actor,
|
||||
target_x, target_y,
|
||||
target_width, target_height);
|
||||
@@ -243,8 +238,6 @@ meta_plugin_manager_event_maximize (MetaPluginManager *plugin_mgr,
|
||||
retval = TRUE;
|
||||
meta_plugin_manager_kill_window_effects (plugin_mgr,
|
||||
actor);
|
||||
|
||||
_meta_plugin_effect_started (plugin);
|
||||
klass->unmaximize (plugin, actor,
|
||||
target_x, target_y,
|
||||
target_width, target_height);
|
||||
@@ -283,8 +276,6 @@ meta_plugin_manager_switch_workspace (MetaPluginManager *plugin_mgr,
|
||||
{
|
||||
retval = TRUE;
|
||||
meta_plugin_manager_kill_switch_workspace (plugin_mgr);
|
||||
|
||||
_meta_plugin_effect_started (plugin);
|
||||
klass->switch_workspace (plugin, from, to, direction);
|
||||
}
|
||||
|
||||
@@ -324,3 +315,44 @@ meta_plugin_manager_confirm_display_change (MetaPluginManager *plugin_mgr)
|
||||
else
|
||||
return meta_plugin_complete_display_change (plugin, TRUE);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_plugin_manager_show_tile_preview (MetaPluginManager *plugin_mgr,
|
||||
MetaWindow *window,
|
||||
MetaRectangle *tile_rect,
|
||||
int tile_monitor_number)
|
||||
{
|
||||
MetaPlugin *plugin = plugin_mgr->plugin;
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
|
||||
|
||||
if (display->display_opening)
|
||||
return FALSE;
|
||||
|
||||
if (klass->show_tile_preview)
|
||||
{
|
||||
klass->show_tile_preview (plugin, window, tile_rect, tile_monitor_number);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_plugin_manager_hide_tile_preview (MetaPluginManager *plugin_mgr)
|
||||
{
|
||||
MetaPlugin *plugin = plugin_mgr->plugin;
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
|
||||
|
||||
if (display->display_opening)
|
||||
return FALSE;
|
||||
|
||||
if (klass->hide_tile_preview)
|
||||
{
|
||||
klass->hide_tile_preview (plugin);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@@ -75,4 +75,9 @@ gboolean _meta_plugin_xevent_filter (MetaPlugin *plugin,
|
||||
|
||||
void meta_plugin_manager_confirm_display_change (MetaPluginManager *mgr);
|
||||
|
||||
gboolean meta_plugin_manager_show_tile_preview (MetaPluginManager *mgr,
|
||||
MetaWindow *window,
|
||||
MetaRectangle *tile_rect,
|
||||
int tile_monitor_number);
|
||||
gboolean meta_plugin_manager_hide_tile_preview (MetaPluginManager *mgr);
|
||||
#endif
|
||||
|
@@ -30,6 +30,7 @@
|
||||
#include "meta-plugin-manager.h"
|
||||
#include <meta/screen.h>
|
||||
#include <meta/display.h>
|
||||
#include <meta/util.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
@@ -46,91 +47,15 @@ G_DEFINE_ABSTRACT_TYPE (MetaPlugin, meta_plugin, G_TYPE_OBJECT);
|
||||
#define META_PLUGIN_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_PLUGIN, MetaPluginPrivate))
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_SCREEN,
|
||||
PROP_DEBUG_MODE,
|
||||
};
|
||||
|
||||
struct _MetaPluginPrivate
|
||||
{
|
||||
MetaScreen *screen;
|
||||
|
||||
gint running;
|
||||
gboolean debug : 1;
|
||||
MetaScreen *screen;
|
||||
};
|
||||
|
||||
static void
|
||||
meta_plugin_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (object)->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SCREEN:
|
||||
priv->screen = g_value_get_object (value);
|
||||
break;
|
||||
case PROP_DEBUG_MODE:
|
||||
priv->debug = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_plugin_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (object)->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SCREEN:
|
||||
g_value_set_object (value, priv->screen);
|
||||
break;
|
||||
case PROP_DEBUG_MODE:
|
||||
g_value_set_boolean (value, priv->debug);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
meta_plugin_class_init (MetaPluginClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->set_property = meta_plugin_set_property;
|
||||
gobject_class->get_property = meta_plugin_get_property;
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_SCREEN,
|
||||
g_param_spec_object ("screen",
|
||||
"MetaScreen",
|
||||
"MetaScreen",
|
||||
META_TYPE_SCREEN,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_DEBUG_MODE,
|
||||
g_param_spec_boolean ("debug-mode",
|
||||
"Debug Mode",
|
||||
"Debug Mode",
|
||||
FALSE,
|
||||
G_PARAM_READABLE));
|
||||
|
||||
g_type_class_add_private (gobject_class, sizeof (MetaPluginPrivate));
|
||||
g_type_class_add_private (klass, sizeof (MetaPluginPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -139,22 +64,6 @@ meta_plugin_init (MetaPlugin *self)
|
||||
self->priv = META_PLUGIN_GET_PRIVATE (self);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_plugin_running (MetaPlugin *plugin)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
return (priv->running > 0);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_plugin_debug_mode (MetaPlugin *plugin)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
return priv->debug;
|
||||
}
|
||||
|
||||
const MetaPluginInfo *
|
||||
meta_plugin_get_info (MetaPlugin *plugin)
|
||||
{
|
||||
@@ -166,21 +75,6 @@ meta_plugin_get_info (MetaPlugin *plugin)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* _meta_plugin_effect_started:
|
||||
* @plugin: the plugin
|
||||
*
|
||||
* Mark that an effect has started for the plugin. This is called
|
||||
* internally by MetaPluginManager.
|
||||
*/
|
||||
void
|
||||
_meta_plugin_effect_started (MetaPlugin *plugin)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
priv->running++;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_meta_plugin_xevent_filter (MetaPlugin *plugin,
|
||||
XEvent *xev)
|
||||
@@ -207,15 +101,8 @@ void
|
||||
meta_plugin_switch_workspace_completed (MetaPlugin *plugin)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
MetaScreen *screen = priv->screen;
|
||||
|
||||
if (priv->running-- < 0)
|
||||
{
|
||||
g_warning ("Error in running effect accounting, adjusting.");
|
||||
priv->running = 0;
|
||||
}
|
||||
|
||||
meta_switch_workspace_completed (screen);
|
||||
}
|
||||
|
||||
@@ -224,26 +111,6 @@ meta_plugin_window_effect_completed (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor,
|
||||
unsigned long event)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
if (priv->running-- < 0)
|
||||
{
|
||||
g_warning ("Error in running effect accounting, adjusting.");
|
||||
priv->running = 0;
|
||||
}
|
||||
|
||||
if (!actor)
|
||||
{
|
||||
const MetaPluginInfo *info;
|
||||
const gchar *name = NULL;
|
||||
|
||||
if (plugin && (info = meta_plugin_get_info (plugin)))
|
||||
name = info->name;
|
||||
|
||||
g_warning ("Plugin [%s] passed NULL for actor!",
|
||||
name ? name : "unknown");
|
||||
}
|
||||
|
||||
meta_window_actor_effect_completed (actor, event);
|
||||
}
|
||||
|
||||
@@ -338,9 +205,7 @@ meta_plugin_end_modal (MetaPlugin *plugin,
|
||||
* meta_plugin_get_screen:
|
||||
* @plugin: a #MetaPlugin
|
||||
*
|
||||
* Gets the #MetaScreen corresponding to a plugin. Each plugin instance
|
||||
* is associated with exactly one screen; if Metacity is managing
|
||||
* multiple screens, multiple plugin instances will be created.
|
||||
* Gets the #MetaScreen corresponding to a plugin.
|
||||
*
|
||||
* Return value: (transfer none): the #MetaScreen for the plugin
|
||||
*/
|
||||
@@ -352,6 +217,15 @@ meta_plugin_get_screen (MetaPlugin *plugin)
|
||||
return priv->screen;
|
||||
}
|
||||
|
||||
void
|
||||
_meta_plugin_set_screen (MetaPlugin *plugin,
|
||||
MetaScreen *screen)
|
||||
{
|
||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||
|
||||
priv->screen = screen;
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_complete_display_change (MetaPlugin *plugin,
|
||||
gboolean ok)
|
||||
|
@@ -32,5 +32,8 @@
|
||||
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
|
||||
|
@@ -33,6 +33,7 @@
|
||||
#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>
|
||||
@@ -42,8 +43,6 @@
|
||||
static void meta_shaped_texture_dispose (GObject *object);
|
||||
|
||||
static void meta_shaped_texture_paint (ClutterActor *actor);
|
||||
static void meta_shaped_texture_pick (ClutterActor *actor,
|
||||
const ClutterColor *color);
|
||||
|
||||
static void meta_shaped_texture_get_preferred_width (ClutterActor *self,
|
||||
gfloat for_height,
|
||||
@@ -73,10 +72,13 @@ struct _MetaShapedTexturePrivate
|
||||
CoglTexture *texture;
|
||||
CoglTexture *mask_texture;
|
||||
|
||||
cairo_region_t *clip_region;
|
||||
cairo_region_t *input_shape_region;
|
||||
/* The region containing only fully opaque pixels */
|
||||
cairo_region_t *opaque_region;
|
||||
|
||||
/* MetaCullable regions, see that documentation for more details */
|
||||
cairo_region_t *clip_region;
|
||||
cairo_region_t *unobscured_region;
|
||||
|
||||
guint tex_width, tex_height;
|
||||
|
||||
guint create_mipmaps : 1;
|
||||
@@ -93,7 +95,6 @@ meta_shaped_texture_class_init (MetaShapedTextureClass *klass)
|
||||
actor_class->get_preferred_width = meta_shaped_texture_get_preferred_width;
|
||||
actor_class->get_preferred_height = meta_shaped_texture_get_preferred_height;
|
||||
actor_class->paint = meta_shaped_texture_paint;
|
||||
actor_class->pick = meta_shaped_texture_pick;
|
||||
actor_class->get_paint_volume = meta_shaped_texture_get_paint_volume;
|
||||
|
||||
g_type_class_add_private (klass, sizeof (MetaShapedTexturePrivate));
|
||||
@@ -113,6 +114,21 @@ meta_shaped_texture_init (MetaShapedTexture *self)
|
||||
priv->create_mipmaps = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
set_unobscured_region (MetaShapedTexture *self,
|
||||
cairo_region_t *unobscured_region)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv = self->priv;
|
||||
|
||||
g_clear_pointer (&priv->unobscured_region, (GDestroyNotify) cairo_region_destroy);
|
||||
if (unobscured_region)
|
||||
{
|
||||
cairo_rectangle_int_t bounds = { 0, 0, priv->tex_width, priv->tex_height };
|
||||
priv->unobscured_region = cairo_region_copy (unobscured_region);
|
||||
cairo_region_intersect_rectangle (priv->unobscured_region, &bounds);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_clip_region (MetaShapedTexture *self,
|
||||
cairo_region_t *clip_region)
|
||||
@@ -138,6 +154,7 @@ meta_shaped_texture_dispose (GObject *object)
|
||||
g_clear_pointer (&priv->opaque_region, cairo_region_destroy);
|
||||
|
||||
meta_shaped_texture_set_mask_texture (self, NULL);
|
||||
set_unobscured_region (self, NULL);
|
||||
set_clip_region (self, NULL);
|
||||
|
||||
G_OBJECT_CLASS (meta_shaped_texture_parent_class)->dispose (object);
|
||||
@@ -442,71 +459,6 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
||||
cairo_region_destroy (blended_region);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_pick (ClutterActor *actor,
|
||||
const ClutterColor *color)
|
||||
{
|
||||
MetaShapedTexture *stex = (MetaShapedTexture *) actor;
|
||||
MetaShapedTexturePrivate *priv = stex->priv;
|
||||
|
||||
if (!clutter_actor_should_pick_paint (actor) ||
|
||||
(priv->clip_region && cairo_region_is_empty (priv->clip_region)))
|
||||
return;
|
||||
|
||||
/* If there is no region then use the regular pick */
|
||||
if (priv->input_shape_region == NULL)
|
||||
CLUTTER_ACTOR_CLASS (meta_shaped_texture_parent_class)->pick (actor, color);
|
||||
else
|
||||
{
|
||||
int n_rects;
|
||||
float *rectangles;
|
||||
int i;
|
||||
CoglPipeline *pipeline;
|
||||
CoglContext *ctx;
|
||||
CoglFramebuffer *fb;
|
||||
CoglColor cogl_color;
|
||||
|
||||
/* Note: We don't bother trying to intersect the pick and clip regions
|
||||
* since needing to copy the region, do the intersection, and probably
|
||||
* increase the number of rectangles seems more likely to have a negative
|
||||
* effect.
|
||||
*
|
||||
* NB: Most of the time when just using rectangles for picking then
|
||||
* picking shouldn't involve any rendering, and minimizing the number of
|
||||
* rectangles has more benefit than reducing the area of the pick
|
||||
* region.
|
||||
*/
|
||||
|
||||
n_rects = cairo_region_num_rectangles (priv->input_shape_region);
|
||||
rectangles = g_alloca (sizeof (float) * 4 * n_rects);
|
||||
|
||||
for (i = 0; i < n_rects; i++)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
int pos = i * 4;
|
||||
|
||||
cairo_region_get_rectangle (priv->input_shape_region, i, &rect);
|
||||
|
||||
rectangles[pos] = rect.x;
|
||||
rectangles[pos + 1] = rect.y;
|
||||
rectangles[pos + 2] = rect.x + rect.width;
|
||||
rectangles[pos + 3] = rect.y + rect.height;
|
||||
}
|
||||
|
||||
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
fb = cogl_get_draw_framebuffer ();
|
||||
|
||||
cogl_color_init_from_4ub (&cogl_color, color->red, color->green, color->blue, color->alpha);
|
||||
|
||||
pipeline = cogl_pipeline_new (ctx);
|
||||
cogl_pipeline_set_color (pipeline, &cogl_color);
|
||||
|
||||
cogl_framebuffer_draw_rectangles (fb, pipeline,
|
||||
rectangles, n_rects);
|
||||
cogl_object_unref (pipeline);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_get_preferred_width (ClutterActor *self,
|
||||
gfloat for_height,
|
||||
@@ -546,10 +498,37 @@ meta_shaped_texture_get_preferred_height (ClutterActor *self,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_shaped_texture_get_paint_volume (ClutterActor *self,
|
||||
meta_shaped_texture_get_paint_volume (ClutterActor *actor,
|
||||
ClutterPaintVolume *volume)
|
||||
{
|
||||
return clutter_paint_volume_set_from_allocation (volume, self);
|
||||
MetaShapedTexture *self = META_SHAPED_TEXTURE (actor);
|
||||
cairo_rectangle_int_t unobscured_bounds;
|
||||
|
||||
if (!clutter_paint_volume_set_from_allocation (volume, actor))
|
||||
return FALSE;
|
||||
|
||||
if (meta_shaped_texture_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);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -594,50 +573,48 @@ meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex,
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
get_clip (MetaShapedTexture *stex,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
cairo_rectangle_int_t *clip)
|
||||
static cairo_region_t *
|
||||
effective_unobscured_region (MetaShapedTexture *self)
|
||||
{
|
||||
ClutterActor *self = CLUTTER_ACTOR (stex);
|
||||
MetaShapedTexturePrivate *priv;
|
||||
ClutterActorBox allocation;
|
||||
double scale_x;
|
||||
double scale_y;
|
||||
MetaShapedTexturePrivate *priv = self->priv;
|
||||
ClutterActor *parent = clutter_actor_get_parent (CLUTTER_ACTOR (self));
|
||||
|
||||
/* NB: clutter_actor_queue_redraw_with_clip expects a box in the actor's
|
||||
* coordinate space so we need to convert from surface coordinates to
|
||||
* actor coordinates...
|
||||
*/
|
||||
if (clutter_actor_has_mapped_clones (CLUTTER_ACTOR (self)))
|
||||
return NULL;
|
||||
|
||||
/* Calling clutter_actor_get_allocation_box() is enormously expensive
|
||||
* if the actor has an out-of-date allocation, since it triggers
|
||||
* a full redraw. clutter_actor_queue_redraw_with_clip() would redraw
|
||||
* the whole stage anyways in that case, so just go ahead and do
|
||||
* it here.
|
||||
*/
|
||||
if (!clutter_actor_has_allocation (self))
|
||||
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;
|
||||
}
|
||||
|
||||
priv = stex->priv;
|
||||
gboolean
|
||||
meta_shaped_texture_is_obscured (MetaShapedTexture *self)
|
||||
{
|
||||
cairo_region_t *unobscured_region = effective_unobscured_region (self);
|
||||
|
||||
if (priv->tex_width == 0 || priv->tex_height == 0)
|
||||
if (unobscured_region)
|
||||
return cairo_region_is_empty (unobscured_region);
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
clutter_actor_get_allocation_box (self, &allocation);
|
||||
|
||||
scale_x = (allocation.x2 - allocation.x1) / priv->tex_width;
|
||||
scale_y = (allocation.y2 - allocation.y1) / priv->tex_height;
|
||||
|
||||
clip->x = x * scale_x;
|
||||
clip->y = y * scale_y;
|
||||
clip->width = width * scale_x;
|
||||
clip->height = height * scale_y;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -647,14 +624,9 @@ get_clip (MetaShapedTexture *stex,
|
||||
* @y: the y coordinate of the damaged area
|
||||
* @width: the width of the damaged area
|
||||
* @height: the height of the damaged area
|
||||
* @unobscured_region: The unobscured region of the window or %NULL if
|
||||
* there is no valid one (like when the actor is transformed or
|
||||
* has a mapped clone)
|
||||
*
|
||||
* Repairs the damaged area indicated by @x, @y, @width and @height
|
||||
* and queues a redraw for the intersection @unobscured_region and
|
||||
* the damage area. If @unobscured_region is %NULL a redraw will always
|
||||
* get queued.
|
||||
* and potentially queues a redraw.
|
||||
*
|
||||
* Return value: Whether a redraw have been queued or not
|
||||
*/
|
||||
@@ -663,12 +635,11 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
cairo_region_t *unobscured_region)
|
||||
int height)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv;
|
||||
cairo_rectangle_int_t clip;
|
||||
gboolean has_clip;
|
||||
cairo_region_t *unobscured_region;
|
||||
const cairo_rectangle_int_t clip = { x, y, width, height };
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
@@ -677,8 +648,7 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
|
||||
|
||||
meta_texture_tower_update_area (priv->paint_tower, x, y, width, height);
|
||||
|
||||
has_clip = get_clip (stex, x, y, width, height, &clip);
|
||||
|
||||
unobscured_region = effective_unobscured_region (stex);
|
||||
if (unobscured_region)
|
||||
{
|
||||
cairo_region_t *intersection;
|
||||
@@ -687,8 +657,7 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
|
||||
return FALSE;
|
||||
|
||||
intersection = cairo_region_copy (unobscured_region);
|
||||
if (has_clip)
|
||||
cairo_region_intersect_rectangle (intersection, &clip);
|
||||
cairo_region_intersect_rectangle (intersection, &clip);
|
||||
|
||||
if (!cairo_region_is_empty (intersection))
|
||||
{
|
||||
@@ -696,21 +665,17 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
|
||||
cairo_region_get_extents (intersection, &damage_rect);
|
||||
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &damage_rect);
|
||||
cairo_region_destroy (intersection);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
cairo_region_destroy (intersection);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (has_clip)
|
||||
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &clip);
|
||||
else
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
|
||||
|
||||
return TRUE;
|
||||
{
|
||||
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &clip);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -740,41 +705,6 @@ meta_shaped_texture_get_texture (MetaShapedTexture *stex)
|
||||
return COGL_TEXTURE (stex->priv->texture);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_shaped_texture_set_input_shape_region:
|
||||
* @stex: a #MetaShapedTexture
|
||||
* @shape_region: the region of the texture that should respond to
|
||||
* input.
|
||||
*
|
||||
* Determines what region of the texture should accept input. For
|
||||
* X based windows this is defined by the ShapeInput region of the
|
||||
* window.
|
||||
*/
|
||||
void
|
||||
meta_shaped_texture_set_input_shape_region (MetaShapedTexture *stex,
|
||||
cairo_region_t *shape_region)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv;
|
||||
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
if (priv->input_shape_region != NULL)
|
||||
{
|
||||
cairo_region_destroy (priv->input_shape_region);
|
||||
priv->input_shape_region = NULL;
|
||||
}
|
||||
|
||||
if (shape_region != NULL)
|
||||
{
|
||||
cairo_region_reference (shape_region);
|
||||
priv->input_shape_region = shape_region;
|
||||
}
|
||||
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_shaped_texture_set_opaque_region:
|
||||
* @stex: a #MetaShapedTexture
|
||||
@@ -911,14 +841,17 @@ meta_shaped_texture_cull_out (MetaCullable *cullable,
|
||||
MetaShapedTexture *self = META_SHAPED_TEXTURE (cullable);
|
||||
MetaShapedTexturePrivate *priv = self->priv;
|
||||
|
||||
set_unobscured_region (self, unobscured_region);
|
||||
set_clip_region (self, clip_region);
|
||||
|
||||
if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (self)) == 0xff)
|
||||
{
|
||||
if (priv->opaque_region)
|
||||
{
|
||||
cairo_region_subtract (unobscured_region, priv->opaque_region);
|
||||
cairo_region_subtract (clip_region, priv->opaque_region);
|
||||
if (unobscured_region)
|
||||
cairo_region_subtract (unobscured_region, priv->opaque_region);
|
||||
if (clip_region)
|
||||
cairo_region_subtract (clip_region, priv->opaque_region);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
203
src/compositor/meta-surface-actor-wayland.c
Normal file
203
src/compositor/meta-surface-actor-wayland.c
Normal file
@@ -0,0 +1,203 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "meta-surface-actor-wayland.h"
|
||||
|
||||
#include <cogl/cogl-wayland-server.h>
|
||||
#include "meta-shaped-texture-private.h"
|
||||
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
|
||||
struct _MetaSurfaceActorWaylandPrivate
|
||||
{
|
||||
MetaWaylandSurface *surface;
|
||||
MetaWaylandBuffer *buffer;
|
||||
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
|
||||
meta_surface_actor_wayland_pre_paint (MetaSurfaceActor *actor)
|
||||
{
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_surface_actor_wayland_is_argb32 (MetaSurfaceActor *actor)
|
||||
{
|
||||
MetaShapedTexture *stex = meta_surface_actor_get_texture (actor);
|
||||
CoglTexture *texture = meta_shaped_texture_get_texture (stex);
|
||||
|
||||
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 gboolean
|
||||
meta_surface_actor_wayland_is_visible (MetaSurfaceActor *actor)
|
||||
{
|
||||
/* TODO: ensure that the buffer isn't NULL, implement
|
||||
* wayland mapping semantics */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_surface_actor_wayland_should_unredirect (MetaSurfaceActor *actor)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_wayland_set_unredirected (MetaSurfaceActor *actor,
|
||||
gboolean unredirected)
|
||||
{
|
||||
/* Do nothing. In the future, we'll use KMS to set this
|
||||
* up as a hardware overlay or something. */
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_surface_actor_wayland_is_unredirected (MetaSurfaceActor *actor)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static MetaWindow *
|
||||
meta_surface_actor_wayland_get_window (MetaSurfaceActor *actor)
|
||||
{
|
||||
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (META_SURFACE_ACTOR_WAYLAND (actor));
|
||||
|
||||
return priv->surface->window;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass)
|
||||
{
|
||||
MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass);
|
||||
|
||||
surface_actor_class->process_damage = meta_surface_actor_wayland_process_damage;
|
||||
surface_actor_class->pre_paint = meta_surface_actor_wayland_pre_paint;
|
||||
surface_actor_class->is_argb32 = meta_surface_actor_wayland_is_argb32;
|
||||
surface_actor_class->is_visible = meta_surface_actor_wayland_is_visible;
|
||||
|
||||
surface_actor_class->should_unredirect = meta_surface_actor_wayland_should_unredirect;
|
||||
surface_actor_class->set_unredirected = meta_surface_actor_wayland_set_unredirected;
|
||||
surface_actor_class->is_unredirected = meta_surface_actor_wayland_is_unredirected;
|
||||
|
||||
surface_actor_class->get_window = meta_surface_actor_wayland_get_window;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_wayland_init (MetaSurfaceActorWayland *self)
|
||||
{
|
||||
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
|
||||
|
||||
priv->buffer_destroy_listener.notify = meta_surface_actor_handle_buffer_destroy;
|
||||
}
|
||||
|
||||
MetaSurfaceActor *
|
||||
meta_surface_actor_wayland_new (MetaWaylandSurface *surface)
|
||||
{
|
||||
MetaSurfaceActorWayland *self = g_object_new (META_TYPE_SURFACE_ACTOR_WAYLAND, NULL);
|
||||
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
|
||||
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
priv->surface = surface;
|
||||
|
||||
return META_SURFACE_ACTOR (self);
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self,
|
||||
MetaWaylandBuffer *buffer)
|
||||
{
|
||||
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
|
||||
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
MetaWaylandSurface *
|
||||
meta_surface_actor_wayland_get_surface (MetaSurfaceActorWayland *self)
|
||||
{
|
||||
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
|
||||
return priv->surface;
|
||||
}
|
66
src/compositor/meta-surface-actor-wayland.h
Normal file
66
src/compositor/meta-surface-actor-wayland.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#ifndef __META_SURFACE_ACTOR_WAYLAND_H__
|
||||
#define __META_SURFACE_ACTOR_WAYLAND_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "meta-surface-actor.h"
|
||||
|
||||
#include "wayland/meta-wayland.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define META_TYPE_SURFACE_ACTOR_WAYLAND (meta_surface_actor_wayland_get_type ())
|
||||
#define META_SURFACE_ACTOR_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWayland))
|
||||
#define META_SURFACE_ACTOR_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWaylandClass))
|
||||
#define META_IS_SURFACE_ACTOR_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SURFACE_ACTOR_WAYLAND))
|
||||
#define META_IS_SURFACE_ACTOR_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_SURFACE_ACTOR_WAYLAND))
|
||||
#define META_SURFACE_ACTOR_WAYLAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWaylandClass))
|
||||
|
||||
typedef struct _MetaSurfaceActorWayland MetaSurfaceActorWayland;
|
||||
typedef struct _MetaSurfaceActorWaylandClass MetaSurfaceActorWaylandClass;
|
||||
|
||||
struct _MetaSurfaceActorWayland
|
||||
{
|
||||
MetaSurfaceActor parent;
|
||||
};
|
||||
|
||||
struct _MetaSurfaceActorWaylandClass
|
||||
{
|
||||
MetaSurfaceActorClass parent_class;
|
||||
};
|
||||
|
||||
GType meta_surface_actor_wayland_get_type (void);
|
||||
|
||||
MetaSurfaceActor * meta_surface_actor_wayland_new (MetaWaylandSurface *surface);
|
||||
MetaWaylandSurface * meta_surface_actor_wayland_get_surface (MetaSurfaceActorWayland *self);
|
||||
|
||||
void meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self,
|
||||
MetaWaylandBuffer *buffer);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __META_SURFACE_ACTOR_WAYLAND_H__ */
|
486
src/compositor/meta-surface-actor-x11.c
Normal file
486
src/compositor/meta-surface-actor-x11.c
Normal file
@@ -0,0 +1,486 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Owen Taylor <otaylor@redhat.com>
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "meta-surface-actor-x11.h"
|
||||
|
||||
#include <X11/extensions/Xcomposite.h>
|
||||
#include <X11/extensions/Xrender.h>
|
||||
#include <cogl/cogl-texture-pixmap-x11.h>
|
||||
|
||||
#include <meta/errors.h>
|
||||
#include "window-private.h"
|
||||
#include "meta-shaped-texture-private.h"
|
||||
#include "meta-cullable.h"
|
||||
|
||||
struct _MetaSurfaceActorX11Private
|
||||
{
|
||||
MetaWindow *window;
|
||||
|
||||
MetaDisplay *display;
|
||||
|
||||
CoglTexture *texture;
|
||||
Pixmap pixmap;
|
||||
Damage damage;
|
||||
|
||||
int last_width;
|
||||
int last_height;
|
||||
|
||||
/* This is used to detect fullscreen windows that need to be unredirected */
|
||||
guint full_damage_frames_count;
|
||||
guint does_full_damage : 1;
|
||||
|
||||
/* Other state... */
|
||||
guint argb32 : 1;
|
||||
guint received_damage : 1;
|
||||
guint size_changed : 1;
|
||||
|
||||
guint unredirected : 1;
|
||||
};
|
||||
typedef struct _MetaSurfaceActorX11Private MetaSurfaceActorX11Private;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaSurfaceActorX11, meta_surface_actor_x11, META_TYPE_SURFACE_ACTOR)
|
||||
|
||||
static void
|
||||
free_damage (MetaSurfaceActorX11 *self)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
MetaDisplay *display = priv->display;
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
|
||||
if (priv->damage == None)
|
||||
return;
|
||||
|
||||
meta_error_trap_push (display);
|
||||
XDamageDestroy (xdisplay, priv->damage);
|
||||
priv->damage = None;
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
|
||||
static void
|
||||
detach_pixmap (MetaSurfaceActorX11 *self)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
MetaDisplay *display = priv->display;
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
|
||||
|
||||
if (priv->pixmap == None)
|
||||
return;
|
||||
|
||||
/* Get rid of all references to the pixmap before freeing it; it's unclear whether
|
||||
* you are supposed to be able to free a GLXPixmap after freeing the underlying
|
||||
* pixmap, but it certainly doesn't work with current DRI/Mesa
|
||||
*/
|
||||
meta_shaped_texture_set_texture (stex, NULL);
|
||||
cogl_flush ();
|
||||
|
||||
meta_error_trap_push (display);
|
||||
XFreePixmap (xdisplay, priv->pixmap);
|
||||
priv->pixmap = None;
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
cogl_object_unref (priv->texture);
|
||||
priv->texture = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
set_pixmap (MetaSurfaceActorX11 *self,
|
||||
Pixmap pixmap)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
|
||||
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
|
||||
CoglTexture *texture;
|
||||
|
||||
g_assert (priv->pixmap == None);
|
||||
priv->pixmap = pixmap;
|
||||
|
||||
texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (ctx, priv->pixmap, FALSE, NULL));
|
||||
|
||||
if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (COGL_TEXTURE_PIXMAP_X11 (texture))))
|
||||
g_warning ("NOTE: Not using GLX TFP!\n");
|
||||
|
||||
priv->texture = texture;
|
||||
meta_shaped_texture_set_texture (stex, texture);
|
||||
}
|
||||
|
||||
static void
|
||||
update_pixmap (MetaSurfaceActorX11 *self)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
MetaDisplay *display = priv->display;
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
|
||||
if (priv->size_changed)
|
||||
{
|
||||
detach_pixmap (self);
|
||||
priv->size_changed = FALSE;
|
||||
}
|
||||
|
||||
if (priv->pixmap == None)
|
||||
{
|
||||
Pixmap new_pixmap;
|
||||
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
|
||||
|
||||
meta_error_trap_push (display);
|
||||
new_pixmap = XCompositeNameWindowPixmap (xdisplay, xwindow);
|
||||
|
||||
if (meta_error_trap_pop_with_return (display) != Success)
|
||||
{
|
||||
/* Probably a BadMatch if the window isn't viewable; we could
|
||||
* GrabServer/GetWindowAttributes/NameWindowPixmap/UngrabServer/Sync
|
||||
* to avoid this, but there's no reason to take two round trips
|
||||
* when one will do. (We need that Sync if we want to handle failures
|
||||
* for any reason other than !viewable. That's unlikely, but maybe
|
||||
* we'll BadAlloc or something.)
|
||||
*/
|
||||
new_pixmap = None;
|
||||
}
|
||||
|
||||
if (new_pixmap == None)
|
||||
{
|
||||
meta_verbose ("Unable to get named pixmap for %s\n",
|
||||
meta_window_get_description (priv->window));
|
||||
return;
|
||||
}
|
||||
|
||||
set_pixmap (self, new_pixmap);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_visible (MetaSurfaceActorX11 *self)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
return (priv->pixmap != None) && !priv->unredirected;
|
||||
}
|
||||
|
||||
static void
|
||||
damage_area (MetaSurfaceActorX11 *self,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
|
||||
if (!is_visible (self))
|
||||
return;
|
||||
|
||||
cogl_texture_pixmap_x11_update_area (priv->texture, x, y, width, height);
|
||||
meta_surface_actor_update_area (META_SURFACE_ACTOR (self), x, y, width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_x11_process_damage (MetaSurfaceActor *actor,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
|
||||
priv->received_damage = TRUE;
|
||||
|
||||
if (meta_window_is_fullscreen (priv->window) && !priv->unredirected && !priv->does_full_damage)
|
||||
{
|
||||
MetaRectangle window_rect;
|
||||
meta_window_get_frame_rect (priv->window, &window_rect);
|
||||
|
||||
if (window_rect.x == x &&
|
||||
window_rect.y == y &&
|
||||
window_rect.width == width &&
|
||||
window_rect.height == height)
|
||||
priv->full_damage_frames_count++;
|
||||
else
|
||||
priv->full_damage_frames_count = 0;
|
||||
|
||||
if (priv->full_damage_frames_count >= 100)
|
||||
priv->does_full_damage = TRUE;
|
||||
}
|
||||
|
||||
/* Drop damage event for unredirected windows */
|
||||
if (priv->unredirected)
|
||||
return;
|
||||
|
||||
damage_area (self, x, y, width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_x11_pre_paint (MetaSurfaceActor *actor)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
MetaDisplay *display = priv->display;
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
|
||||
if (priv->received_damage)
|
||||
{
|
||||
meta_error_trap_push (display);
|
||||
XDamageSubtract (xdisplay, priv->damage, None, None);
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
/* We need to make sure that any X drawing that happens before the
|
||||
* XDamageSubtract() above is visible to subsequent GL rendering;
|
||||
* the only standardized way to do this is EXT_x11_sync_object,
|
||||
* which isn't yet widely available. For now, we count on details
|
||||
* of Xorg and the open source drivers, and hope for the best
|
||||
* otherwise.
|
||||
*
|
||||
* Xorg and open source driver specifics:
|
||||
*
|
||||
* The X server makes sure to flush drawing to the kernel before
|
||||
* sending out damage events, but since we use DamageReportBoundingBox
|
||||
* there may be drawing between the last damage event and the
|
||||
* XDamageSubtract() that needs to be flushed as well.
|
||||
*
|
||||
* Xorg always makes sure that drawing is flushed to the kernel
|
||||
* before writing events or responses to the client, so any round trip
|
||||
* request at this point is sufficient to flush the GLX buffers.
|
||||
*/
|
||||
XSync (xdisplay, False);
|
||||
|
||||
priv->received_damage = FALSE;
|
||||
}
|
||||
|
||||
update_pixmap (self);
|
||||
}
|
||||
|
||||
static void
|
||||
update_is_argb32 (MetaSurfaceActorX11 *self)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
MetaDisplay *display = priv->display;
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
|
||||
XRenderPictFormat *format;
|
||||
format = XRenderFindVisualFormat (xdisplay, priv->window->xvisual);
|
||||
|
||||
priv->argb32 = (format && format->type == PictTypeDirect && format->direct.alphaMask);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_surface_actor_x11_is_argb32 (MetaSurfaceActor *actor)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
|
||||
return priv->argb32;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_surface_actor_x11_is_visible (MetaSurfaceActor *actor)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
|
||||
return is_visible (self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_surface_actor_x11_should_unredirect (MetaSurfaceActor *actor)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
|
||||
MetaWindow *window = priv->window;
|
||||
|
||||
if (meta_window_requested_dont_bypass_compositor (window))
|
||||
return FALSE;
|
||||
|
||||
if (window->opacity != 0xFF)
|
||||
return FALSE;
|
||||
|
||||
if (window->shape_region != NULL)
|
||||
return FALSE;
|
||||
|
||||
if (priv->argb32 && !meta_window_requested_bypass_compositor (window))
|
||||
return FALSE;
|
||||
|
||||
if (!meta_window_is_monitor_sized (window))
|
||||
return FALSE;
|
||||
|
||||
if (meta_window_requested_bypass_compositor (window))
|
||||
return TRUE;
|
||||
|
||||
if (meta_window_is_override_redirect (window))
|
||||
return TRUE;
|
||||
|
||||
if (priv->does_full_damage)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
sync_unredirected (MetaSurfaceActorX11 *self)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
MetaDisplay *display = priv->display;
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
|
||||
|
||||
meta_error_trap_push (display);
|
||||
|
||||
if (priv->unredirected)
|
||||
{
|
||||
detach_pixmap (self);
|
||||
XCompositeUnredirectWindow (xdisplay, xwindow, CompositeRedirectManual);
|
||||
}
|
||||
else
|
||||
{
|
||||
XCompositeRedirectWindow (xdisplay, xwindow, CompositeRedirectManual);
|
||||
}
|
||||
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_x11_set_unredirected (MetaSurfaceActor *actor,
|
||||
gboolean unredirected)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
|
||||
if (priv->unredirected == unredirected)
|
||||
return;
|
||||
|
||||
priv->unredirected = unredirected;
|
||||
sync_unredirected (self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_surface_actor_x11_is_unredirected (MetaSurfaceActor *actor)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
|
||||
return priv->unredirected;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_x11_dispose (GObject *object)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (object);
|
||||
|
||||
detach_pixmap (self);
|
||||
free_damage (self);
|
||||
|
||||
G_OBJECT_CLASS (meta_surface_actor_x11_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static MetaWindow *
|
||||
meta_surface_actor_x11_get_window (MetaSurfaceActor *actor)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (META_SURFACE_ACTOR_X11 (actor));
|
||||
|
||||
return priv->window;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_x11_class_init (MetaSurfaceActorX11Class *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass);
|
||||
|
||||
object_class->dispose = meta_surface_actor_x11_dispose;
|
||||
|
||||
surface_actor_class->process_damage = meta_surface_actor_x11_process_damage;
|
||||
surface_actor_class->pre_paint = meta_surface_actor_x11_pre_paint;
|
||||
surface_actor_class->is_argb32 = meta_surface_actor_x11_is_argb32;
|
||||
surface_actor_class->is_visible = meta_surface_actor_x11_is_visible;
|
||||
|
||||
surface_actor_class->should_unredirect = meta_surface_actor_x11_should_unredirect;
|
||||
surface_actor_class->set_unredirected = meta_surface_actor_x11_set_unredirected;
|
||||
surface_actor_class->is_unredirected = meta_surface_actor_x11_is_unredirected;
|
||||
|
||||
surface_actor_class->get_window = meta_surface_actor_x11_get_window;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_x11_init (MetaSurfaceActorX11 *self)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
|
||||
priv->last_width = -1;
|
||||
priv->last_height = -1;
|
||||
}
|
||||
|
||||
static void
|
||||
create_damage (MetaSurfaceActorX11 *self)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
Display *xdisplay = meta_display_get_xdisplay (priv->display);
|
||||
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
|
||||
|
||||
priv->damage = XDamageCreate (xdisplay, xwindow, XDamageReportBoundingBox);
|
||||
}
|
||||
|
||||
static void
|
||||
window_decorated_notify (MetaWindow *window,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (user_data);
|
||||
|
||||
free_damage (self);
|
||||
create_damage (self);
|
||||
}
|
||||
|
||||
MetaSurfaceActor *
|
||||
meta_surface_actor_x11_new (MetaWindow *window)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = g_object_new (META_TYPE_SURFACE_ACTOR_X11, NULL);
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
MetaDisplay *display = meta_window_get_display (window);
|
||||
|
||||
g_assert (!meta_is_wayland_compositor ());
|
||||
|
||||
priv->window = window;
|
||||
priv->display = display;
|
||||
|
||||
create_damage (self);
|
||||
g_signal_connect_object (priv->window, "notify::decorated",
|
||||
G_CALLBACK (window_decorated_notify), self, 0);
|
||||
|
||||
update_is_argb32 (self);
|
||||
|
||||
priv->unredirected = FALSE;
|
||||
sync_unredirected (self);
|
||||
|
||||
clutter_actor_set_reactive (CLUTTER_ACTOR (self), TRUE);
|
||||
return META_SURFACE_ACTOR (self);
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self,
|
||||
int width, int height)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
|
||||
if (priv->last_width == width &&
|
||||
priv->last_height == height)
|
||||
return;
|
||||
|
||||
priv->size_changed = TRUE;
|
||||
priv->last_width = width;
|
||||
priv->last_height = height;
|
||||
}
|
69
src/compositor/meta-surface-actor-x11.h
Normal file
69
src/compositor/meta-surface-actor-x11.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Owen Taylor <otaylor@redhat.com>
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#ifndef __META_SURFACE_ACTOR_X11_H__
|
||||
#define __META_SURFACE_ACTOR_X11_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "meta-surface-actor.h"
|
||||
|
||||
#include <X11/extensions/Xdamage.h>
|
||||
|
||||
#include <meta/display.h>
|
||||
#include <meta/window.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define META_TYPE_SURFACE_ACTOR_X11 (meta_surface_actor_x11_get_type ())
|
||||
#define META_SURFACE_ACTOR_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11))
|
||||
#define META_SURFACE_ACTOR_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11Class))
|
||||
#define META_IS_SURFACE_ACTOR_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SURFACE_ACTOR_X11))
|
||||
#define META_IS_SURFACE_ACTOR_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_SURFACE_ACTOR_X11))
|
||||
#define META_SURFACE_ACTOR_X11_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11Class))
|
||||
|
||||
typedef struct _MetaSurfaceActorX11 MetaSurfaceActorX11;
|
||||
typedef struct _MetaSurfaceActorX11Class MetaSurfaceActorX11Class;
|
||||
|
||||
struct _MetaSurfaceActorX11
|
||||
{
|
||||
MetaSurfaceActor parent;
|
||||
};
|
||||
|
||||
struct _MetaSurfaceActorX11Class
|
||||
{
|
||||
MetaSurfaceActorClass parent_class;
|
||||
};
|
||||
|
||||
GType meta_surface_actor_x11_get_type (void);
|
||||
|
||||
MetaSurfaceActor * meta_surface_actor_x11_new (MetaWindow *window);
|
||||
|
||||
void meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self,
|
||||
int width, int height);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __META_SURFACE_ACTOR_X11_H__ */
|
@@ -10,30 +10,124 @@
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <clutter/clutter.h>
|
||||
#include <cogl/cogl-wayland-server.h>
|
||||
#include <cogl/cogl-texture-pixmap-x11.h>
|
||||
#include <meta/meta-shaped-texture.h>
|
||||
#include "meta-surface-actor.h"
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-cullable.h"
|
||||
|
||||
#include "meta-surface-actor.h"
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <meta/meta-shaped-texture.h>
|
||||
#include "meta-cullable.h"
|
||||
#include "meta-shaped-texture-private.h"
|
||||
|
||||
struct _MetaSurfaceActorPrivate
|
||||
{
|
||||
MetaShapedTexture *texture;
|
||||
MetaWaylandBuffer *buffer;
|
||||
|
||||
cairo_region_t *input_region;
|
||||
|
||||
/* Freeze/thaw accounting */
|
||||
guint needs_damage_all : 1;
|
||||
guint frozen : 1;
|
||||
};
|
||||
|
||||
static void cullable_iface_init (MetaCullableInterface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (MetaSurfaceActor, meta_surface_actor, CLUTTER_TYPE_ACTOR,
|
||||
G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaSurfaceActor, meta_surface_actor, CLUTTER_TYPE_ACTOR,
|
||||
G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
|
||||
|
||||
enum {
|
||||
REPAINT_SCHEDULED,
|
||||
|
||||
LAST_SIGNAL,
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL];
|
||||
|
||||
gboolean
|
||||
meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor *self,
|
||||
cairo_rectangle_int_t *unobscured_bounds)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
return meta_shaped_texture_get_unobscured_bounds (priv->texture, unobscured_bounds);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_pick (ClutterActor *actor,
|
||||
const ClutterColor *color)
|
||||
{
|
||||
MetaSurfaceActor *self = META_SURFACE_ACTOR (actor);
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
|
||||
if (!clutter_actor_should_pick_paint (actor))
|
||||
return;
|
||||
|
||||
/* If there is no region then use the regular pick */
|
||||
if (priv->input_region == NULL)
|
||||
CLUTTER_ACTOR_CLASS (meta_surface_actor_parent_class)->pick (actor, color);
|
||||
else
|
||||
{
|
||||
int n_rects;
|
||||
float *rectangles;
|
||||
int i;
|
||||
CoglPipeline *pipeline;
|
||||
CoglContext *ctx;
|
||||
CoglFramebuffer *fb;
|
||||
CoglColor cogl_color;
|
||||
|
||||
n_rects = cairo_region_num_rectangles (priv->input_region);
|
||||
rectangles = g_alloca (sizeof (float) * 4 * n_rects);
|
||||
|
||||
for (i = 0; i < n_rects; i++)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
int pos = i * 4;
|
||||
|
||||
cairo_region_get_rectangle (priv->input_region, i, &rect);
|
||||
|
||||
rectangles[pos + 0] = rect.x;
|
||||
rectangles[pos + 1] = rect.y;
|
||||
rectangles[pos + 2] = rect.x + rect.width;
|
||||
rectangles[pos + 3] = rect.y + rect.height;
|
||||
}
|
||||
|
||||
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
fb = cogl_get_draw_framebuffer ();
|
||||
|
||||
cogl_color_init_from_4ub (&cogl_color, color->red, color->green, color->blue, color->alpha);
|
||||
|
||||
pipeline = cogl_pipeline_new (ctx);
|
||||
cogl_pipeline_set_color (pipeline, &cogl_color);
|
||||
cogl_framebuffer_draw_rectangles (fb, pipeline, rectangles, n_rects);
|
||||
cogl_object_unref (pipeline);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_dispose (GObject *object)
|
||||
{
|
||||
MetaSurfaceActor *self = META_SURFACE_ACTOR (object);
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
|
||||
g_clear_pointer (&priv->input_region, cairo_region_destroy);
|
||||
|
||||
G_OBJECT_CLASS (meta_surface_actor_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_class_init (MetaSurfaceActorClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
|
||||
object_class->dispose = meta_surface_actor_dispose;
|
||||
actor_class->pick = meta_surface_actor_pick;
|
||||
|
||||
signals[REPAINT_SCHEDULED] = g_signal_new ("repaint-scheduled",
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
g_type_class_add_private (klass, sizeof (MetaSurfaceActorPrivate));
|
||||
}
|
||||
|
||||
@@ -84,80 +178,21 @@ meta_surface_actor_get_texture (MetaSurfaceActor *self)
|
||||
return self->priv->texture;
|
||||
}
|
||||
|
||||
static void
|
||||
update_area (MetaSurfaceActor *self,
|
||||
int x, int y, int width, int height)
|
||||
void
|
||||
meta_surface_actor_update_area (MetaSurfaceActor *self,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CoglTexturePixmapX11 *texture = COGL_TEXTURE_PIXMAP_X11 (meta_shaped_texture_get_texture (priv->texture));
|
||||
cogl_texture_pixmap_x11_update_area (texture, x, y, width, height);
|
||||
}
|
||||
if (meta_shaped_texture_update_area (priv->texture, x, y, width, height))
|
||||
g_signal_emit (self, signals[REPAINT_SCHEDULED], 0);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_surface_actor_damage_all (MetaSurfaceActor *self,
|
||||
cairo_region_t *unobscured_region)
|
||||
meta_surface_actor_is_obscured (MetaSurfaceActor *self)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
CoglTexture *texture = meta_shaped_texture_get_texture (priv->texture);
|
||||
|
||||
update_area (self, 0, 0, cogl_texture_get_width (texture), cogl_texture_get_height (texture));
|
||||
return meta_shaped_texture_update_area (priv->texture,
|
||||
0, 0,
|
||||
cogl_texture_get_width (texture),
|
||||
cogl_texture_get_height (texture),
|
||||
unobscured_region);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_surface_actor_damage_area (MetaSurfaceActor *self,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
cairo_region_t *unobscured_region)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
|
||||
update_area (self, x, y, width, height);
|
||||
return meta_shaped_texture_update_area (priv->texture,
|
||||
x, y, width, height,
|
||||
unobscured_region);
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_attach_wayland_buffer (MetaSurfaceActor *self,
|
||||
MetaWaylandBuffer *buffer)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
priv->buffer = buffer;
|
||||
|
||||
if (buffer)
|
||||
meta_shaped_texture_set_texture (priv->texture, buffer->texture);
|
||||
else
|
||||
meta_shaped_texture_set_texture (priv->texture, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_set_texture (MetaSurfaceActor *self,
|
||||
CoglTexture *texture)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
meta_shaped_texture_set_texture (priv->texture, texture);
|
||||
return meta_shaped_texture_is_obscured (priv->texture);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -165,7 +200,14 @@ meta_surface_actor_set_input_region (MetaSurfaceActor *self,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
meta_shaped_texture_set_input_shape_region (priv->texture, region);
|
||||
|
||||
if (priv->input_region)
|
||||
cairo_region_destroy (priv->input_region);
|
||||
|
||||
if (region)
|
||||
priv->input_region = cairo_region_reference (region);
|
||||
else
|
||||
priv->input_region = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -176,8 +218,102 @@ meta_surface_actor_set_opaque_region (MetaSurfaceActor *self,
|
||||
meta_shaped_texture_set_opaque_region (priv->texture, region);
|
||||
}
|
||||
|
||||
MetaSurfaceActor *
|
||||
meta_surface_actor_new (void)
|
||||
static gboolean
|
||||
is_frozen (MetaSurfaceActor *self)
|
||||
{
|
||||
return g_object_new (META_TYPE_SURFACE_ACTOR, NULL);
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
return priv->frozen;
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_process_damage (MetaSurfaceActor *self,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
|
||||
if (is_frozen (self))
|
||||
{
|
||||
/* The window is frozen due to an effect in progress: we ignore damage
|
||||
* here on the off chance that this will stop the corresponding
|
||||
* texture_from_pixmap from being update.
|
||||
*
|
||||
* needs_damage_all tracks that some unknown damage happened while the
|
||||
* window was frozen so that when the window becomes unfrozen we can
|
||||
* issue a full window update to cover any lost damage.
|
||||
*
|
||||
* It should be noted that this is an unreliable mechanism since it's
|
||||
* quite likely that drivers will aim to provide a zero-copy
|
||||
* implementation of the texture_from_pixmap extension and in those cases
|
||||
* any drawing done to the window is always immediately reflected in the
|
||||
* texture regardless of damage event handling.
|
||||
*/
|
||||
priv->needs_damage_all = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
META_SURFACE_ACTOR_GET_CLASS (self)->process_damage (self, x, y, width, height);
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_pre_paint (MetaSurfaceActor *self)
|
||||
{
|
||||
META_SURFACE_ACTOR_GET_CLASS (self)->pre_paint (self);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_surface_actor_is_argb32 (MetaSurfaceActor *self)
|
||||
{
|
||||
return META_SURFACE_ACTOR_GET_CLASS (self)->is_argb32 (self);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_surface_actor_is_visible (MetaSurfaceActor *self)
|
||||
{
|
||||
return META_SURFACE_ACTOR_GET_CLASS (self)->is_visible (self);
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_set_frozen (MetaSurfaceActor *self,
|
||||
gboolean frozen)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
|
||||
priv->frozen = frozen;
|
||||
|
||||
if (!frozen && priv->needs_damage_all)
|
||||
{
|
||||
/* Since we ignore damage events while a window is frozen for certain effects
|
||||
* we may need to issue an update_area() covering the whole pixmap if we
|
||||
* don't know what real damage has happened. */
|
||||
|
||||
meta_surface_actor_process_damage (self, 0, 0,
|
||||
clutter_actor_get_width (CLUTTER_ACTOR (priv->texture)),
|
||||
clutter_actor_get_height (CLUTTER_ACTOR (priv->texture)));
|
||||
priv->needs_damage_all = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_surface_actor_should_unredirect (MetaSurfaceActor *self)
|
||||
{
|
||||
return META_SURFACE_ACTOR_GET_CLASS (self)->should_unredirect (self);
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_set_unredirected (MetaSurfaceActor *self,
|
||||
gboolean unredirected)
|
||||
{
|
||||
META_SURFACE_ACTOR_GET_CLASS (self)->set_unredirected (self, unredirected);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_surface_actor_is_unredirected (MetaSurfaceActor *self)
|
||||
{
|
||||
return META_SURFACE_ACTOR_GET_CLASS (self)->is_unredirected (self);
|
||||
}
|
||||
|
||||
MetaWindow *
|
||||
meta_surface_actor_get_window (MetaSurfaceActor *self)
|
||||
{
|
||||
return META_SURFACE_ACTOR_GET_CLASS (self)->get_window (self);
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@
|
||||
#include <config.h>
|
||||
|
||||
#include <meta/meta-shaped-texture.h>
|
||||
#include "meta-wayland-types.h"
|
||||
#include <meta/window.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@@ -25,6 +25,19 @@ struct _MetaSurfaceActorClass
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterActorClass parent_class;
|
||||
|
||||
void (* process_damage) (MetaSurfaceActor *actor,
|
||||
int x, int y, int width, int height);
|
||||
void (* pre_paint) (MetaSurfaceActor *actor);
|
||||
gboolean (* is_argb32) (MetaSurfaceActor *actor);
|
||||
gboolean (* is_visible) (MetaSurfaceActor *actor);
|
||||
|
||||
gboolean (* should_unredirect) (MetaSurfaceActor *actor);
|
||||
void (* set_unredirected) (MetaSurfaceActor *actor,
|
||||
gboolean unredirected);
|
||||
gboolean (* is_unredirected) (MetaSurfaceActor *actor);
|
||||
|
||||
MetaWindow *(* get_window) (MetaSurfaceActor *actor);
|
||||
};
|
||||
|
||||
struct _MetaSurfaceActor
|
||||
@@ -36,32 +49,38 @@ struct _MetaSurfaceActor
|
||||
|
||||
GType meta_surface_actor_get_type (void);
|
||||
|
||||
MetaSurfaceActor *meta_surface_actor_new (void);
|
||||
|
||||
cairo_surface_t *meta_surface_actor_get_image (MetaSurfaceActor *self,
|
||||
cairo_rectangle_int_t *clip);
|
||||
|
||||
MetaShapedTexture *meta_surface_actor_get_texture (MetaSurfaceActor *self);
|
||||
MetaWindow *meta_surface_actor_get_window (MetaSurfaceActor *self);
|
||||
|
||||
gboolean meta_surface_actor_damage_all (MetaSurfaceActor *self,
|
||||
cairo_region_t *unobscured_region);
|
||||
gboolean meta_surface_actor_is_obscured (MetaSurfaceActor *self);
|
||||
gboolean meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor *self,
|
||||
cairo_rectangle_int_t *unobscured_bounds);
|
||||
|
||||
gboolean meta_surface_actor_damage_area (MetaSurfaceActor *self,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
cairo_region_t *unobscured_region);
|
||||
|
||||
void meta_surface_actor_set_texture (MetaSurfaceActor *self,
|
||||
CoglTexture *texture);
|
||||
void meta_surface_actor_attach_wayland_buffer (MetaSurfaceActor *self,
|
||||
MetaWaylandBuffer *buffer);
|
||||
void meta_surface_actor_set_input_region (MetaSurfaceActor *self,
|
||||
cairo_region_t *region);
|
||||
void meta_surface_actor_set_opaque_region (MetaSurfaceActor *self,
|
||||
cairo_region_t *region);
|
||||
|
||||
void meta_surface_actor_update_area (MetaSurfaceActor *actor,
|
||||
int x, int y, int width, int height);
|
||||
|
||||
void meta_surface_actor_process_damage (MetaSurfaceActor *actor,
|
||||
int x, int y, int width, int height);
|
||||
void meta_surface_actor_pre_paint (MetaSurfaceActor *actor);
|
||||
gboolean meta_surface_actor_is_argb32 (MetaSurfaceActor *actor);
|
||||
gboolean meta_surface_actor_is_visible (MetaSurfaceActor *actor);
|
||||
|
||||
void meta_surface_actor_set_frozen (MetaSurfaceActor *actor,
|
||||
gboolean frozen);
|
||||
|
||||
gboolean meta_surface_actor_should_unredirect (MetaSurfaceActor *actor);
|
||||
void meta_surface_actor_set_unredirected (MetaSurfaceActor *actor,
|
||||
gboolean unredirected);
|
||||
gboolean meta_surface_actor_is_unredirected (MetaSurfaceActor *actor);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* META_SURFACE_ACTOR_PRIVATE_H */
|
||||
|
@@ -5,9 +5,6 @@
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <wayland-server.h>
|
||||
#include <meta-wayland-private.h>
|
||||
|
||||
#include <X11/extensions/Xdamage.h>
|
||||
#include <meta/compositor-mutter.h>
|
||||
#include "meta-surface-actor.h"
|
||||
@@ -59,12 +56,10 @@ void meta_window_actor_set_updates_frozen (MetaWindowActor *self,
|
||||
void meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
|
||||
gboolean no_delay_frame);
|
||||
|
||||
void meta_window_actor_set_unobscured_region (MetaWindowActor *self,
|
||||
cairo_region_t *unobscured_region);
|
||||
|
||||
void meta_window_actor_effect_completed (MetaWindowActor *actor,
|
||||
gulong event);
|
||||
|
||||
MetaSurfaceActor *meta_window_actor_get_surface (MetaWindowActor *self);
|
||||
void meta_window_actor_update_surface (MetaWindowActor *self);
|
||||
|
||||
#endif /* META_WINDOW_ACTOR_PRIVATE_H */
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -115,8 +115,6 @@ meta_window_group_paint (ClutterActor *actor)
|
||||
{
|
||||
cairo_region_t *clip_region;
|
||||
cairo_region_t *unobscured_region;
|
||||
ClutterActorIter iter;
|
||||
ClutterActor *child;
|
||||
cairo_rectangle_int_t visible_rect, clip_rect;
|
||||
int paint_x_offset, paint_y_offset;
|
||||
int paint_x_origin, paint_y_origin;
|
||||
@@ -125,18 +123,6 @@ meta_window_group_paint (ClutterActor *actor)
|
||||
MetaWindowGroup *window_group = META_WINDOW_GROUP (actor);
|
||||
ClutterActor *stage = clutter_actor_get_stage (actor);
|
||||
|
||||
/* Start off by treating all windows as completely unobscured, so damage anywhere
|
||||
* in a window queues redraws, but confine it more below. */
|
||||
clutter_actor_iter_init (&iter, actor);
|
||||
while (clutter_actor_iter_next (&iter, &child))
|
||||
{
|
||||
if (META_IS_WINDOW_ACTOR (child))
|
||||
{
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (child);
|
||||
meta_window_actor_set_unobscured_region (window_actor, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Normally we expect an actor to be drawn at it's position on the screen.
|
||||
* However, if we're inside the paint of a ClutterClone, that won't be the
|
||||
* case and we need to compensate. We look at the position of the window
|
||||
@@ -178,19 +164,6 @@ meta_window_group_paint (ClutterActor *actor)
|
||||
paint_y_offset = paint_y_origin - actor_y_origin;
|
||||
cairo_region_translate (clip_region, -paint_x_offset, -paint_y_offset);
|
||||
|
||||
if (!meta_is_wayland_compositor ())
|
||||
{
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (window_group->screen);
|
||||
if (info->unredirected_window != NULL)
|
||||
{
|
||||
cairo_rectangle_int_t unredirected_rect;
|
||||
|
||||
meta_window_get_frame_rect (info->unredirected_window, (MetaRectangle *)&unredirected_rect);
|
||||
cairo_region_subtract_rectangle (unobscured_region, &unredirected_rect);
|
||||
cairo_region_subtract_rectangle (clip_region, &unredirected_rect);
|
||||
}
|
||||
}
|
||||
|
||||
meta_cullable_cull_out (META_CULLABLE (window_group), unobscured_region, clip_region);
|
||||
|
||||
cairo_region_destroy (unobscured_region);
|
||||
|
@@ -32,13 +32,14 @@
|
||||
#include <gmodule.h>
|
||||
#include <string.h>
|
||||
|
||||
#define DESTROY_TIMEOUT 250
|
||||
#define DESTROY_TIMEOUT 100
|
||||
#define MINIMIZE_TIMEOUT 250
|
||||
#define MAXIMIZE_TIMEOUT 250
|
||||
#define MAP_TIMEOUT 250
|
||||
#define SWITCH_TIMEOUT 500
|
||||
|
||||
#define ACTOR_DATA_KEY "MCCP-Default-actor-data"
|
||||
#define SCREEN_TILE_PREVIEW_DATA_KEY "MCCP-Default-screen-tile-preview-data"
|
||||
|
||||
#define META_TYPE_DEFAULT_PLUGIN (meta_default_plugin_get_type ())
|
||||
#define META_DEFAULT_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEFAULT_PLUGIN, MetaDefaultPlugin))
|
||||
@@ -67,6 +68,7 @@ struct _MetaDefaultPluginClass
|
||||
};
|
||||
|
||||
static GQuark actor_data_quark = 0;
|
||||
static GQuark screen_tile_preview_data_quark = 0;
|
||||
|
||||
static void start (MetaPlugin *plugin);
|
||||
static void minimize (MetaPlugin *plugin,
|
||||
@@ -97,6 +99,12 @@ static void kill_window_effects (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor);
|
||||
static void kill_switch_workspace (MetaPlugin *plugin);
|
||||
|
||||
static void show_tile_preview (MetaPlugin *plugin,
|
||||
MetaWindow *window,
|
||||
MetaRectangle *tile_rect,
|
||||
int tile_monitor_number);
|
||||
static void hide_tile_preview (MetaPlugin *plugin);
|
||||
|
||||
static void confirm_display_change (MetaPlugin *plugin);
|
||||
|
||||
static const MetaPluginInfo * plugin_info (MetaPlugin *plugin);
|
||||
@@ -143,6 +151,15 @@ typedef struct
|
||||
} EffectCompleteData;
|
||||
|
||||
|
||||
typedef struct _ScreenTilePreview
|
||||
{
|
||||
ClutterActor *actor;
|
||||
|
||||
GdkRGBA *preview_color;
|
||||
|
||||
MetaRectangle tile_rect;
|
||||
} ScreenTilePreview;
|
||||
|
||||
static void
|
||||
meta_default_plugin_dispose (GObject *object)
|
||||
{
|
||||
@@ -203,6 +220,8 @@ meta_default_plugin_class_init (MetaDefaultPluginClass *klass)
|
||||
plugin_class->unmaximize = unmaximize;
|
||||
plugin_class->destroy = destroy;
|
||||
plugin_class->switch_workspace = switch_workspace;
|
||||
plugin_class->show_tile_preview = show_tile_preview;
|
||||
plugin_class->hide_tile_preview = hide_tile_preview;
|
||||
plugin_class->plugin_info = plugin_info;
|
||||
plugin_class->kill_window_effects = kill_window_effects;
|
||||
plugin_class->kill_switch_workspace = kill_switch_workspace;
|
||||
@@ -289,26 +308,13 @@ on_switch_workspace_effect_complete (ClutterTimeline *timeline, gpointer data)
|
||||
meta_plugin_switch_workspace_completed (plugin);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
show_stage (MetaPlugin *plugin)
|
||||
{
|
||||
MetaScreen *screen;
|
||||
ClutterActor *stage;
|
||||
|
||||
screen = meta_plugin_get_screen (plugin);
|
||||
stage = meta_get_stage_for_screen (screen);
|
||||
|
||||
clutter_actor_show (stage);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
on_monitors_changed (MetaScreen *screen,
|
||||
MetaPlugin *plugin)
|
||||
{
|
||||
MetaDefaultPlugin *self = META_DEFAULT_PLUGIN (plugin);
|
||||
int i, n;
|
||||
GRand *rand = g_rand_new_with_seed (12345);
|
||||
|
||||
clutter_actor_destroy_all_children (self->priv->background_group);
|
||||
|
||||
@@ -331,14 +337,16 @@ on_monitors_changed (MetaScreen *screen,
|
||||
reproducible.
|
||||
*/
|
||||
clutter_color_init (&color,
|
||||
g_random_int () % 255,
|
||||
g_random_int () % 255,
|
||||
g_random_int () % 255,
|
||||
g_rand_int_range (rand, 0, 255),
|
||||
g_rand_int_range (rand, 0, 255),
|
||||
g_rand_int_range (rand, 0, 255),
|
||||
255);
|
||||
clutter_actor_set_background_color (background, &color);
|
||||
|
||||
clutter_actor_add_child (self->priv->background_group, background);
|
||||
}
|
||||
|
||||
g_rand_free (rand);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -355,10 +363,7 @@ start (MetaPlugin *plugin)
|
||||
G_CALLBACK (on_monitors_changed), plugin);
|
||||
on_monitors_changed (screen, plugin);
|
||||
|
||||
meta_later_add (META_LATER_BEFORE_REDRAW,
|
||||
(GSourceFunc) show_stage,
|
||||
plugin,
|
||||
NULL);
|
||||
clutter_actor_show (meta_get_stage_for_screen (screen));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -483,8 +488,6 @@ on_minimize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data
|
||||
/* FIXME - we shouldn't assume the original scale, it should be saved
|
||||
* at the start of the effect */
|
||||
clutter_actor_set_scale (data->actor, 1.0, 1.0);
|
||||
clutter_actor_move_anchor_point_from_gravity (data->actor,
|
||||
CLUTTER_GRAVITY_NORTH_WEST);
|
||||
|
||||
/* Now notify the manager that we are done with this effect */
|
||||
meta_plugin_minimize_completed (plugin, window_actor);
|
||||
@@ -521,9 +524,6 @@ minimize (MetaPlugin *plugin, MetaWindowActor *window_actor)
|
||||
|
||||
apriv->is_minimized = TRUE;
|
||||
|
||||
clutter_actor_move_anchor_point_from_gravity (actor,
|
||||
CLUTTER_GRAVITY_CENTER);
|
||||
|
||||
animation = clutter_actor_animate (actor,
|
||||
CLUTTER_EASE_IN_SINE,
|
||||
MINIMIZE_TIMEOUT,
|
||||
@@ -562,8 +562,6 @@ on_maximize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data
|
||||
|
||||
/* FIXME - don't assume the original scale was 1.0 */
|
||||
clutter_actor_set_scale (data->actor, 1.0, 1.0);
|
||||
clutter_actor_move_anchor_point_from_gravity (data->actor,
|
||||
CLUTTER_GRAVITY_NORTH_WEST);
|
||||
|
||||
/* Now notify the manager that we are done with this effect */
|
||||
meta_plugin_maximize_completed (plugin, window_actor);
|
||||
@@ -588,10 +586,8 @@ maximize (MetaPlugin *plugin,
|
||||
ClutterActor *actor = CLUTTER_ACTOR (window_actor);
|
||||
MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
|
||||
|
||||
gdouble scale_x = 1.0;
|
||||
gdouble scale_y = 1.0;
|
||||
gfloat anchor_x = 0;
|
||||
gfloat anchor_y = 0;
|
||||
gdouble scale_x = 1.0;
|
||||
gdouble scale_y = 1.0;
|
||||
|
||||
type = meta_window_get_window_type (meta_window);
|
||||
|
||||
@@ -615,13 +611,6 @@ maximize (MetaPlugin *plugin,
|
||||
scale_x = (gdouble)end_width / (gdouble) width;
|
||||
scale_y = (gdouble)end_height / (gdouble) height;
|
||||
|
||||
anchor_x = (gdouble)(x - end_x)*(gdouble)width /
|
||||
((gdouble)(end_width - width));
|
||||
anchor_y = (gdouble)(y - end_y)*(gdouble)height /
|
||||
((gdouble)(end_height - height));
|
||||
|
||||
clutter_actor_move_anchor_point (actor, anchor_x, anchor_y);
|
||||
|
||||
animation = clutter_actor_animate (actor,
|
||||
CLUTTER_EASE_IN_SINE,
|
||||
MAXIMIZE_TIMEOUT,
|
||||
@@ -676,9 +665,6 @@ on_map_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data)
|
||||
|
||||
apriv->tml_map = NULL;
|
||||
|
||||
clutter_actor_move_anchor_point_from_gravity (data->actor,
|
||||
CLUTTER_GRAVITY_NORTH_WEST);
|
||||
|
||||
/* Now notify the manager that we are done with this effect */
|
||||
meta_plugin_map_completed (plugin, window_actor);
|
||||
|
||||
@@ -704,15 +690,15 @@ map (MetaPlugin *plugin, MetaWindowActor *window_actor)
|
||||
EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
|
||||
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||
|
||||
clutter_actor_move_anchor_point_from_gravity (actor,
|
||||
CLUTTER_GRAVITY_CENTER);
|
||||
|
||||
clutter_actor_set_scale (actor, 0.0, 0.0);
|
||||
clutter_actor_set_pivot_point (actor, 0.5, 0.5);
|
||||
clutter_actor_set_opacity (actor, 0);
|
||||
clutter_actor_set_scale (actor, 0.5, 0.5);
|
||||
clutter_actor_show (actor);
|
||||
|
||||
animation = clutter_actor_animate (actor,
|
||||
CLUTTER_EASE_IN_SINE,
|
||||
CLUTTER_EASE_OUT_QUAD,
|
||||
MAP_TIMEOUT,
|
||||
"opacity", 255,
|
||||
"scale-x", 1.0,
|
||||
"scale-y", 1.0,
|
||||
NULL);
|
||||
@@ -764,14 +750,12 @@ destroy (MetaPlugin *plugin, MetaWindowActor *window_actor)
|
||||
EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
|
||||
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||
|
||||
clutter_actor_move_anchor_point_from_gravity (actor,
|
||||
CLUTTER_GRAVITY_CENTER);
|
||||
|
||||
animation = clutter_actor_animate (actor,
|
||||
CLUTTER_EASE_IN_SINE,
|
||||
CLUTTER_EASE_OUT_QUAD,
|
||||
DESTROY_TIMEOUT,
|
||||
"scale-x", 0.0,
|
||||
"scale-y", 1.0,
|
||||
"opacity", 0,
|
||||
"scale-x", 0.8,
|
||||
"scale-y", 0.8,
|
||||
NULL);
|
||||
apriv->tml_destroy = clutter_animation_get_timeline (animation);
|
||||
data->plugin = plugin;
|
||||
@@ -784,6 +768,82 @@ destroy (MetaPlugin *plugin, MetaWindowActor *window_actor)
|
||||
meta_plugin_destroy_completed (plugin, window_actor);
|
||||
}
|
||||
|
||||
/*
|
||||
* Tile preview private data accessor
|
||||
*/
|
||||
static void
|
||||
free_screen_tile_preview (gpointer data)
|
||||
{
|
||||
ScreenTilePreview *preview = data;
|
||||
|
||||
if (G_LIKELY (preview != NULL)) {
|
||||
clutter_actor_destroy (preview->actor);
|
||||
g_slice_free (ScreenTilePreview, preview);
|
||||
}
|
||||
}
|
||||
|
||||
static ScreenTilePreview *
|
||||
get_screen_tile_preview (MetaScreen *screen)
|
||||
{
|
||||
ScreenTilePreview *preview = g_object_get_qdata (G_OBJECT (screen), screen_tile_preview_data_quark);
|
||||
|
||||
if (G_UNLIKELY (screen_tile_preview_data_quark == 0))
|
||||
screen_tile_preview_data_quark = g_quark_from_static_string (SCREEN_TILE_PREVIEW_DATA_KEY);
|
||||
|
||||
if (G_UNLIKELY (!preview))
|
||||
{
|
||||
preview = g_slice_new0 (ScreenTilePreview);
|
||||
|
||||
preview->actor = clutter_actor_new ();
|
||||
clutter_actor_set_background_color (preview->actor, CLUTTER_COLOR_Blue);
|
||||
clutter_actor_set_opacity (preview->actor, 100);
|
||||
|
||||
clutter_actor_add_child (meta_get_window_group_for_screen (screen), preview->actor);
|
||||
g_object_set_qdata_full (G_OBJECT (screen),
|
||||
screen_tile_preview_data_quark, preview,
|
||||
free_screen_tile_preview);
|
||||
}
|
||||
|
||||
return preview;
|
||||
}
|
||||
|
||||
static void
|
||||
show_tile_preview (MetaPlugin *plugin,
|
||||
MetaWindow *window,
|
||||
MetaRectangle *tile_rect,
|
||||
int tile_monitor_number)
|
||||
{
|
||||
MetaScreen *screen = meta_plugin_get_screen (plugin);
|
||||
ScreenTilePreview *preview = get_screen_tile_preview (screen);
|
||||
ClutterActor *window_actor;
|
||||
|
||||
if (CLUTTER_ACTOR_IS_VISIBLE (preview->actor)
|
||||
&& preview->tile_rect.x == tile_rect->x
|
||||
&& preview->tile_rect.y == tile_rect->y
|
||||
&& preview->tile_rect.width == tile_rect->width
|
||||
&& preview->tile_rect.height == tile_rect->height)
|
||||
return; /* nothing to do */
|
||||
|
||||
clutter_actor_set_position (preview->actor, tile_rect->x, tile_rect->y);
|
||||
clutter_actor_set_size (preview->actor, tile_rect->width, tile_rect->height);
|
||||
|
||||
clutter_actor_show (preview->actor);
|
||||
|
||||
window_actor = CLUTTER_ACTOR (meta_window_get_compositor_private (window));
|
||||
clutter_actor_lower (preview->actor, window_actor);
|
||||
|
||||
preview->tile_rect = *tile_rect;
|
||||
}
|
||||
|
||||
static void
|
||||
hide_tile_preview (MetaPlugin *plugin)
|
||||
{
|
||||
MetaScreen *screen = meta_plugin_get_screen (plugin);
|
||||
ScreenTilePreview *preview = get_screen_tile_preview (screen);
|
||||
|
||||
clutter_actor_hide (preview->actor);
|
||||
}
|
||||
|
||||
static void
|
||||
kill_switch_workspace (MetaPlugin *plugin)
|
||||
{
|
||||
|
@@ -58,88 +58,6 @@
|
||||
#include <canberra-gtk.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* bell_flash_screen:
|
||||
* @display: The display which owns the screen (rather redundant)
|
||||
* @screen: The screen to flash
|
||||
*
|
||||
* Flashes one entire screen. This is done by making a window the size of the
|
||||
* whole screen (or reusing the old one, if it's still around), mapping it,
|
||||
* painting it white and then black, and then unmapping it. We set saveunder so
|
||||
* that all the windows behind it come back immediately.
|
||||
*
|
||||
* Unlike frame flashes, we don't do fullscreen flashes with a timeout; rather,
|
||||
* we do them in one go, because we don't have to rely on the theme code
|
||||
* redrawing the frame for us in order to do the flash.
|
||||
*/
|
||||
/*
|
||||
* Bug: The way I read it, this appears not to do the flash
|
||||
* the first time we flash a particular display. Am I wrong?
|
||||
*
|
||||
* Bug: This appears to destroy our current XSync status.
|
||||
*/
|
||||
static void
|
||||
bell_flash_screen (MetaDisplay *display,
|
||||
MetaScreen *screen)
|
||||
{
|
||||
Window root = screen->xroot;
|
||||
int width = screen->rect.width;
|
||||
int height = screen->rect.height;
|
||||
|
||||
if (screen->flash_window == None)
|
||||
{
|
||||
Visual *visual = (Visual *)CopyFromParent;
|
||||
XSetWindowAttributes xswa;
|
||||
int depth = CopyFromParent;
|
||||
xswa.save_under = True;
|
||||
xswa.override_redirect = True;
|
||||
/*
|
||||
* TODO: use XGetVisualInfo and determine which is an
|
||||
* overlay, if one is present, and use the Overlay visual
|
||||
* for this window (for performance reasons).
|
||||
* Not sure how to tell this yet...
|
||||
*/
|
||||
screen->flash_window = XCreateWindow (display->xdisplay, root,
|
||||
0, 0, width, height,
|
||||
0, depth,
|
||||
InputOutput,
|
||||
visual,
|
||||
/* note: XSun doesn't like SaveUnder here */
|
||||
CWSaveUnder | CWOverrideRedirect,
|
||||
&xswa);
|
||||
XSelectInput (display->xdisplay, screen->flash_window, ExposureMask);
|
||||
XMapWindow (display->xdisplay, screen->flash_window);
|
||||
XSync (display->xdisplay, False);
|
||||
XFlush (display->xdisplay);
|
||||
XUnmapWindow (display->xdisplay, screen->flash_window);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* just draw something in the window */
|
||||
GC gc = XCreateGC (display->xdisplay, screen->flash_window, 0, NULL);
|
||||
XMapWindow (display->xdisplay, screen->flash_window);
|
||||
XSetForeground (display->xdisplay, gc,
|
||||
WhitePixel (display->xdisplay,
|
||||
XScreenNumberOfScreen (screen->xscreen)));
|
||||
XFillRectangle (display->xdisplay, screen->flash_window, gc,
|
||||
0, 0, width, height);
|
||||
XSetForeground (display->xdisplay, gc,
|
||||
BlackPixel (display->xdisplay,
|
||||
XScreenNumberOfScreen (screen->xscreen)));
|
||||
XFillRectangle (display->xdisplay, screen->flash_window, gc,
|
||||
0, 0, width, height);
|
||||
XFlush (display->xdisplay);
|
||||
XSync (display->xdisplay, False);
|
||||
XUnmapWindow (display->xdisplay, screen->flash_window);
|
||||
XFreeGC (display->xdisplay, gc);
|
||||
}
|
||||
|
||||
if (meta_prefs_get_focus_mode () != G_DESKTOP_FOCUS_MODE_CLICK &&
|
||||
!display->mouse_mode)
|
||||
meta_display_increment_focus_sentinel (display);
|
||||
XFlush (display->xdisplay);
|
||||
}
|
||||
|
||||
/**
|
||||
* bell_flash_fullscreen:
|
||||
* @display: The display the event came in on
|
||||
@@ -164,12 +82,7 @@ bell_flash_fullscreen (MetaDisplay *display,
|
||||
{
|
||||
screen = meta_display_screen_for_xwindow (display, xkb_bell_ev->window);
|
||||
if (screen)
|
||||
{
|
||||
if (display->compositor)
|
||||
meta_compositor_flash_screen (display->compositor, screen);
|
||||
else
|
||||
bell_flash_screen (display, screen);
|
||||
}
|
||||
meta_compositor_flash_screen (display->compositor, screen);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -177,10 +90,7 @@ bell_flash_fullscreen (MetaDisplay *display,
|
||||
while (screen_list)
|
||||
{
|
||||
screen = (MetaScreen *) screen_list->data;
|
||||
if (display->compositor)
|
||||
meta_compositor_flash_screen (display->compositor, screen);
|
||||
else
|
||||
bell_flash_screen (display, screen);
|
||||
meta_compositor_flash_screen (display->compositor, screen);
|
||||
screen_list = screen_list->next;
|
||||
}
|
||||
}
|
||||
|
@@ -425,8 +425,9 @@ setup_constraint_info (ConstraintInfo *info,
|
||||
* the monitor.
|
||||
*/
|
||||
if (meta_prefs_get_force_fullscreen() &&
|
||||
window->client_type != META_WINDOW_CLIENT_TYPE_WAYLAND &&
|
||||
!window->hide_titlebar_when_maximized &&
|
||||
window->decorated &&
|
||||
(window->decorated || !meta_window_is_client_decorated (window)) &&
|
||||
meta_rectangle_equal (new, &monitor_info->rect) &&
|
||||
window->has_fullscreen_func &&
|
||||
!window->fullscreen)
|
||||
@@ -491,12 +492,17 @@ place_window_if_needed(MetaWindow *window,
|
||||
!window->minimized &&
|
||||
!window->fullscreen)
|
||||
{
|
||||
MetaRectangle orig_rect;
|
||||
MetaRectangle placed_rect;
|
||||
MetaWorkspace *cur_workspace;
|
||||
const MetaMonitorInfo *monitor_info;
|
||||
|
||||
meta_window_get_frame_rect (window, &placed_rect);
|
||||
meta_window_place (window, info->orig.x, info->orig.y,
|
||||
|
||||
orig_rect = info->orig;
|
||||
extend_by_frame (window, &orig_rect);
|
||||
|
||||
meta_window_place (window, orig_rect.x, orig_rect.y,
|
||||
&placed_rect.x, &placed_rect.y);
|
||||
did_placement = TRUE;
|
||||
|
||||
|
@@ -27,16 +27,6 @@
|
||||
#include "window-private.h"
|
||||
#include "frame.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
META_IS_CONFIGURE_REQUEST = 1 << 0,
|
||||
META_DO_GRAVITY_ADJUST = 1 << 1,
|
||||
META_IS_USER_ACTION = 1 << 2,
|
||||
META_IS_MOVE_ACTION = 1 << 3,
|
||||
META_IS_RESIZE_ACTION = 1 << 4,
|
||||
META_IS_WAYLAND_RESIZE = 1 << 5
|
||||
} MetaMoveResizeFlags;
|
||||
|
||||
void meta_window_constrain (MetaWindow *window,
|
||||
MetaMoveResizeFlags flags,
|
||||
int resize_gravity,
|
||||
|
@@ -328,8 +328,7 @@ meta_core_maximize (Display *xdisplay,
|
||||
if (meta_prefs_get_raise_on_click ())
|
||||
meta_window_raise (window);
|
||||
|
||||
meta_window_maximize (window,
|
||||
META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
|
||||
meta_window_maximize (window, META_MAXIMIZE_BOTH);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -342,11 +341,9 @@ meta_core_toggle_maximize_vertically (Display *xdisplay,
|
||||
meta_window_raise (window);
|
||||
|
||||
if (META_WINDOW_MAXIMIZED_VERTICALLY (window))
|
||||
meta_window_unmaximize (window,
|
||||
META_MAXIMIZE_VERTICAL);
|
||||
meta_window_unmaximize (window, META_MAXIMIZE_VERTICAL);
|
||||
else
|
||||
meta_window_maximize (window,
|
||||
META_MAXIMIZE_VERTICAL);
|
||||
meta_window_maximize (window, META_MAXIMIZE_VERTICAL);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -359,11 +356,9 @@ meta_core_toggle_maximize_horizontally (Display *xdisplay,
|
||||
meta_window_raise (window);
|
||||
|
||||
if (META_WINDOW_MAXIMIZED_HORIZONTALLY (window))
|
||||
meta_window_unmaximize (window,
|
||||
META_MAXIMIZE_HORIZONTAL);
|
||||
meta_window_unmaximize (window, META_MAXIMIZE_HORIZONTAL);
|
||||
else
|
||||
meta_window_maximize (window,
|
||||
META_MAXIMIZE_HORIZONTAL);
|
||||
meta_window_maximize (window, META_MAXIMIZE_HORIZONTAL);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -376,11 +371,9 @@ meta_core_toggle_maximize (Display *xdisplay,
|
||||
meta_window_raise (window);
|
||||
|
||||
if (META_WINDOW_MAXIMIZED (window))
|
||||
meta_window_unmaximize (window,
|
||||
META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
|
||||
meta_window_unmaximize (window, META_MAXIMIZE_BOTH);
|
||||
else
|
||||
meta_window_maximize (window,
|
||||
META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
|
||||
meta_window_maximize (window, META_MAXIMIZE_BOTH);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -392,8 +385,7 @@ meta_core_unmaximize (Display *xdisplay,
|
||||
if (meta_prefs_get_raise_on_click ())
|
||||
meta_window_raise (window);
|
||||
|
||||
meta_window_unmaximize (window,
|
||||
META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
|
||||
meta_window_unmaximize (window, META_MAXIMIZE_BOTH);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -726,16 +718,6 @@ meta_core_set_screen_cursor (Display *xdisplay,
|
||||
meta_frame_set_screen_cursor (window->frame, cursor);
|
||||
}
|
||||
|
||||
void
|
||||
meta_core_increment_event_serial (Display *xdisplay)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
|
||||
display = meta_display_for_x_display (xdisplay);
|
||||
|
||||
meta_display_increment_event_serial (display);
|
||||
}
|
||||
|
||||
void
|
||||
meta_invalidate_default_icons (void)
|
||||
{
|
||||
|
@@ -193,12 +193,6 @@ void meta_core_set_screen_cursor (Display *xdisplay,
|
||||
Window frame_on_screen,
|
||||
MetaCursor cursor);
|
||||
|
||||
/* Used because we ignore EnterNotify when a window is unmapped that
|
||||
* really shouldn't cause focus changes, by comparing the event serial
|
||||
* of the EnterNotify and the UnmapNotify.
|
||||
*/
|
||||
void meta_core_increment_event_serial (Display *display);
|
||||
|
||||
void meta_invalidate_default_icons (void);
|
||||
|
||||
void meta_core_add_old_event_mask (Display *xdisplay,
|
||||
|
@@ -37,6 +37,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "wayland/meta-wayland-surface.h"
|
||||
|
||||
static void meta_window_present_delete_dialog (MetaWindow *window,
|
||||
guint32 timestamp);
|
||||
|
||||
@@ -130,35 +132,18 @@ void
|
||||
meta_window_check_alive (MetaWindow *window,
|
||||
guint32 timestamp)
|
||||
{
|
||||
meta_window_ping (window,
|
||||
timestamp,
|
||||
delete_ping_reply_func,
|
||||
delete_ping_timeout_func,
|
||||
NULL);
|
||||
meta_display_ping_window (window,
|
||||
timestamp,
|
||||
delete_ping_reply_func,
|
||||
delete_ping_timeout_func,
|
||||
NULL);
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_delete (MetaWindow *window,
|
||||
guint32 timestamp)
|
||||
{
|
||||
meta_error_trap_push (window->display);
|
||||
if (window->delete_window)
|
||||
{
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Deleting %s with delete_window request\n",
|
||||
window->desc);
|
||||
meta_window_send_icccm_message (window,
|
||||
window->display->atom_WM_DELETE_WINDOW,
|
||||
timestamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Deleting %s with explicit kill\n",
|
||||
window->desc);
|
||||
XKillClient (window->display->xdisplay, window->xwindow);
|
||||
}
|
||||
meta_error_trap_pop (window->display);
|
||||
META_WINDOW_GET_CLASS (window)->delete (window, timestamp);
|
||||
|
||||
meta_window_check_alive (window, timestamp);
|
||||
|
||||
@@ -191,33 +176,10 @@ meta_window_delete (MetaWindow *window,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
meta_window_kill (MetaWindow *window)
|
||||
{
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Killing %s brutally\n",
|
||||
window->desc);
|
||||
|
||||
if (!meta_window_is_remote (window) &&
|
||||
window->net_wm_pid > 0)
|
||||
{
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Killing %s with kill()\n",
|
||||
window->desc);
|
||||
|
||||
if (kill (window->net_wm_pid, 9) < 0)
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Failed to signal %s: %s\n",
|
||||
window->desc, strerror (errno));
|
||||
}
|
||||
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Disconnecting %s with XKillClient()\n",
|
||||
window->desc);
|
||||
meta_error_trap_push (window->display);
|
||||
XKillClient (window->display->xdisplay, window->xwindow);
|
||||
meta_error_trap_pop (window->display);
|
||||
META_WINDOW_GET_CLASS (window)->kill (window);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -252,8 +214,7 @@ meta_window_present_delete_dialog (MetaWindow *window, guint32 timestamp)
|
||||
{
|
||||
MetaWindow *w = tmp->data;
|
||||
|
||||
if (w->xtransient_for == window->xwindow &&
|
||||
w->res_class &&
|
||||
if (w->transient_for == window && w->res_class &&
|
||||
g_ascii_strcasecmp (w->res_class, "mutter-dialog") == 0)
|
||||
{
|
||||
meta_window_activate (w, timestamp);
|
||||
|
@@ -55,6 +55,10 @@ typedef struct _MetaWindowPropHooks MetaWindowPropHooks;
|
||||
|
||||
typedef struct MetaEdgeResistanceData MetaEdgeResistanceData;
|
||||
|
||||
typedef void (* MetaWindowPingFunc) (MetaWindow *window,
|
||||
guint32 timestamp,
|
||||
gpointer user_data);
|
||||
|
||||
typedef enum {
|
||||
META_LIST_DEFAULT = 0, /* normal windows */
|
||||
META_LIST_INCLUDE_OVERRIDE_REDIRECT = 1 << 0, /* normal and O-R */
|
||||
@@ -80,14 +84,6 @@ typedef enum {
|
||||
META_TILE_MAXIMIZED
|
||||
} MetaTileMode;
|
||||
|
||||
typedef enum {
|
||||
META_FOCUS_NONE = 0,
|
||||
META_FOCUS_X_CLIENT = 1,
|
||||
META_FOCUS_WAYLAND_CLIENT = 2,
|
||||
META_FOCUS_NO_FOCUS_WINDOW = 3,
|
||||
META_FOCUS_STAGE = 4
|
||||
} MetaFocusType;
|
||||
|
||||
struct _MetaDisplay
|
||||
{
|
||||
GObject parent_instance;
|
||||
@@ -121,7 +117,6 @@ struct _MetaDisplay
|
||||
* like the no_focus_window or the stage X window. */
|
||||
Window focus_xwindow;
|
||||
gulong focus_serial;
|
||||
MetaFocusType focus_type;
|
||||
|
||||
/* last timestamp passed to XSetInputFocus */
|
||||
guint32 last_focus_time;
|
||||
@@ -150,8 +145,6 @@ struct _MetaDisplay
|
||||
* multiple events with the same serial.
|
||||
*/
|
||||
guint focused_by_us : 1;
|
||||
|
||||
guint static_gravity_works : 1;
|
||||
|
||||
/*< private-ish >*/
|
||||
guint error_trap_synced_at_last_pop : 1;
|
||||
@@ -183,7 +176,7 @@ struct _MetaDisplay
|
||||
guint32 window_sequence_counter;
|
||||
|
||||
/* Pings which we're waiting for a reply from */
|
||||
GHashTable *pending_pings;
|
||||
GSList *pending_pings;
|
||||
|
||||
/* Pending focus change */
|
||||
guint focus_timeout_id;
|
||||
@@ -220,7 +213,6 @@ struct _MetaDisplay
|
||||
gboolean grab_threshold_movement_reached; /* raise_on_click == FALSE. */
|
||||
MetaResizePopup *grab_resize_popup;
|
||||
GTimeVal grab_last_moveresize_time;
|
||||
guint32 grab_motion_notify_time;
|
||||
GList* grab_old_window_stacking;
|
||||
MetaEdgeResistanceData *grab_edge_resistance_data;
|
||||
unsigned int grab_last_user_action_was_snap;
|
||||
@@ -238,8 +230,8 @@ struct _MetaDisplay
|
||||
int grab_resize_timeout_id;
|
||||
|
||||
/* Keybindings stuff */
|
||||
MetaKeyBinding *key_bindings;
|
||||
int n_key_bindings;
|
||||
GHashTable *key_bindings;
|
||||
GHashTable *key_bindings_index;
|
||||
int min_keycode;
|
||||
int max_keycode;
|
||||
KeySym *keymap;
|
||||
@@ -449,11 +441,22 @@ void meta_display_retheme_all (void);
|
||||
void meta_display_set_cursor_theme (const char *theme,
|
||||
int size);
|
||||
|
||||
void meta_display_ping_window (MetaWindow *window,
|
||||
guint32 timestamp,
|
||||
MetaWindowPingFunc ping_reply_func,
|
||||
MetaWindowPingFunc ping_timeout_func,
|
||||
void *user_data);
|
||||
void meta_display_pong_for_serial (MetaDisplay *display,
|
||||
guint32 serial);
|
||||
|
||||
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_mouse (MetaGrabOp op);
|
||||
gboolean meta_grab_op_is_clicking (MetaGrabOp op);
|
||||
gboolean meta_grab_op_is_wayland (MetaGrabOp op);
|
||||
gboolean meta_grab_op_is_keyboard (MetaGrabOp op);
|
||||
|
||||
void meta_display_devirtualize_modifiers (MetaDisplay *display,
|
||||
MetaVirtualModifier modifiers,
|
||||
@@ -481,10 +484,21 @@ gboolean meta_display_process_barrier_event (MetaDisplay *display,
|
||||
XIEvent *event);
|
||||
#endif /* HAVE_XI23 */
|
||||
|
||||
void meta_display_set_input_focus_xwindow (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
MetaFocusType type,
|
||||
Window window,
|
||||
guint32 timestamp);
|
||||
void meta_display_set_input_focus_xwindow (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
Window window,
|
||||
guint32 timestamp);
|
||||
|
||||
void meta_display_sync_wayland_input_focus (MetaDisplay *display);
|
||||
void meta_display_update_focus_window (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
Window xwindow,
|
||||
gulong serial,
|
||||
gboolean focused_by_us);
|
||||
|
||||
void meta_display_sanity_check_timestamps (MetaDisplay *display,
|
||||
guint32 timestamp);
|
||||
gboolean meta_display_timestamp_too_old (MetaDisplay *display,
|
||||
guint32 *timestamp);
|
||||
|
||||
#endif
|
||||
|
3049
src/core/display.c
3049
src/core/display.c
File diff suppressed because it is too large
Load Diff
2263
src/core/events.c
Normal file
2263
src/core/events.c
Normal file
File diff suppressed because it is too large
Load Diff
32
src/core/events.h
Normal file
32
src/core/events.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
* Copyright (C) 2002, 2003, 2004 Red Hat, Inc.
|
||||
* Copyright (C) 2003, 2004 Rob Adams
|
||||
* Copyright (C) 2004-2006 Elijah Newren
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <meta/display.h>
|
||||
|
||||
#ifndef META_EVENTS_H
|
||||
#define META_EVENTS_H
|
||||
|
||||
void meta_display_init_events (MetaDisplay *display);
|
||||
void meta_display_free_events (MetaDisplay *display);
|
||||
|
||||
#endif
|
||||
|
@@ -35,8 +35,7 @@
|
||||
ButtonPressMask | ButtonReleaseMask | \
|
||||
PointerMotionMask | PointerMotionHintMask | \
|
||||
EnterWindowMask | LeaveWindowMask | \
|
||||
FocusChangeMask | \
|
||||
ColormapChangeMask)
|
||||
FocusChangeMask)
|
||||
|
||||
void
|
||||
meta_window_ensure_frame (MetaWindow *window)
|
||||
@@ -62,7 +61,6 @@ meta_window_ensure_frame (MetaWindow *window)
|
||||
frame->right_width = 0;
|
||||
frame->current_cursor = 0;
|
||||
|
||||
frame->mapped = FALSE;
|
||||
frame->is_flashing = FALSE;
|
||||
frame->borders_cached = FALSE;
|
||||
|
||||
@@ -157,6 +155,8 @@ meta_window_ensure_frame (MetaWindow *window)
|
||||
|
||||
/* Move keybindings to frame instead of window */
|
||||
meta_window_grab_keys (window);
|
||||
|
||||
meta_ui_map_frame (frame->window->screen->ui, frame->xwindow);
|
||||
}
|
||||
|
||||
void
|
||||
|
@@ -47,7 +47,6 @@ struct _MetaFrame
|
||||
int right_width;
|
||||
int bottom_height;
|
||||
|
||||
guint mapped : 1;
|
||||
guint need_reapply_frame_shape : 1;
|
||||
guint is_flashing : 1; /* used by the visual bell flash */
|
||||
guint borders_cached : 1;
|
||||
|
@@ -30,6 +30,7 @@
|
||||
#include <gio/gio.h>
|
||||
#include <meta/keybindings.h>
|
||||
|
||||
typedef struct _MetaKeyHandler MetaKeyHandler;
|
||||
struct _MetaKeyHandler
|
||||
{
|
||||
char *name;
|
||||
@@ -47,9 +48,48 @@ struct _MetaKeyBinding
|
||||
KeyCode keycode;
|
||||
unsigned int mask;
|
||||
MetaVirtualModifier modifiers;
|
||||
gint flags;
|
||||
MetaKeyHandler *handler;
|
||||
};
|
||||
|
||||
/**
|
||||
* MetaKeyCombo:
|
||||
* @keysym: keysym
|
||||
* @keycode: keycode
|
||||
* @modifiers: modifiers
|
||||
*/
|
||||
typedef struct _MetaKeyCombo MetaKeyCombo;
|
||||
struct _MetaKeyCombo
|
||||
{
|
||||
unsigned int keysym;
|
||||
unsigned int keycode;
|
||||
MetaVirtualModifier modifiers;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *name;
|
||||
GSettings *settings;
|
||||
|
||||
MetaKeyBindingAction action;
|
||||
|
||||
/*
|
||||
* A list of MetaKeyCombos. Each of them is bound to
|
||||
* this keypref. If one has keysym==modifiers==0, it is
|
||||
* ignored.
|
||||
*/
|
||||
GSList *combos;
|
||||
|
||||
/* for keybindings that can have shift or not like Alt+Tab */
|
||||
gboolean add_shift:1;
|
||||
|
||||
/* for keybindings that apply only to a window */
|
||||
gboolean per_window:1;
|
||||
|
||||
/* for keybindings not added with meta_display_add_keybinding() */
|
||||
gboolean builtin:1;
|
||||
} MetaKeyPref;
|
||||
|
||||
void meta_display_init_keys (MetaDisplay *display);
|
||||
void meta_display_shutdown_keys (MetaDisplay *display);
|
||||
void meta_screen_grab_keys (MetaScreen *screen);
|
||||
@@ -77,5 +117,8 @@ gboolean meta_prefs_add_keybinding (const char *name,
|
||||
|
||||
gboolean meta_prefs_remove_keybinding (const char *name);
|
||||
|
||||
GList *meta_prefs_get_keybindings (void);
|
||||
void meta_prefs_get_overlay_binding (MetaKeyCombo *combo);
|
||||
const char *meta_prefs_get_iso_next_group_option (void);
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -42,7 +42,7 @@
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define _SVID_SOURCE /* for putenv() and some signal-related functions */
|
||||
#define _XOPEN_SOURCE /* for putenv() and some signal-related functions */
|
||||
|
||||
#include <config.h>
|
||||
#include <meta/main.h>
|
||||
@@ -50,10 +50,8 @@
|
||||
#include "display-private.h"
|
||||
#include <meta/errors.h>
|
||||
#include "ui.h"
|
||||
#include "session.h"
|
||||
#include <meta/prefs.h>
|
||||
#include <meta/compositor.h>
|
||||
#include "meta-wayland-private.h"
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <glib-unix.h>
|
||||
@@ -79,6 +77,10 @@
|
||||
#include <girepository.h>
|
||||
#endif
|
||||
|
||||
#include "x11/session.h"
|
||||
|
||||
#include "wayland/meta-wayland.h"
|
||||
|
||||
/*
|
||||
* The exit code we'll return to our parent process when we eventually die.
|
||||
*/
|
||||
@@ -190,6 +192,7 @@ static gboolean opt_replace_wm;
|
||||
static gboolean opt_disable_sm;
|
||||
static gboolean opt_sync;
|
||||
static gboolean opt_wayland;
|
||||
static gboolean opt_display_server;
|
||||
|
||||
static GOptionEntry meta_options[] = {
|
||||
{
|
||||
@@ -233,6 +236,11 @@ static GOptionEntry meta_options[] = {
|
||||
N_("Run as a wayland compositor"),
|
||||
NULL
|
||||
},
|
||||
{
|
||||
"display-server", 0, 0, G_OPTION_ARG_NONE,
|
||||
&opt_display_server,
|
||||
N_("Run as a full display server, rather than nested")
|
||||
},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
@@ -254,19 +262,8 @@ meta_get_option_context (void)
|
||||
bindtextdomain (GETTEXT_PACKAGE, MUTTER_LOCALEDIR);
|
||||
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
||||
|
||||
/* We must set the windowing backend here, because Clutter creates the backend
|
||||
object when the first call is made.
|
||||
|
||||
We consider running from mutter-launch equivalent to running from bare metal.
|
||||
*/
|
||||
if (getenv ("WESTON_LAUNCHER_SOCK"))
|
||||
clutter_set_windowing_backend (CLUTTER_WINDOWING_EGL);
|
||||
|
||||
ctx = g_option_context_new (NULL);
|
||||
g_option_context_add_main_entries (ctx, meta_options, GETTEXT_PACKAGE);
|
||||
g_option_context_add_group (ctx, clutter_get_option_group_without_init ());
|
||||
g_option_context_add_group (ctx, cogl_get_option_group ());
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
@@ -354,7 +351,8 @@ meta_select_display (char *display_arg)
|
||||
else
|
||||
display_name = g_getenv ("MUTTER_DISPLAY");
|
||||
|
||||
g_setenv ("DISPLAY", display_name, TRUE);
|
||||
if (display_name)
|
||||
g_setenv ("DISPLAY", display_name, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -389,7 +387,8 @@ meta_init (void)
|
||||
{
|
||||
struct sigaction act;
|
||||
sigset_t empty_mask;
|
||||
|
||||
ClutterSettings *clutter_settings;
|
||||
|
||||
sigemptyset (&empty_mask);
|
||||
act.sa_handler = SIG_IGN;
|
||||
act.sa_mask = empty_mask;
|
||||
@@ -410,6 +409,9 @@ meta_init (void)
|
||||
if (g_getenv ("MUTTER_DEBUG"))
|
||||
meta_set_debugging (TRUE);
|
||||
|
||||
if (opt_display_server)
|
||||
clutter_set_windowing_backend (CLUTTER_WINDOWING_EGL);
|
||||
|
||||
meta_set_is_wayland_compositor (opt_wayland);
|
||||
|
||||
if (g_get_home_dir ())
|
||||
@@ -441,7 +443,7 @@ meta_init (void)
|
||||
meta_fatal ("Can't specify both SM save file and SM client id\n");
|
||||
|
||||
meta_main_loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
|
||||
meta_ui_init ();
|
||||
|
||||
/* If we are running with wayland then we don't wait until we have
|
||||
@@ -455,6 +457,13 @@ meta_init (void)
|
||||
*/
|
||||
meta_clutter_init ();
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: We cannot handle high dpi scaling yet, so fix the scale to 1
|
||||
* for now.
|
||||
*/
|
||||
clutter_settings = clutter_settings_get_default ();
|
||||
g_object_set (clutter_settings, "window-scaling-factor", 1, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -495,6 +504,32 @@ meta_register_with_session (void)
|
||||
g_free (opt_client_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_activate_session:
|
||||
*
|
||||
* Tells mutter to activate the session. When mutter is a
|
||||
* Wayland compositor, this tells logind to switch over to
|
||||
* the new session.
|
||||
*/
|
||||
gboolean
|
||||
meta_activate_session (void)
|
||||
{
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||
GError *error = NULL;
|
||||
|
||||
if (!meta_wayland_compositor_activate_session (compositor, &error))
|
||||
{
|
||||
g_warning ("Could not activate session: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_run: (skip)
|
||||
*
|
||||
|
@@ -43,4 +43,7 @@ void meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
|
||||
int new_x,
|
||||
int new_y);
|
||||
void meta_cursor_tracker_paint (MetaCursorTracker *tracker);
|
||||
|
||||
void meta_cursor_tracker_force_update (MetaCursorTracker *tracker);
|
||||
|
||||
#endif
|
||||
|
@@ -39,6 +39,7 @@
|
||||
#include <gbm.h>
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
|
||||
#include <X11/cursorfont.h>
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
@@ -46,9 +47,10 @@
|
||||
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
#include "screen-private.h"
|
||||
#include "meta-wayland-private.h"
|
||||
#include "monitor-private.h"
|
||||
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
|
||||
#define META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_X 7
|
||||
#define META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_Y 4
|
||||
|
||||
@@ -569,13 +571,18 @@ make_wayland_cursor_tracker (MetaScreen *screen)
|
||||
|
||||
compositor = meta_wayland_compositor_get_default ();
|
||||
compositor->seat->cursor_tracker = self;
|
||||
meta_cursor_tracker_update_position (self,
|
||||
wl_fixed_to_int (compositor->seat->pointer.x),
|
||||
wl_fixed_to_int (compositor->seat->pointer.y));
|
||||
|
||||
if (meta_wayland_compositor_is_native (compositor))
|
||||
#if defined(CLUTTER_WINDOWING_EGL)
|
||||
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
|
||||
{
|
||||
CoglRenderer *cogl_renderer = cogl_display_get_renderer (cogl_context_get_display (ctx));
|
||||
self->drm_fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
|
||||
self->gbm = gbm_create_device (self->drm_fd);
|
||||
}
|
||||
#endif
|
||||
|
||||
monitors = meta_monitor_manager_get ();
|
||||
g_signal_connect_object (monitors, "monitors-changed",
|
||||
@@ -613,11 +620,9 @@ meta_cursor_tracker_get_for_screen (MetaScreen *screen)
|
||||
if (screen->cursor_tracker)
|
||||
return screen->cursor_tracker;
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
if (meta_is_wayland_compositor ())
|
||||
self = make_wayland_cursor_tracker (screen);
|
||||
else
|
||||
#endif
|
||||
self = make_x11_cursor_tracker (screen);
|
||||
|
||||
screen->cursor_tracker = self;
|
||||
@@ -1074,12 +1079,13 @@ get_pointer_position_gdk (int *x,
|
||||
GdkScreen *gscreen;
|
||||
|
||||
gmanager = gdk_display_get_device_manager (gdk_display_get_default ());
|
||||
gdevice = gdk_device_manager_get_client_pointer (gmanager);
|
||||
gdevice = gdk_x11_device_manager_lookup (gmanager, META_VIRTUAL_CORE_POINTER_ID);
|
||||
|
||||
gdk_device_get_position (gdevice, &gscreen, x, y);
|
||||
gdk_device_get_state (gdevice,
|
||||
gdk_screen_get_root_window (gscreen),
|
||||
NULL, (GdkModifierType*)mods);
|
||||
if (mods)
|
||||
gdk_device_get_state (gdevice,
|
||||
gdk_screen_get_root_window (gscreen),
|
||||
NULL, (GdkModifierType*)mods);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1095,9 +1101,12 @@ get_pointer_position_clutter (int *x,
|
||||
cdevice = clutter_device_manager_get_core_device (cmanager, CLUTTER_POINTER_DEVICE);
|
||||
|
||||
clutter_input_device_get_coords (cdevice, NULL, &point);
|
||||
*x = point.x;
|
||||
*y = point.y;
|
||||
*mods = clutter_input_device_get_modifier_state (cdevice);
|
||||
if (x)
|
||||
*x = point.x;
|
||||
if (y)
|
||||
*y = point.y;
|
||||
if (mods)
|
||||
*mods = clutter_input_device_get_modifier_state (cdevice);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1139,3 +1148,12 @@ meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker,
|
||||
tracker->screen->xroot);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_force_update (MetaCursorTracker *tracker)
|
||||
{
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
update_hw_cursor (tracker);
|
||||
sync_cursor (tracker);
|
||||
}
|
||||
|
@@ -535,7 +535,7 @@ make_watch (MetaIdleMonitor *monitor,
|
||||
watch->timeout_source = source;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (monitor->user_active_alarm != None)
|
||||
{
|
||||
if (timeout_msec != 0)
|
||||
{
|
||||
@@ -653,8 +653,10 @@ meta_idle_monitor_remove_watch (MetaIdleMonitor *monitor,
|
||||
{
|
||||
g_return_if_fail (META_IS_IDLE_MONITOR (monitor));
|
||||
|
||||
g_object_ref (monitor);
|
||||
g_hash_table_remove (monitor->watches,
|
||||
GUINT_TO_POINTER (id));
|
||||
g_object_unref (monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -650,7 +650,7 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
|
||||
state = DRM_MODE_DPMS_SUSPEND;
|
||||
break;
|
||||
case META_POWER_SAVE_OFF:
|
||||
state = DRM_MODE_DPMS_SUSPEND;
|
||||
state = DRM_MODE_DPMS_OFF;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
|
@@ -42,9 +42,7 @@
|
||||
#include <meta/screen.h>
|
||||
#include "stack-tracker.h"
|
||||
#include "ui.h"
|
||||
#ifdef HAVE_WAYLAND
|
||||
#include <wayland-server.h>
|
||||
#endif
|
||||
#include "meta-xrandr-shared.h"
|
||||
|
||||
#include "meta-dbus-xrandr.h"
|
||||
@@ -54,19 +52,6 @@ typedef struct _MetaMonitorManager MetaMonitorManager;
|
||||
typedef struct _MetaMonitorConfigClass MetaMonitorConfigClass;
|
||||
typedef struct _MetaMonitorConfig MetaMonitorConfig;
|
||||
|
||||
#ifndef HAVE_WAYLAND
|
||||
enum wl_output_transform {
|
||||
WL_OUTPUT_TRANSFORM_NORMAL,
|
||||
WL_OUTPUT_TRANSFORM_90,
|
||||
WL_OUTPUT_TRANSFORM_180,
|
||||
WL_OUTPUT_TRANSFORM_270,
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED,
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED_90,
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED_180,
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED_270
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef struct _MetaOutput MetaOutput;
|
||||
typedef struct _MetaCRTC MetaCRTC;
|
||||
typedef struct _MetaMonitorMode MetaMonitorMode;
|
||||
|
@@ -34,7 +34,6 @@
|
||||
#include "util-private.h"
|
||||
#include <meta/errors.h>
|
||||
#include "monitor-private.h"
|
||||
#include "meta-wayland-private.h"
|
||||
|
||||
#include "meta-dbus-xrandr.h"
|
||||
|
||||
@@ -356,19 +355,35 @@ make_logical_config (MetaMonitorManager *manager)
|
||||
static GType
|
||||
get_default_backend (void)
|
||||
{
|
||||
if (meta_is_wayland_compositor ())
|
||||
#if defined(CLUTTER_WINDOWING_EGL)
|
||||
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
|
||||
return META_TYPE_MONITOR_MANAGER_KMS;
|
||||
#endif
|
||||
|
||||
#if defined(CLUTTER_WINDOWING_X11)
|
||||
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_X11))
|
||||
{
|
||||
MetaWaylandCompositor *compositor;
|
||||
|
||||
compositor = meta_wayland_compositor_get_default ();
|
||||
|
||||
if (meta_wayland_compositor_is_native (compositor))
|
||||
return META_TYPE_MONITOR_MANAGER_KMS;
|
||||
else
|
||||
/* If we're a Wayland compositor using the X11 backend,
|
||||
* we're a nested configuration, so return the dummy
|
||||
* monitor setup. */
|
||||
if (meta_is_wayland_compositor ())
|
||||
return META_TYPE_MONITOR_MANAGER;
|
||||
else
|
||||
return META_TYPE_MONITOR_MANAGER_XRANDR;
|
||||
}
|
||||
else
|
||||
return META_TYPE_MONITOR_MANAGER_XRANDR;
|
||||
#endif
|
||||
|
||||
#if defined(CLUTTER_WINDOWING_WAYLAND)
|
||||
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_WAYLAND))
|
||||
{
|
||||
/* Use the dummy implementation on Wayland for now.
|
||||
* In the future, we should support wl_fullscreen_output
|
||||
* which will have CRTC management in the protocol. */
|
||||
return META_TYPE_MONITOR_MANAGER;
|
||||
}
|
||||
#endif
|
||||
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
static MetaMonitorManager *
|
||||
|
@@ -344,7 +344,7 @@ avoid_being_obscured_as_second_modal_dialog (MetaWindow *window,
|
||||
/* denied_focus_and_not_transient is only set when focus_window != NULL */
|
||||
|
||||
if (window->denied_focus_and_not_transient &&
|
||||
window->wm_state_modal && /* FIXME: Maybe do this for all transients? */
|
||||
window->type == META_WINDOW_MODAL_DIALOG &&
|
||||
meta_window_same_application (window, focus_window) &&
|
||||
window_overlaps_focus_window (window))
|
||||
{
|
||||
@@ -610,7 +610,7 @@ meta_window_place (MetaWindow *window,
|
||||
meta_topic (META_DEBUG_PLACEMENT, "Placing window %s\n", window->desc);
|
||||
|
||||
windows = NULL;
|
||||
|
||||
|
||||
switch (window->type)
|
||||
{
|
||||
/* Run placement algorithm on these. */
|
||||
@@ -638,7 +638,7 @@ meta_window_place (MetaWindow *window,
|
||||
case META_WINDOW_OVERRIDE_OTHER:
|
||||
goto done_no_constraints;
|
||||
}
|
||||
|
||||
|
||||
if (meta_prefs_get_disable_workarounds ())
|
||||
{
|
||||
switch (window->type)
|
||||
@@ -699,18 +699,11 @@ meta_window_place (MetaWindow *window,
|
||||
goto done_no_constraints;
|
||||
}
|
||||
}
|
||||
|
||||
if ((window->type == META_WINDOW_DIALOG ||
|
||||
window->type == META_WINDOW_MODAL_DIALOG) &&
|
||||
window->xtransient_for != None)
|
||||
{
|
||||
/* Center horizontally, at top of parent vertically */
|
||||
|
||||
MetaWindow *parent;
|
||||
|
||||
parent =
|
||||
meta_display_lookup_x_window (window->display,
|
||||
window->xtransient_for);
|
||||
if (window->type == META_WINDOW_DIALOG ||
|
||||
window->type == META_WINDOW_MODAL_DIALOG)
|
||||
{
|
||||
MetaWindow *parent = meta_window_get_transient_for (window);
|
||||
|
||||
if (parent)
|
||||
{
|
||||
|
@@ -57,7 +57,6 @@
|
||||
|
||||
#define KEY_OVERLAY_KEY "overlay-key"
|
||||
#define KEY_WORKSPACES_ONLY_ON_PRIMARY "workspaces-only-on-primary"
|
||||
#define KEY_NO_TAB_POPUP "no-tab-popup"
|
||||
|
||||
/* These are the different schemas we are keeping
|
||||
* a GSettings instance for */
|
||||
@@ -112,8 +111,6 @@ static char **workspace_names = NULL;
|
||||
|
||||
static gboolean workspaces_only_on_primary = FALSE;
|
||||
|
||||
static gboolean no_tab_popup = FALSE;
|
||||
|
||||
static char *iso_next_group_option = NULL;
|
||||
|
||||
static void handle_preference_update_enum (GSettings *settings,
|
||||
@@ -365,13 +362,6 @@ static MetaBoolPreference preferences_bool[] =
|
||||
},
|
||||
&workspaces_only_on_primary,
|
||||
},
|
||||
{
|
||||
{ KEY_NO_TAB_POPUP,
|
||||
SCHEMA_MUTTER,
|
||||
META_PREF_NO_TAB_POPUP,
|
||||
},
|
||||
&no_tab_popup,
|
||||
},
|
||||
{
|
||||
{ "auto-maximize",
|
||||
SCHEMA_MUTTER,
|
||||
@@ -1813,9 +1803,6 @@ meta_preference_to_string (MetaPreference pref)
|
||||
case META_PREF_WORKSPACES_ONLY_ON_PRIMARY:
|
||||
return "WORKSPACES_ONLY_ON_PRIMARY";
|
||||
|
||||
case META_PREF_NO_TAB_POPUP:
|
||||
return "NO_TAB_POPUP";
|
||||
|
||||
case META_PREF_DRAGGABLE_BORDER_WIDTH:
|
||||
return "DRAGGABLE_BORDER_WIDTH";
|
||||
|
||||
@@ -1869,7 +1856,7 @@ init_bindings (void)
|
||||
pref = g_new0 (MetaKeyPref, 1);
|
||||
pref->name = g_strdup ("overlay-key");
|
||||
pref->action = META_KEYBINDING_ACTION_OVERLAY_KEY;
|
||||
pref->bindings = g_slist_prepend (pref->bindings, &overlay_key_combo);
|
||||
pref->combos = g_slist_prepend (pref->combos, &overlay_key_combo);
|
||||
pref->builtin = 1;
|
||||
|
||||
g_hash_table_insert (key_bindings, g_strdup ("overlay-key"), pref);
|
||||
@@ -1879,7 +1866,7 @@ static gboolean
|
||||
update_binding (MetaKeyPref *binding,
|
||||
gchar **strokes)
|
||||
{
|
||||
GSList *old_bindings, *a, *b;
|
||||
GSList *old_combos, *a, *b;
|
||||
gboolean changed;
|
||||
unsigned int keysym;
|
||||
unsigned int keycode;
|
||||
@@ -1891,8 +1878,8 @@ update_binding (MetaKeyPref *binding,
|
||||
"Binding \"%s\" has new GSettings value\n",
|
||||
binding->name);
|
||||
|
||||
old_bindings = binding->bindings;
|
||||
binding->bindings = NULL;
|
||||
old_combos = binding->combos;
|
||||
binding->combos = NULL;
|
||||
|
||||
for (i = 0; strokes && strokes[i]; i++)
|
||||
{
|
||||
@@ -1933,17 +1920,17 @@ update_binding (MetaKeyPref *binding,
|
||||
combo->keysym = keysym;
|
||||
combo->keycode = keycode;
|
||||
combo->modifiers = mods;
|
||||
binding->bindings = g_slist_prepend (binding->bindings, combo);
|
||||
binding->combos = g_slist_prepend (binding->combos, combo);
|
||||
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"New keybinding for \"%s\" is keysym = 0x%x keycode = 0x%x mods = 0x%x\n",
|
||||
binding->name, keysym, keycode, mods);
|
||||
}
|
||||
|
||||
binding->bindings = g_slist_reverse (binding->bindings);
|
||||
binding->combos = g_slist_reverse (binding->combos);
|
||||
|
||||
a = old_bindings;
|
||||
b = binding->bindings;
|
||||
a = old_combos;
|
||||
b = binding->combos;
|
||||
while (TRUE)
|
||||
{
|
||||
if ((!a && b) || (a && !b))
|
||||
@@ -1968,7 +1955,7 @@ update_binding (MetaKeyPref *binding,
|
||||
}
|
||||
}
|
||||
|
||||
g_slist_free_full (old_bindings, g_free);
|
||||
g_slist_free_full (old_combos, g_free);
|
||||
|
||||
return changed;
|
||||
}
|
||||
@@ -2103,7 +2090,7 @@ meta_prefs_add_keybinding (const char *name,
|
||||
pref->name = g_strdup (name);
|
||||
pref->settings = g_object_ref (settings);
|
||||
pref->action = action;
|
||||
pref->bindings = NULL;
|
||||
pref->combos = NULL;
|
||||
pref->add_shift = (flags & META_KEY_BINDING_REVERSES) != 0;
|
||||
pref->per_window = (flags & META_KEY_BINDING_PER_WINDOW) != 0;
|
||||
pref->builtin = (flags & META_KEY_BINDING_BUILTIN) != 0;
|
||||
@@ -2167,11 +2154,6 @@ meta_prefs_remove_keybinding (const char *name)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_prefs_get_keybindings:
|
||||
*
|
||||
* Returns: (element-type MetaKeyPref) (transfer container):
|
||||
*/
|
||||
GList *
|
||||
meta_prefs_get_keybindings ()
|
||||
{
|
||||
@@ -2272,7 +2254,7 @@ meta_prefs_get_window_binding (const char *name,
|
||||
|
||||
if (pref->per_window)
|
||||
{
|
||||
GSList *s = pref->bindings;
|
||||
GSList *s = pref->combos;
|
||||
|
||||
while (s)
|
||||
{
|
||||
@@ -2320,25 +2302,6 @@ meta_prefs_get_workspaces_only_on_primary (void)
|
||||
return workspaces_only_on_primary;
|
||||
}
|
||||
|
||||
|
||||
gboolean
|
||||
meta_prefs_get_no_tab_popup (void)
|
||||
{
|
||||
return no_tab_popup;
|
||||
}
|
||||
|
||||
void
|
||||
meta_prefs_set_no_tab_popup (gboolean whether)
|
||||
{
|
||||
MetaBasePreference *pref;
|
||||
|
||||
if (find_pref (preferences_bool, sizeof(MetaBoolPreference),
|
||||
KEY_NO_TAB_POPUP, &pref))
|
||||
{
|
||||
g_settings_set_boolean (SETTINGS (pref->schema), KEY_NO_TAB_POPUP, whether);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
meta_prefs_get_draggable_border_width (void)
|
||||
{
|
||||
|
@@ -64,8 +64,6 @@ struct _MetaScreen
|
||||
Visual *default_xvisual;
|
||||
MetaRectangle rect; /* Size of screen; rect.x & rect.y are always 0 */
|
||||
MetaUI *ui;
|
||||
MetaTabPopup *tab_popup, *ws_popup;
|
||||
MetaTilePreview *tile_preview;
|
||||
|
||||
guint tile_preview_timeout_id;
|
||||
|
||||
@@ -84,8 +82,6 @@ struct _MetaScreen
|
||||
MetaCursorTracker *cursor_tracker;
|
||||
MetaCursor current_cursor;
|
||||
|
||||
Window flash_window;
|
||||
|
||||
Window wm_sn_selection_window;
|
||||
Atom wm_sn_atom;
|
||||
guint32 wm_sn_timestamp;
|
||||
@@ -151,25 +147,9 @@ void meta_screen_foreach_window (MetaScreen *scree
|
||||
|
||||
void meta_screen_update_cursor (MetaScreen *screen);
|
||||
|
||||
void meta_screen_tab_popup_create (MetaScreen *screen,
|
||||
MetaTabList list_type,
|
||||
MetaTabShowType show_type,
|
||||
MetaWindow *initial_window);
|
||||
void meta_screen_tab_popup_forward (MetaScreen *screen);
|
||||
void meta_screen_tab_popup_backward (MetaScreen *screen);
|
||||
MetaWindow* meta_screen_tab_popup_get_selected (MetaScreen *screen);
|
||||
void meta_screen_tab_popup_destroy (MetaScreen *screen);
|
||||
|
||||
void meta_screen_workspace_popup_create (MetaScreen *screen,
|
||||
MetaWorkspace *initial_selection);
|
||||
void meta_screen_workspace_popup_select (MetaScreen *screen,
|
||||
MetaWorkspace *workspace);
|
||||
MetaWorkspace*meta_screen_workspace_popup_get_selected (MetaScreen *screen);
|
||||
void meta_screen_workspace_popup_destroy (MetaScreen *screen);
|
||||
|
||||
void meta_screen_tile_preview_update (MetaScreen *screen,
|
||||
void meta_screen_update_tile_preview (MetaScreen *screen,
|
||||
gboolean delay);
|
||||
void meta_screen_tile_preview_hide (MetaScreen *screen);
|
||||
void meta_screen_hide_tile_preview (MetaScreen *screen);
|
||||
|
||||
MetaWindow* meta_screen_get_mouse_window (MetaScreen *screen,
|
||||
MetaWindow *not_this_one);
|
||||
|
@@ -39,11 +39,9 @@
|
||||
#include "workspace-private.h"
|
||||
#include "keybindings-private.h"
|
||||
#include "stack.h"
|
||||
#include "xprops.h"
|
||||
#include <meta/compositor.h>
|
||||
#include "mutter-enum-types.h"
|
||||
#include "core.h"
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
|
||||
#include <X11/extensions/Xinerama.h>
|
||||
@@ -54,6 +52,8 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "x11/xprops.h"
|
||||
|
||||
static char* get_screen_name (MetaDisplay *display,
|
||||
int number);
|
||||
|
||||
@@ -308,6 +308,8 @@ set_supported_hint (MetaScreen *screen)
|
||||
#include <meta/atomnames.h>
|
||||
#undef item
|
||||
#undef EWMH_ATOMS_ONLY
|
||||
|
||||
screen->display->atom__GTK_FRAME_EXTENTS,
|
||||
};
|
||||
|
||||
XChangeProperty (screen->display->xdisplay, screen->xroot,
|
||||
@@ -389,6 +391,8 @@ int
|
||||
meta_screen_monitor_index_to_xinerama_index (MetaScreen *screen,
|
||||
int index)
|
||||
{
|
||||
g_return_val_if_fail (index >= 0 && index < screen->n_monitor_infos, -1);
|
||||
|
||||
meta_screen_ensure_xinerama_indices (screen);
|
||||
|
||||
return screen->monitor_infos[index].xinerama_index;
|
||||
@@ -686,7 +690,6 @@ meta_screen_new (MetaDisplay *display,
|
||||
screen->current_cursor = -1; /* invalid/unset */
|
||||
screen->default_xvisual = DefaultVisualOfScreen (screen->xscreen);
|
||||
screen->default_depth = DefaultDepthOfScreen (screen->xscreen);
|
||||
screen->flash_window = None;
|
||||
|
||||
screen->wm_sn_selection_window = new_wm_sn_owner;
|
||||
screen->wm_sn_atom = wm_sn_atom;
|
||||
@@ -758,10 +761,6 @@ meta_screen_new (MetaDisplay *display,
|
||||
screen->ui = meta_ui_new (screen->display->xdisplay,
|
||||
screen->xscreen);
|
||||
|
||||
screen->tab_popup = NULL;
|
||||
screen->ws_popup = NULL;
|
||||
screen->tile_preview = NULL;
|
||||
|
||||
screen->tile_preview_timeout_id = 0;
|
||||
|
||||
screen->stack = meta_stack_new (screen);
|
||||
@@ -809,11 +808,8 @@ meta_screen_free (MetaScreen *screen,
|
||||
|
||||
meta_display_grab (display);
|
||||
|
||||
if (screen->display->compositor)
|
||||
{
|
||||
meta_compositor_unmanage_screen (screen->display->compositor,
|
||||
screen);
|
||||
}
|
||||
meta_compositor_unmanage_screen (screen->display->compositor,
|
||||
screen);
|
||||
|
||||
meta_display_unmanage_windows_for_screen (display, screen, timestamp);
|
||||
|
||||
@@ -866,9 +862,6 @@ meta_screen_free (MetaScreen *screen,
|
||||
if (screen->tile_preview_timeout_id)
|
||||
g_source_remove (screen->tile_preview_timeout_id);
|
||||
|
||||
if (screen->tile_preview)
|
||||
meta_tile_preview_free (screen->tile_preview);
|
||||
|
||||
g_free (screen->screen_name);
|
||||
|
||||
g_object_unref (screen);
|
||||
@@ -1430,255 +1423,8 @@ meta_screen_update_cursor (MetaScreen *screen)
|
||||
screen->current_cursor);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_tab_popup_create (MetaScreen *screen,
|
||||
MetaTabList list_type,
|
||||
MetaTabShowType show_type,
|
||||
MetaWindow *initial_selection)
|
||||
{
|
||||
MetaTabEntry *entries;
|
||||
GList *tab_list;
|
||||
GList *tmp;
|
||||
int len;
|
||||
int i;
|
||||
|
||||
if (screen->tab_popup)
|
||||
return;
|
||||
|
||||
tab_list = meta_display_get_tab_list (screen->display,
|
||||
list_type,
|
||||
screen,
|
||||
screen->active_workspace);
|
||||
|
||||
len = g_list_length (tab_list);
|
||||
|
||||
entries = g_new (MetaTabEntry, len + 1);
|
||||
entries[len].key = NULL;
|
||||
entries[len].title = NULL;
|
||||
entries[len].icon = NULL;
|
||||
|
||||
i = 0;
|
||||
tmp = tab_list;
|
||||
while (i < len)
|
||||
{
|
||||
MetaWindow *window;
|
||||
MetaRectangle r;
|
||||
|
||||
window = tmp->data;
|
||||
|
||||
entries[i].key = (MetaTabEntryKey) window;
|
||||
entries[i].title = window->title;
|
||||
entries[i].icon = g_object_ref (window->icon);
|
||||
entries[i].blank = FALSE;
|
||||
entries[i].hidden = !meta_window_showing_on_its_workspace (window);
|
||||
entries[i].demands_attention = window->wm_state_demands_attention;
|
||||
|
||||
if (show_type == META_TAB_SHOW_INSTANTLY ||
|
||||
!entries[i].hidden ||
|
||||
!meta_window_get_icon_geometry (window, &r))
|
||||
meta_window_get_frame_rect (window, &r);
|
||||
|
||||
entries[i].rect = r;
|
||||
|
||||
/* Find inside of highlight rectangle to be used when window is
|
||||
* outlined for tabbing. This should be the size of the
|
||||
* east/west frame, and the size of the south frame, on those
|
||||
* sides. On the top it should be the size of the south frame
|
||||
* edge.
|
||||
*/
|
||||
#define OUTLINE_WIDTH 5
|
||||
/* Top side */
|
||||
if (!entries[i].hidden &&
|
||||
window->frame && window->frame->bottom_height > 0 &&
|
||||
window->frame->child_y >= window->frame->bottom_height)
|
||||
entries[i].inner_rect.y = window->frame->bottom_height;
|
||||
else
|
||||
entries[i].inner_rect.y = OUTLINE_WIDTH;
|
||||
|
||||
/* Bottom side */
|
||||
if (!entries[i].hidden &&
|
||||
window->frame && window->frame->bottom_height != 0)
|
||||
entries[i].inner_rect.height = r.height
|
||||
- entries[i].inner_rect.y - window->frame->bottom_height;
|
||||
else
|
||||
entries[i].inner_rect.height = r.height
|
||||
- entries[i].inner_rect.y - OUTLINE_WIDTH;
|
||||
|
||||
/* Left side */
|
||||
if (!entries[i].hidden && window->frame && window->frame->child_x != 0)
|
||||
entries[i].inner_rect.x = window->frame->child_x;
|
||||
else
|
||||
entries[i].inner_rect.x = OUTLINE_WIDTH;
|
||||
|
||||
/* Right side */
|
||||
if (!entries[i].hidden &&
|
||||
window->frame && window->frame->right_width != 0)
|
||||
entries[i].inner_rect.width = r.width
|
||||
- entries[i].inner_rect.x - window->frame->right_width;
|
||||
else
|
||||
entries[i].inner_rect.width = r.width
|
||||
- entries[i].inner_rect.x - OUTLINE_WIDTH;
|
||||
|
||||
++i;
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
if (!meta_prefs_get_no_tab_popup ())
|
||||
screen->tab_popup = meta_ui_tab_popup_new (entries,
|
||||
screen->number,
|
||||
len,
|
||||
5, /* FIXME */
|
||||
TRUE);
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
g_object_unref (entries[i].icon);
|
||||
|
||||
g_free (entries);
|
||||
|
||||
g_list_free (tab_list);
|
||||
|
||||
meta_ui_tab_popup_select (screen->tab_popup,
|
||||
(MetaTabEntryKey) initial_selection);
|
||||
|
||||
if (show_type != META_TAB_SHOW_INSTANTLY)
|
||||
meta_ui_tab_popup_set_showing (screen->tab_popup, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_tab_popup_forward (MetaScreen *screen)
|
||||
{
|
||||
g_return_if_fail (screen->tab_popup != NULL);
|
||||
|
||||
meta_ui_tab_popup_forward (screen->tab_popup);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_tab_popup_backward (MetaScreen *screen)
|
||||
{
|
||||
g_return_if_fail (screen->tab_popup != NULL);
|
||||
|
||||
meta_ui_tab_popup_backward (screen->tab_popup);
|
||||
}
|
||||
|
||||
MetaWindow *
|
||||
meta_screen_tab_popup_get_selected (MetaScreen *screen)
|
||||
{
|
||||
g_return_val_if_fail (screen->tab_popup != NULL, NULL);
|
||||
|
||||
return (MetaWindow *) meta_ui_tab_popup_get_selected (screen->tab_popup);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_tab_popup_destroy (MetaScreen *screen)
|
||||
{
|
||||
if (screen->tab_popup)
|
||||
{
|
||||
meta_ui_tab_popup_free (screen->tab_popup);
|
||||
screen->tab_popup = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_workspace_popup_create (MetaScreen *screen,
|
||||
MetaWorkspace *initial_selection)
|
||||
{
|
||||
MetaTabEntry *entries;
|
||||
int len;
|
||||
int i;
|
||||
MetaWorkspaceLayout layout;
|
||||
int n_workspaces;
|
||||
int current_workspace;
|
||||
|
||||
if (screen->ws_popup || meta_prefs_get_no_tab_popup ())
|
||||
return;
|
||||
|
||||
current_workspace = meta_workspace_index (screen->active_workspace);
|
||||
n_workspaces = meta_screen_get_n_workspaces (screen);
|
||||
|
||||
meta_screen_calc_workspace_layout (screen, n_workspaces,
|
||||
current_workspace, &layout);
|
||||
|
||||
len = layout.grid_area;
|
||||
|
||||
entries = g_new (MetaTabEntry, len + 1);
|
||||
entries[len].key = NULL;
|
||||
entries[len].title = NULL;
|
||||
entries[len].icon = NULL;
|
||||
|
||||
i = 0;
|
||||
while (i < len)
|
||||
{
|
||||
if (layout.grid[i] >= 0)
|
||||
{
|
||||
MetaWorkspace *workspace;
|
||||
|
||||
workspace = meta_screen_get_workspace_by_index (screen,
|
||||
layout.grid[i]);
|
||||
|
||||
entries[i].key = (MetaTabEntryKey) workspace;
|
||||
entries[i].title = meta_workspace_get_name (workspace);
|
||||
entries[i].icon = NULL;
|
||||
entries[i].blank = FALSE;
|
||||
|
||||
g_assert (entries[i].title != NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
entries[i].key = NULL;
|
||||
entries[i].title = NULL;
|
||||
entries[i].icon = NULL;
|
||||
entries[i].blank = TRUE;
|
||||
}
|
||||
entries[i].hidden = FALSE;
|
||||
entries[i].demands_attention = FALSE;
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
screen->ws_popup = meta_ui_tab_popup_new (entries,
|
||||
screen->number,
|
||||
len,
|
||||
layout.cols,
|
||||
FALSE);
|
||||
|
||||
g_free (entries);
|
||||
meta_screen_free_workspace_layout (&layout);
|
||||
|
||||
meta_ui_tab_popup_select (screen->ws_popup,
|
||||
(MetaTabEntryKey) initial_selection);
|
||||
meta_ui_tab_popup_set_showing (screen->ws_popup, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_workspace_popup_select (MetaScreen *screen,
|
||||
MetaWorkspace *workspace)
|
||||
{
|
||||
g_return_if_fail (screen->ws_popup != NULL);
|
||||
|
||||
meta_ui_tab_popup_select (screen->ws_popup,
|
||||
(MetaTabEntryKey) workspace);
|
||||
}
|
||||
|
||||
MetaWorkspace *
|
||||
meta_screen_workspace_popup_get_selected (MetaScreen *screen)
|
||||
{
|
||||
g_return_val_if_fail (screen->ws_popup != NULL, NULL);
|
||||
|
||||
return (MetaWorkspace *) meta_ui_tab_popup_get_selected (screen->ws_popup);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_workspace_popup_destroy (MetaScreen *screen)
|
||||
{
|
||||
if (screen->ws_popup)
|
||||
{
|
||||
meta_ui_tab_popup_free (screen->ws_popup);
|
||||
screen->ws_popup = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_screen_tile_preview_update_timeout (gpointer data)
|
||||
meta_screen_update_tile_preview_timeout (gpointer data)
|
||||
{
|
||||
MetaScreen *screen = data;
|
||||
MetaWindow *window = screen->display->grab_window;
|
||||
@@ -1686,22 +1432,6 @@ meta_screen_tile_preview_update_timeout (gpointer data)
|
||||
|
||||
screen->tile_preview_timeout_id = 0;
|
||||
|
||||
if (!screen->tile_preview)
|
||||
{
|
||||
Window xwindow;
|
||||
gulong create_serial;
|
||||
MetaStackWindow stack_window;
|
||||
|
||||
screen->tile_preview = meta_tile_preview_new (screen->number);
|
||||
xwindow = meta_tile_preview_get_xwindow (screen->tile_preview,
|
||||
&create_serial);
|
||||
stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
|
||||
stack_window.x11.xwindow = xwindow;
|
||||
meta_stack_tracker_record_add (screen->stack_tracker,
|
||||
&stack_window,
|
||||
create_serial);
|
||||
}
|
||||
|
||||
if (window)
|
||||
{
|
||||
switch (window->tile_mode)
|
||||
@@ -1726,12 +1456,16 @@ meta_screen_tile_preview_update_timeout (gpointer data)
|
||||
if (needs_preview)
|
||||
{
|
||||
MetaRectangle tile_rect;
|
||||
int monitor;
|
||||
|
||||
monitor = meta_window_get_current_tile_monitor_number (window);
|
||||
meta_window_get_current_tile_area (window, &tile_rect);
|
||||
meta_tile_preview_show (screen->tile_preview, &tile_rect);
|
||||
meta_compositor_show_tile_preview (screen->display->compositor,
|
||||
screen, window, &tile_rect, monitor);
|
||||
}
|
||||
else
|
||||
meta_tile_preview_hide (screen->tile_preview);
|
||||
meta_compositor_hide_tile_preview (screen->display->compositor,
|
||||
screen);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@@ -1739,7 +1473,7 @@ meta_screen_tile_preview_update_timeout (gpointer data)
|
||||
#define TILE_PREVIEW_TIMEOUT_MS 200
|
||||
|
||||
void
|
||||
meta_screen_tile_preview_update (MetaScreen *screen,
|
||||
meta_screen_update_tile_preview (MetaScreen *screen,
|
||||
gboolean delay)
|
||||
{
|
||||
if (delay)
|
||||
@@ -1749,7 +1483,7 @@ meta_screen_tile_preview_update (MetaScreen *screen,
|
||||
|
||||
screen->tile_preview_timeout_id =
|
||||
g_timeout_add (TILE_PREVIEW_TIMEOUT_MS,
|
||||
meta_screen_tile_preview_update_timeout,
|
||||
meta_screen_update_tile_preview_timeout,
|
||||
screen);
|
||||
}
|
||||
else
|
||||
@@ -1757,18 +1491,18 @@ meta_screen_tile_preview_update (MetaScreen *screen,
|
||||
if (screen->tile_preview_timeout_id > 0)
|
||||
g_source_remove (screen->tile_preview_timeout_id);
|
||||
|
||||
meta_screen_tile_preview_update_timeout ((gpointer)screen);
|
||||
meta_screen_update_tile_preview_timeout ((gpointer)screen);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_tile_preview_hide (MetaScreen *screen)
|
||||
meta_screen_hide_tile_preview (MetaScreen *screen)
|
||||
{
|
||||
if (screen->tile_preview_timeout_id > 0)
|
||||
g_source_remove (screen->tile_preview_timeout_id);
|
||||
|
||||
if (screen->tile_preview)
|
||||
meta_tile_preview_hide (screen->tile_preview);
|
||||
meta_compositor_hide_tile_preview (screen->display->compositor,
|
||||
screen);
|
||||
}
|
||||
|
||||
MetaWindow*
|
||||
@@ -1776,38 +1510,19 @@ meta_screen_get_mouse_window (MetaScreen *screen,
|
||||
MetaWindow *not_this_one)
|
||||
{
|
||||
MetaWindow *window;
|
||||
Window root_return, child_return;
|
||||
double root_x_return, root_y_return;
|
||||
double win_x_return, win_y_return;
|
||||
XIButtonState buttons;
|
||||
XIModifierState mods;
|
||||
XIGroupState group;
|
||||
int x, y;
|
||||
|
||||
if (not_this_one)
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Focusing mouse window excluding %s\n", not_this_one->desc);
|
||||
|
||||
meta_error_trap_push (screen->display);
|
||||
XIQueryPointer (screen->display->xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
screen->xroot,
|
||||
&root_return,
|
||||
&child_return,
|
||||
&root_x_return,
|
||||
&root_y_return,
|
||||
&win_x_return,
|
||||
&win_y_return,
|
||||
&buttons,
|
||||
&mods,
|
||||
&group);
|
||||
meta_error_trap_pop (screen->display);
|
||||
free (buttons.mask);
|
||||
meta_cursor_tracker_get_pointer (screen->cursor_tracker,
|
||||
&x, &y, NULL);
|
||||
|
||||
window = meta_stack_get_default_focus_window_at_point (screen->stack,
|
||||
screen->active_workspace,
|
||||
not_this_one,
|
||||
root_x_return,
|
||||
root_y_return);
|
||||
x, y);
|
||||
|
||||
return window;
|
||||
}
|
||||
@@ -2089,28 +1804,11 @@ meta_screen_get_current_monitor (MetaScreen *screen)
|
||||
|
||||
if (screen->display->monitor_cache_invalidated)
|
||||
{
|
||||
Window root_return, child_return;
|
||||
double win_x_return, win_y_return;
|
||||
double root_x_return, root_y_return;
|
||||
XIButtonState buttons;
|
||||
XIModifierState mods;
|
||||
XIGroupState group;
|
||||
int x, y;
|
||||
|
||||
XIQueryPointer (screen->display->xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
screen->xroot,
|
||||
&root_return,
|
||||
&child_return,
|
||||
&root_x_return,
|
||||
&root_y_return,
|
||||
&win_x_return,
|
||||
&win_y_return,
|
||||
&buttons,
|
||||
&mods,
|
||||
&group);
|
||||
free (buttons.mask);
|
||||
|
||||
meta_screen_get_current_monitor_for_pos (screen, root_x_return, root_y_return);
|
||||
meta_cursor_tracker_get_pointer (screen->cursor_tracker,
|
||||
&x, &y, NULL);
|
||||
meta_screen_get_current_monitor_for_pos (screen, x, y);
|
||||
}
|
||||
|
||||
return screen->last_monitor_index;
|
||||
@@ -2821,10 +2519,9 @@ on_monitors_changed (MetaMonitorManager *manager,
|
||||
&changes);
|
||||
}
|
||||
|
||||
if (screen->display->compositor)
|
||||
meta_compositor_sync_screen_size (screen->display->compositor,
|
||||
screen,
|
||||
screen->rect.width, screen->rect.height);
|
||||
meta_compositor_sync_screen_size (screen->display->compositor,
|
||||
screen,
|
||||
screen->rect.width, screen->rect.height);
|
||||
|
||||
/* Queue a resize on all the windows */
|
||||
meta_screen_foreach_window (screen, meta_screen_resize_func, 0);
|
||||
|
@@ -1041,7 +1041,7 @@ stack_tracker_event_received (MetaStackTracker *tracker,
|
||||
|
||||
if (op->any.serial < tracker->xserver_serial)
|
||||
{
|
||||
g_warning ("Spurious X event received affecting stack; doing full re-query");
|
||||
/* g_warning ("Spurious X event received affecting stack; doing full re-query"); */
|
||||
resync_verified_stack_with_xserver_stack (tracker);
|
||||
meta_stack_tracker_dump (tracker);
|
||||
return;
|
||||
@@ -1245,10 +1245,9 @@ meta_stack_tracker_sync_stack (MetaStackTracker *tracker)
|
||||
meta_windows = g_list_prepend (meta_windows, window->wayland.meta_window);
|
||||
}
|
||||
|
||||
if (tracker->screen->display->compositor)
|
||||
meta_compositor_sync_stack (tracker->screen->display->compositor,
|
||||
tracker->screen,
|
||||
meta_windows);
|
||||
meta_compositor_sync_stack (tracker->screen->display->compositor,
|
||||
tracker->screen,
|
||||
meta_windows);
|
||||
g_list_free (meta_windows);
|
||||
|
||||
meta_screen_restacked (tracker->screen);
|
||||
|
@@ -36,6 +36,8 @@
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#include "x11/group-private.h"
|
||||
|
||||
#define WINDOW_HAS_TRANSIENT_TYPE(w) \
|
||||
(w->type == META_WINDOW_DIALOG || \
|
||||
w->type == META_WINDOW_MODAL_DIALOG || \
|
||||
@@ -1705,8 +1707,8 @@ get_default_focus_window (MetaStack *stack,
|
||||
MetaWindow *topmost_in_group;
|
||||
MetaWindow *topmost_overall;
|
||||
MetaGroup *not_this_one_group;
|
||||
GList *link;
|
||||
|
||||
GList *l;
|
||||
|
||||
transient_parent = NULL;
|
||||
topmost_in_group = NULL;
|
||||
topmost_overall = NULL;
|
||||
@@ -1718,49 +1720,49 @@ get_default_focus_window (MetaStack *stack,
|
||||
stack_ensure_sorted (stack);
|
||||
|
||||
/* top of this layer is at the front of the list */
|
||||
link = stack->sorted;
|
||||
|
||||
while (link)
|
||||
for (l = stack->sorted; l != NULL; l = l->next)
|
||||
{
|
||||
MetaWindow *window = link->data;
|
||||
MetaWindow *window = l->data;
|
||||
|
||||
if (window &&
|
||||
window != not_this_one &&
|
||||
(window->unmaps_pending == 0) &&
|
||||
!window->minimized &&
|
||||
(window->input || window->take_focus) &&
|
||||
(workspace == NULL ||
|
||||
meta_window_located_on_workspace (window, workspace)))
|
||||
if (!window)
|
||||
continue;
|
||||
|
||||
if (window == not_this_one)
|
||||
continue;
|
||||
|
||||
if (window->unmaps_pending > 0)
|
||||
continue;
|
||||
|
||||
if (window->minimized)
|
||||
continue;
|
||||
|
||||
if (!(window->input || window->take_focus))
|
||||
continue;
|
||||
|
||||
if (workspace != NULL && !meta_window_located_on_workspace (window, workspace))
|
||||
continue;
|
||||
|
||||
if (must_be_at_point && !window_contains_point (window, root_x, root_y))
|
||||
continue;
|
||||
|
||||
if (not_this_one != NULL)
|
||||
{
|
||||
if (not_this_one != NULL)
|
||||
{
|
||||
if (transient_parent == NULL &&
|
||||
not_this_one->xtransient_for != None &&
|
||||
not_this_one->xtransient_for == window->xwindow &&
|
||||
(!must_be_at_point ||
|
||||
window_contains_point (window, root_x, root_y)))
|
||||
transient_parent = window;
|
||||
if (transient_parent == NULL &&
|
||||
meta_window_get_transient_for (not_this_one) == window)
|
||||
transient_parent = window;
|
||||
|
||||
if (topmost_in_group == NULL &&
|
||||
not_this_one_group != NULL &&
|
||||
not_this_one_group == meta_window_get_group (window) &&
|
||||
(!must_be_at_point ||
|
||||
window_contains_point (window, root_x, root_y)))
|
||||
topmost_in_group = window;
|
||||
}
|
||||
|
||||
if (topmost_overall == NULL &&
|
||||
window->type != META_WINDOW_DOCK &&
|
||||
(!must_be_at_point ||
|
||||
window_contains_point (window, root_x, root_y)))
|
||||
topmost_overall = window;
|
||||
|
||||
/* We could try to bail out early here for efficiency in
|
||||
* some cases, but it's just not worth the code.
|
||||
*/
|
||||
if (topmost_in_group == NULL &&
|
||||
not_this_one_group != NULL &&
|
||||
not_this_one_group == meta_window_get_group (window))
|
||||
topmost_in_group = window;
|
||||
}
|
||||
|
||||
link = link->next;
|
||||
if (topmost_overall == NULL && window->type != META_WINDOW_DOCK)
|
||||
topmost_overall = window;
|
||||
|
||||
/* We could try to bail out early here for efficiency in
|
||||
* some cases, but it's just not worth the code.
|
||||
*/
|
||||
}
|
||||
|
||||
if (transient_parent)
|
||||
|
@@ -38,12 +38,15 @@
|
||||
#include "screen-private.h"
|
||||
#include <meta/util.h>
|
||||
#include "stack.h"
|
||||
#include "iconcache.h"
|
||||
#include <X11/Xutil.h>
|
||||
#include <cairo.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <clutter/clutter.h>
|
||||
#include "meta-wayland-types.h"
|
||||
|
||||
#include "x11/iconcache.h"
|
||||
#include "x11/group-private.h"
|
||||
|
||||
#include "wayland/meta-wayland-types.h"
|
||||
|
||||
typedef struct _MetaWindowQueue MetaWindowQueue;
|
||||
|
||||
@@ -62,13 +65,28 @@ typedef enum {
|
||||
|
||||
#define NUMBER_OF_QUEUES 3
|
||||
|
||||
|
||||
typedef enum {
|
||||
_NET_WM_BYPASS_COMPOSITOR_HINT_AUTO = 0,
|
||||
_NET_WM_BYPASS_COMPOSITOR_HINT_ON = 1,
|
||||
_NET_WM_BYPASS_COMPOSITOR_HINT_OFF = 2,
|
||||
} MetaBypassCompositorHintValue;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
META_IS_CONFIGURE_REQUEST = 1 << 0,
|
||||
META_DO_GRAVITY_ADJUST = 1 << 1,
|
||||
META_IS_USER_ACTION = 1 << 2,
|
||||
META_IS_MOVE_ACTION = 1 << 3,
|
||||
META_IS_RESIZE_ACTION = 1 << 4,
|
||||
META_IS_WAYLAND_RESIZE = 1 << 5
|
||||
} MetaMoveResizeFlags;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
META_MOVE_RESIZE_RESULT_MOVED = 1 << 0,
|
||||
META_MOVE_RESIZE_RESULT_RESIZED = 1 << 1,
|
||||
META_MOVE_RESIZE_RESULT_FRAME_SHAPE_CHANGED = 1 << 2,
|
||||
} MetaMoveResizeResultFlags;
|
||||
|
||||
struct _MetaWindow
|
||||
{
|
||||
@@ -79,27 +97,22 @@ struct _MetaWindow
|
||||
const MetaMonitorInfo *monitor;
|
||||
MetaWorkspace *workspace;
|
||||
MetaWindowClientType client_type;
|
||||
#ifdef HAVE_WAYLAND
|
||||
MetaWaylandSurface *surface;
|
||||
#endif
|
||||
Window xwindow;
|
||||
/* may be NULL! not all windows get decorated */
|
||||
MetaFrame *frame;
|
||||
int depth;
|
||||
Visual *xvisual;
|
||||
Colormap colormap;
|
||||
char *desc; /* used in debug spew */
|
||||
char *title;
|
||||
|
||||
char *icon_name;
|
||||
GdkPixbuf *icon;
|
||||
GdkPixbuf *mini_icon;
|
||||
MetaIconCache icon_cache;
|
||||
Pixmap wm_hints_pixmap;
|
||||
Pixmap wm_hints_mask;
|
||||
|
||||
|
||||
MetaWindowType type;
|
||||
Atom type_atom;
|
||||
|
||||
/* NOTE these five are not in UTF-8, we just treat them as random
|
||||
* binary data
|
||||
@@ -161,8 +174,8 @@ struct _MetaWindow
|
||||
/* Whether we're fullscreen */
|
||||
guint fullscreen : 1;
|
||||
|
||||
/* Whether the urgent flag of WM_HINTS is set */
|
||||
guint wm_hints_urgent : 1;
|
||||
/* Whether the window is marked as urgent */
|
||||
guint urgent : 1;
|
||||
|
||||
/* Whether we have to fullscreen after placement */
|
||||
guint fullscreen_after_placement : 1;
|
||||
@@ -240,7 +253,7 @@ struct _MetaWindow
|
||||
/* These are the flags from WM_PROTOCOLS */
|
||||
guint take_focus : 1;
|
||||
guint delete_window : 1;
|
||||
guint net_wm_ping : 1;
|
||||
guint can_ping : 1;
|
||||
/* Globally active / No input */
|
||||
guint input : 1;
|
||||
|
||||
@@ -264,13 +277,6 @@ struct _MetaWindow
|
||||
guint has_move_func : 1;
|
||||
guint has_resize_func : 1;
|
||||
guint has_fullscreen_func : 1;
|
||||
|
||||
/* Weird "_NET_WM_STATE_MODAL" flag */
|
||||
guint wm_state_modal : 1;
|
||||
|
||||
/* TRUE if the client forced these on */
|
||||
guint wm_state_skip_taskbar : 1;
|
||||
guint wm_state_skip_pager : 1;
|
||||
|
||||
/* Computed whether to skip taskbar or not */
|
||||
guint skip_taskbar : 1;
|
||||
@@ -324,15 +330,6 @@ struct _MetaWindow
|
||||
|
||||
/* Transient parent is a root window */
|
||||
guint transient_parent_is_root_window : 1;
|
||||
|
||||
/* Info on which props we got our attributes from */
|
||||
guint using_net_wm_name : 1; /* vs. plain wm_name */
|
||||
guint using_net_wm_visible_name : 1; /* tracked so we can clear it */
|
||||
guint using_net_wm_icon_name : 1; /* vs. plain wm_icon_name */
|
||||
guint using_net_wm_visible_icon_name : 1; /* tracked so we can clear it */
|
||||
|
||||
/* icon props have changed */
|
||||
guint need_reread_icon : 1;
|
||||
|
||||
/* if TRUE, window was maximized at start of current grab op */
|
||||
guint shaken_loose : 1;
|
||||
@@ -433,8 +430,6 @@ struct _MetaWindow
|
||||
* gives the position and size of the client window (i.e. ignoring
|
||||
* the frame).
|
||||
*
|
||||
* Position valid if user_has_moved, size valid if user_has_resized
|
||||
*
|
||||
* Position always in root coords, unlike window->rect.
|
||||
*/
|
||||
MetaRectangle user_rect;
|
||||
@@ -467,18 +462,30 @@ struct _MetaWindow
|
||||
|
||||
/* Bypass compositor hints */
|
||||
guint bypass_compositor;
|
||||
|
||||
GSList *pending_pings;
|
||||
};
|
||||
|
||||
struct _MetaWindowClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (*workspace_changed) (MetaWindow *window, int old_workspace);
|
||||
void (*focus) (MetaWindow *window);
|
||||
void (*raised) (MetaWindow *window);
|
||||
void (*unmanaged) (MetaWindow *window);
|
||||
void (*manage) (MetaWindow *window);
|
||||
void (*unmanage) (MetaWindow *window);
|
||||
void (*ping) (MetaWindow *window,
|
||||
guint32 serial);
|
||||
void (*delete) (MetaWindow *window,
|
||||
guint32 timestamp);
|
||||
void (*kill) (MetaWindow *window);
|
||||
void (*focus) (MetaWindow *window,
|
||||
guint32 timestamp);
|
||||
void (*move_resize_internal) (MetaWindow *window,
|
||||
int gravity,
|
||||
MetaRectangle requested_rect,
|
||||
MetaRectangle constrained_rect,
|
||||
MetaMoveResizeFlags flags,
|
||||
MetaMoveResizeResultFlags *result);
|
||||
void (*get_default_skip_hints) (MetaWindow *window,
|
||||
gboolean *skip_taskbar_out,
|
||||
gboolean *skip_pager_out);
|
||||
};
|
||||
|
||||
/* These differ from window->has_foo_func in that they consider
|
||||
@@ -571,9 +578,6 @@ void meta_window_change_workspace (MetaWindow *window,
|
||||
/* Return whether the window should be currently mapped */
|
||||
gboolean meta_window_should_be_showing (MetaWindow *window);
|
||||
|
||||
/* See warning in window.c about this function */
|
||||
gboolean __window_is_terminal (MetaWindow *window);
|
||||
|
||||
void meta_window_update_struts (MetaWindow *window);
|
||||
|
||||
/* this gets root coords */
|
||||
@@ -607,12 +611,6 @@ void meta_window_get_geometry (MetaWindow *window,
|
||||
|
||||
void meta_window_update_unfocused_button_grabs (MetaWindow *window);
|
||||
|
||||
/* Sends a client message */
|
||||
void meta_window_send_icccm_message (MetaWindow *window,
|
||||
Atom atom,
|
||||
guint32 timestamp);
|
||||
|
||||
|
||||
void meta_window_move_resize_request(MetaWindow *window,
|
||||
guint value_mask,
|
||||
int gravity,
|
||||
@@ -638,12 +636,6 @@ void meta_window_show_menu (MetaWindow *window,
|
||||
int button,
|
||||
guint32 timestamp);
|
||||
|
||||
gboolean meta_window_titlebar_is_onscreen (MetaWindow *window);
|
||||
void meta_window_shove_titlebar_onscreen (MetaWindow *window);
|
||||
|
||||
void meta_window_set_gravity (MetaWindow *window,
|
||||
int gravity);
|
||||
|
||||
#ifdef HAVE_XSYNC
|
||||
void meta_window_update_sync_request_counter (MetaWindow *window,
|
||||
gint64 new_counter_value);
|
||||
@@ -656,6 +648,7 @@ void meta_window_handle_mouse_grab_op_xevent (MetaWindow *window,
|
||||
|
||||
GList* meta_window_get_workspaces (MetaWindow *window);
|
||||
|
||||
int meta_window_get_current_tile_monitor_number (MetaWindow *window);
|
||||
void meta_window_get_current_tile_area (MetaWindow *window,
|
||||
MetaRectangle *tile_area);
|
||||
|
||||
@@ -687,9 +680,8 @@ void meta_window_update_layer (MetaWindow *window);
|
||||
|
||||
void meta_window_recalc_features (MetaWindow *window);
|
||||
|
||||
/* recalc_window_type is x11 only, wayland does its thing and then calls type_changed */
|
||||
void meta_window_recalc_window_type (MetaWindow *window);
|
||||
void meta_window_type_changed (MetaWindow *window);
|
||||
void meta_window_set_type (MetaWindow *window,
|
||||
MetaWindowType type);
|
||||
|
||||
void meta_window_frame_size_changed (MetaWindow *window);
|
||||
|
||||
@@ -733,6 +725,9 @@ void meta_window_set_transient_for (MetaWindow *window,
|
||||
void meta_window_set_opacity (MetaWindow *window,
|
||||
guint opacity);
|
||||
|
||||
void meta_window_set_custom_frame_extents (MetaWindow *window,
|
||||
GtkBorder *extents);
|
||||
|
||||
void meta_window_handle_enter (MetaWindow *window,
|
||||
guint32 timestamp,
|
||||
guint root_x,
|
||||
@@ -741,22 +736,26 @@ void meta_window_handle_enter (MetaWindow *window,
|
||||
void meta_window_set_surface_mapped (MetaWindow *window,
|
||||
gboolean surface_mapped);
|
||||
|
||||
typedef void (* MetaWindowPingFunc) (MetaWindow *window,
|
||||
guint32 timestamp,
|
||||
gpointer user_data);
|
||||
|
||||
void meta_window_ping (MetaWindow *window,
|
||||
guint32 timestamp,
|
||||
MetaWindowPingFunc ping_reply_func,
|
||||
MetaWindowPingFunc ping_timeout_func,
|
||||
void *user_data);
|
||||
void meta_window_pong (MetaWindow *window,
|
||||
guint32 timestamp);
|
||||
Window meta_window_get_toplevel_xwindow (MetaWindow *window);
|
||||
|
||||
void meta_window_get_client_area_rect (const MetaWindow *window,
|
||||
cairo_rectangle_int_t *rect);
|
||||
|
||||
void meta_window_activate_full (MetaWindow *window,
|
||||
guint32 timestamp,
|
||||
MetaClientType source_indication,
|
||||
MetaWorkspace *workspace);
|
||||
|
||||
gboolean meta_window_is_client_decorated (MetaWindow *window);
|
||||
|
||||
void meta_window_update_monitor (MetaWindow *window);
|
||||
|
||||
void meta_window_set_urgent (MetaWindow *window,
|
||||
gboolean urgent);
|
||||
|
||||
void meta_window_update_resize (MetaWindow *window,
|
||||
gboolean snap,
|
||||
int x, int y,
|
||||
gboolean force);
|
||||
|
||||
#endif
|
||||
|
2488
src/core/window.c
2488
src/core/window.c
File diff suppressed because it is too large
Load Diff
@@ -91,7 +91,6 @@ item(hotplug_mode_update)
|
||||
item(_NET_WM_SYNC_REQUEST)
|
||||
item(_NET_WM_SYNC_REQUEST_COUNTER)
|
||||
item(_NET_WM_VISIBLE_NAME)
|
||||
item(_NET_WM_VISIBLE_ICON_NAME)
|
||||
item(_NET_SUPPORTING_WM_CHECK)
|
||||
|
||||
/* But I suppose it's quite reasonable not to advertise using
|
||||
@@ -132,7 +131,6 @@ item(_NET_CLIENT_LIST)
|
||||
item(_NET_CLIENT_LIST_STACKING)
|
||||
item(_NET_WM_STATE_SKIP_TASKBAR)
|
||||
item(_NET_WM_STATE_SKIP_PAGER)
|
||||
item(_NET_WM_ICON_NAME)
|
||||
item(_NET_WM_ICON)
|
||||
item(_NET_WM_ICON_GEOMETRY)
|
||||
item(_NET_WM_MOVERESIZE)
|
||||
|
@@ -163,13 +163,6 @@ typedef void (* MetaWindowMenuFunc) (MetaWindowMenu *menu,
|
||||
* @META_GRAB_OP_KEYBOARD_RESIZING_NE: Resizing NE with keyboard
|
||||
* @META_GRAB_OP_KEYBOARD_RESIZING_SW: Resizing SW with keyboard
|
||||
* @META_GRAB_OP_KEYBOARD_RESIZING_NW: Resizing NS with keyboard
|
||||
* @META_GRAB_OP_KEYBOARD_TABBING_NORMAL: Tabbing
|
||||
* @META_GRAB_OP_KEYBOARD_TABBING_DOCK: Tabbing through docks
|
||||
* @META_GRAB_OP_KEYBOARD_ESCAPING_NORMAL: Escaping
|
||||
* @META_GRAB_OP_KEYBOARD_ESCAPING_DOCK: Escaping through docks
|
||||
* @META_GRAB_OP_KEYBOARD_ESCAPING_GROUP: Escaping through groups
|
||||
* @META_GRAB_OP_KEYBOARD_TABBING_GROUP: Tabbing through groups
|
||||
* @META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING: Switch to another workspace
|
||||
* @META_GRAB_OP_CLICKING_MINIMIZE: Clicked minimize button
|
||||
* @META_GRAB_OP_CLICKING_MAXIMIZE: Clicked maximize button
|
||||
* @META_GRAB_OP_CLICKING_UNMAXIMIZE: Clicked unmaximize button
|
||||
@@ -214,21 +207,6 @@ typedef enum
|
||||
META_GRAB_OP_KEYBOARD_RESIZING_SW,
|
||||
META_GRAB_OP_KEYBOARD_RESIZING_NW,
|
||||
|
||||
/* Alt+Tab */
|
||||
META_GRAB_OP_KEYBOARD_TABBING_NORMAL,
|
||||
META_GRAB_OP_KEYBOARD_TABBING_DOCK,
|
||||
|
||||
/* Alt+Esc */
|
||||
META_GRAB_OP_KEYBOARD_ESCAPING_NORMAL,
|
||||
META_GRAB_OP_KEYBOARD_ESCAPING_DOCK,
|
||||
|
||||
META_GRAB_OP_KEYBOARD_ESCAPING_GROUP,
|
||||
|
||||
/* Alt+F6 */
|
||||
META_GRAB_OP_KEYBOARD_TABBING_GROUP,
|
||||
|
||||
META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING,
|
||||
|
||||
/* Frame button ops */
|
||||
META_GRAB_OP_CLICKING_MINIMIZE,
|
||||
META_GRAB_OP_CLICKING_MAXIMIZE,
|
||||
@@ -243,7 +221,10 @@ typedef enum
|
||||
META_GRAB_OP_CLICKING_UNSTICK,
|
||||
|
||||
/* Special grab op when the compositor asked for a grab */
|
||||
META_GRAB_OP_COMPOSITOR
|
||||
META_GRAB_OP_COMPOSITOR,
|
||||
|
||||
/* For when a client takes a popup grab */
|
||||
META_GRAB_OP_WAYLAND_CLIENT,
|
||||
} MetaGrabOp;
|
||||
|
||||
/**
|
||||
|
@@ -66,6 +66,8 @@ void meta_compositor_window_shape_changed (MetaCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
void meta_compositor_window_opacity_changed (MetaCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
void meta_compositor_window_surface_changed (MetaCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
|
||||
gboolean meta_compositor_process_event (MetaCompositor *compositor,
|
||||
XEvent *event,
|
||||
@@ -75,11 +77,10 @@ gboolean meta_compositor_filter_keybinding (MetaCompositor *compositor,
|
||||
MetaScreen *screen,
|
||||
MetaKeyBinding *binding);
|
||||
|
||||
void meta_compositor_add_window (MetaCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
void meta_compositor_remove_window (MetaCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
|
||||
void meta_compositor_add_window (MetaCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
void meta_compositor_remove_window (MetaCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
void meta_compositor_show_window (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
MetaCompEffect effect);
|
||||
@@ -101,10 +102,6 @@ void meta_compositor_unmaximize_window (MetaCompositor *compositor,
|
||||
MetaRectangle *old_rect,
|
||||
MetaRectangle *new_rect);
|
||||
|
||||
void meta_compositor_window_mapped (MetaCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
void meta_compositor_window_unmapped (MetaCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
void meta_compositor_sync_window_geometry (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
gboolean did_placement);
|
||||
@@ -126,4 +123,12 @@ void meta_compositor_sync_screen_size (MetaCompositor *compositor,
|
||||
void meta_compositor_flash_screen (MetaCompositor *compositor,
|
||||
MetaScreen *screen);
|
||||
|
||||
void meta_compositor_show_tile_preview (MetaCompositor *compositor,
|
||||
MetaScreen *screen,
|
||||
MetaWindow *window,
|
||||
MetaRectangle *tile_rect,
|
||||
int tile_monitor_number);
|
||||
void meta_compositor_hide_tile_preview (MetaCompositor *compositor,
|
||||
MetaScreen *screen);
|
||||
|
||||
#endif /* META_COMPOSITOR_H */
|
||||
|
@@ -163,10 +163,6 @@ void meta_display_set_input_focus_window (MetaDisplay *display,
|
||||
gboolean focus_frame,
|
||||
guint32 timestamp);
|
||||
|
||||
void meta_display_request_take_focus (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
guint32 timestamp);
|
||||
|
||||
/* meta_display_focus_the_no_focus_window is called when the
|
||||
* designated no_focus_window should be focused, but is otherwise the
|
||||
* same as meta_display_set_input_focus_window
|
||||
@@ -178,8 +174,6 @@ void meta_display_focus_the_no_focus_window (MetaDisplay *display,
|
||||
GSList *meta_display_sort_windows_by_stacking (MetaDisplay *display,
|
||||
GSList *windows);
|
||||
|
||||
Window meta_display_get_leader_window (MetaDisplay *display);
|
||||
|
||||
void meta_display_add_ignored_crossing_serial (MetaDisplay *display,
|
||||
unsigned long serial);
|
||||
|
||||
|
@@ -28,6 +28,7 @@ GOptionContext *meta_get_option_context (void);
|
||||
void meta_init (void);
|
||||
int meta_run (void);
|
||||
void meta_register_with_session (void);
|
||||
gboolean meta_activate_session (void);
|
||||
gboolean meta_get_replace_current_wm (void); /* Actually defined in util.c */
|
||||
|
||||
void meta_set_wm_name (const char *wm_name);
|
||||
|
@@ -158,6 +158,11 @@ struct _MetaPluginClass
|
||||
gint to,
|
||||
MetaMotionDirection direction);
|
||||
|
||||
void (*show_tile_preview) (MetaPlugin *plugin,
|
||||
MetaWindow *window,
|
||||
MetaRectangle *tile_rect,
|
||||
int tile_monitor_number);
|
||||
void (*hide_tile_preview) (MetaPlugin *plugin);
|
||||
|
||||
/**
|
||||
* MetaPluginClass::kill_window_effects:
|
||||
@@ -249,9 +254,6 @@ struct _MetaPluginInfo
|
||||
|
||||
GType meta_plugin_get_type (void);
|
||||
|
||||
gboolean meta_plugin_running (MetaPlugin *plugin);
|
||||
gboolean meta_plugin_debug_mode (MetaPlugin *plugin);
|
||||
|
||||
const MetaPluginInfo * meta_plugin_get_info (MetaPlugin *plugin);
|
||||
|
||||
/**
|
||||
@@ -403,8 +405,7 @@ meta_plugin_end_modal (MetaPlugin *plugin,
|
||||
|
||||
MetaScreen *meta_plugin_get_screen (MetaPlugin *plugin);
|
||||
|
||||
void
|
||||
_meta_plugin_effect_started (MetaPlugin *plugin);
|
||||
void _meta_plugin_set_screen (MetaPlugin *plugin, MetaScreen *screen);
|
||||
|
||||
/* XXX: Putting this in here so it's in the public header. */
|
||||
void meta_plugin_manager_set_plugin_type (GType gtype);
|
||||
|
@@ -69,16 +69,12 @@ gboolean meta_shaped_texture_update_area (MetaShapedTexture *stex,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
cairo_region_t *unobscured_region);
|
||||
int height);
|
||||
|
||||
CoglTexture * meta_shaped_texture_get_texture (MetaShapedTexture *stex);
|
||||
|
||||
void meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex,
|
||||
CoglTexture *mask_texture);
|
||||
void meta_shaped_texture_set_input_shape_region (MetaShapedTexture *stex,
|
||||
cairo_region_t *shape_region);
|
||||
|
||||
void meta_shaped_texture_set_opaque_region (MetaShapedTexture *stex,
|
||||
cairo_region_t *opaque_region);
|
||||
|
||||
|
@@ -62,7 +62,6 @@
|
||||
* @META_PREF_EDGE_TILING: edge tiling
|
||||
* @META_PREF_FORCE_FULLSCREEN: force fullscreen
|
||||
* @META_PREF_WORKSPACES_ONLY_ON_PRIMARY: workspaces only on primary
|
||||
* @META_PREF_NO_TAB_POPUP: no tab popup
|
||||
* @META_PREF_DRAGGABLE_BORDER_WIDTH: draggable border width
|
||||
* @META_PREF_AUTO_MAXIMIZE: auto-maximize
|
||||
*/
|
||||
@@ -100,7 +99,6 @@ typedef enum
|
||||
META_PREF_EDGE_TILING,
|
||||
META_PREF_FORCE_FULLSCREEN,
|
||||
META_PREF_WORKSPACES_ONLY_ON_PRIMARY,
|
||||
META_PREF_NO_TAB_POPUP,
|
||||
META_PREF_DRAGGABLE_BORDER_WIDTH,
|
||||
META_PREF_AUTO_MAXIMIZE
|
||||
} MetaPreference;
|
||||
@@ -163,9 +161,6 @@ void meta_prefs_set_force_fullscreen (gboolean whether);
|
||||
|
||||
gboolean meta_prefs_get_workspaces_only_on_primary (void);
|
||||
|
||||
gboolean meta_prefs_get_no_tab_popup (void);
|
||||
void meta_prefs_set_no_tab_popup (gboolean whether);
|
||||
|
||||
int meta_prefs_get_draggable_border_width (void);
|
||||
|
||||
gboolean meta_prefs_get_ignore_request_hide_titlebar (void);
|
||||
@@ -204,8 +199,6 @@ void meta_prefs_set_ignore_request_hide_titlebar (gboolean whether);
|
||||
* @META_KEYBINDING_ACTION_CYCLE_WINDOWS_BACKWARD: FILLME
|
||||
* @META_KEYBINDING_ACTION_CYCLE_PANELS: FILLME
|
||||
* @META_KEYBINDING_ACTION_CYCLE_PANELS_BACKWARD: FILLME
|
||||
* @META_KEYBINDING_ACTION_TAB_POPUP_SELECT: FILLME
|
||||
* @META_KEYBINDING_ACTION_TAB_POPUP_CANCEL: FILLME
|
||||
* @META_KEYBINDING_ACTION_SHOW_DESKTOP: FILLME
|
||||
* @META_KEYBINDING_ACTION_PANEL_MAIN_MENU: FILLME
|
||||
* @META_KEYBINDING_ACTION_PANEL_RUN_DIALOG: FILLME
|
||||
@@ -301,8 +294,6 @@ typedef enum _MetaKeyBindingAction
|
||||
META_KEYBINDING_ACTION_CYCLE_WINDOWS_BACKWARD,
|
||||
META_KEYBINDING_ACTION_CYCLE_PANELS,
|
||||
META_KEYBINDING_ACTION_CYCLE_PANELS_BACKWARD,
|
||||
META_KEYBINDING_ACTION_TAB_POPUP_SELECT,
|
||||
META_KEYBINDING_ACTION_TAB_POPUP_CANCEL,
|
||||
META_KEYBINDING_ACTION_SHOW_DESKTOP,
|
||||
META_KEYBINDING_ACTION_PANEL_MAIN_MENU,
|
||||
META_KEYBINDING_ACTION_PANEL_RUN_DIALOG,
|
||||
@@ -380,20 +371,6 @@ typedef enum
|
||||
META_KEY_BINDING_IS_REVERSED = 1 << 3
|
||||
} MetaKeyBindingFlags;
|
||||
|
||||
/**
|
||||
* MetaKeyCombo:
|
||||
* @keysym: keysym
|
||||
* @keycode: keycode
|
||||
* @modifiers: modifiers
|
||||
*/
|
||||
typedef struct _MetaKeyCombo MetaKeyCombo;
|
||||
struct _MetaKeyCombo
|
||||
{
|
||||
unsigned int keysym;
|
||||
unsigned int keycode;
|
||||
MetaVirtualModifier modifiers;
|
||||
};
|
||||
|
||||
/**
|
||||
* MetaKeyHandlerFunc:
|
||||
* @display: a #MetaDisplay
|
||||
@@ -411,45 +388,14 @@ typedef void (* MetaKeyHandlerFunc) (MetaDisplay *display,
|
||||
MetaKeyBinding *binding,
|
||||
gpointer user_data);
|
||||
|
||||
typedef struct _MetaKeyHandler MetaKeyHandler;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *name;
|
||||
GSettings *settings;
|
||||
|
||||
MetaKeyBindingAction action;
|
||||
|
||||
/*
|
||||
* A list of MetaKeyCombos. Each of them is bound to
|
||||
* this keypref. If one has keysym==modifiers==0, it is
|
||||
* ignored.
|
||||
*/
|
||||
GSList *bindings;
|
||||
|
||||
/* for keybindings that can have shift or not like Alt+Tab */
|
||||
gboolean add_shift:1;
|
||||
|
||||
/* for keybindings that apply only to a window */
|
||||
gboolean per_window:1;
|
||||
|
||||
/* for keybindings not added with meta_display_add_keybinding() */
|
||||
gboolean builtin:1;
|
||||
} MetaKeyPref;
|
||||
|
||||
GType meta_key_binding_get_type (void);
|
||||
|
||||
GList *meta_prefs_get_keybindings (void);
|
||||
|
||||
MetaKeyBindingAction meta_prefs_get_keybinding_action (const char *name);
|
||||
|
||||
void meta_prefs_get_window_binding (const char *name,
|
||||
unsigned int *keysym,
|
||||
MetaVirtualModifier *modifiers);
|
||||
|
||||
void meta_prefs_get_overlay_binding (MetaKeyCombo *combo);
|
||||
const char *meta_prefs_get_iso_next_group_option (void);
|
||||
|
||||
gboolean meta_prefs_get_visual_bell (void);
|
||||
gboolean meta_prefs_bell_is_audible (void);
|
||||
GDesktopVisualBellType meta_prefs_get_visual_bell_type (void);
|
||||
|
@@ -72,11 +72,13 @@ typedef enum
|
||||
* MetaMaximizeFlags:
|
||||
* @META_MAXIMIZE_HORIZONTAL: Horizontal
|
||||
* @META_MAXIMIZE_VERTICAL: Vertical
|
||||
* @META_MAXIMIZE_BOTH: Both
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
META_MAXIMIZE_HORIZONTAL = 1 << 0,
|
||||
META_MAXIMIZE_VERTICAL = 1 << 1
|
||||
META_MAXIMIZE_VERTICAL = 1 << 1,
|
||||
META_MAXIMIZE_BOTH = (1 << 0 | 1 << 1),
|
||||
} MetaMaximizeFlags;
|
||||
|
||||
/**
|
||||
@@ -123,7 +125,6 @@ MetaScreen *meta_window_get_screen (MetaWindow *window);
|
||||
MetaDisplay *meta_window_get_display (MetaWindow *window);
|
||||
Window meta_window_get_xwindow (MetaWindow *window);
|
||||
MetaWindowType meta_window_get_window_type (MetaWindow *window);
|
||||
Atom meta_window_get_window_type_atom (MetaWindow *window);
|
||||
MetaWorkspace *meta_window_get_workspace (MetaWindow *window);
|
||||
int meta_window_get_monitor (MetaWindow *window);
|
||||
gboolean meta_window_is_on_all_workspaces (MetaWindow *window);
|
||||
@@ -163,7 +164,6 @@ void meta_window_change_workspace (MetaWindow *window,
|
||||
MetaWorkspace *workspace);
|
||||
GObject *meta_window_get_compositor_private (MetaWindow *window);
|
||||
void meta_window_set_compositor_private (MetaWindow *window, GObject *priv);
|
||||
void meta_window_configure_notify (MetaWindow *window, XConfigureEvent *event);
|
||||
const char *meta_window_get_role (MetaWindow *window);
|
||||
MetaStackLayer meta_window_get_layer (MetaWindow *window);
|
||||
MetaWindow* meta_window_find_root_ancestor (MetaWindow *window);
|
||||
@@ -189,8 +189,6 @@ gboolean meta_window_requested_bypass_compositor (MetaWindow *window);
|
||||
gboolean meta_window_requested_dont_bypass_compositor (MetaWindow *window);
|
||||
gint *meta_window_get_all_monitors (MetaWindow *window, gsize *length);
|
||||
|
||||
gboolean meta_window_is_mapped (MetaWindow *window);
|
||||
gboolean meta_window_toplevel_is_mapped (MetaWindow *window);
|
||||
gboolean meta_window_get_icon_geometry (MetaWindow *window,
|
||||
MetaRectangle *rect);
|
||||
void meta_window_set_icon_geometry (MetaWindow *window,
|
||||
@@ -205,7 +203,6 @@ void meta_window_raise (MetaWindow *window);
|
||||
void meta_window_lower (MetaWindow *window);
|
||||
const char *meta_window_get_title (MetaWindow *window);
|
||||
MetaWindow *meta_window_get_transient_for (MetaWindow *window);
|
||||
Window meta_window_get_transient_for_as_xid (MetaWindow *window);
|
||||
void meta_window_delete (MetaWindow *window,
|
||||
guint32 timestamp);
|
||||
guint meta_window_get_stable_sequence (MetaWindow *window);
|
||||
@@ -213,7 +210,6 @@ guint32 meta_window_get_user_time (MetaWindow *window);
|
||||
int meta_window_get_pid (MetaWindow *window);
|
||||
const char *meta_window_get_client_machine (MetaWindow *window);
|
||||
gboolean meta_window_is_remote (MetaWindow *window);
|
||||
gboolean meta_window_is_modal (MetaWindow *window);
|
||||
gboolean meta_window_is_attached_dialog (MetaWindow *window);
|
||||
const char *meta_window_get_mutter_hints (MetaWindow *window);
|
||||
|
||||
@@ -254,6 +250,16 @@ void meta_window_begin_grab_op (MetaWindow *window,
|
||||
gboolean frame_action,
|
||||
guint32 timestamp);
|
||||
|
||||
gboolean meta_window_can_maximize (MetaWindow *window);
|
||||
gboolean meta_window_can_minimize (MetaWindow *window);
|
||||
gboolean meta_window_can_shade (MetaWindow *window);
|
||||
gboolean meta_window_can_close (MetaWindow *window);
|
||||
gboolean meta_window_is_always_on_all_workspaces (MetaWindow *window);
|
||||
gboolean meta_window_is_above (MetaWindow *window);
|
||||
gboolean meta_window_allows_move (MetaWindow *window);
|
||||
gboolean meta_window_allows_resize (MetaWindow *window);
|
||||
|
||||
gboolean meta_window_titlebar_is_onscreen (MetaWindow *window);
|
||||
void meta_window_shove_titlebar_onscreen (MetaWindow *window);
|
||||
|
||||
#endif
|
||||
|
@@ -1,7 +1,7 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
_Name=Mutter (wayland compositor)
|
||||
Exec=mutter-launch -- mutter --wayland
|
||||
Exec=mutter-launch -- mutter --wayland --display-server
|
||||
NoDisplay=true
|
||||
# name of loadable control center module
|
||||
X-GNOME-WMSettingsModule=metacity
|
||||
|
@@ -1,109 +0,0 @@
|
||||
#! /bin/bash
|
||||
|
||||
if test -z "$XNEST_DISPLAY"; then
|
||||
XNEST_DISPLAY=:8
|
||||
fi
|
||||
|
||||
if test -z "$CLIENT_DISPLAY"; then
|
||||
CLIENT_DISPLAY=:8
|
||||
fi
|
||||
|
||||
if test -z "$MUTTER_DISPLAY"; then
|
||||
export MUTTER_DISPLAY=$CLIENT_DISPLAY
|
||||
fi
|
||||
|
||||
if test -z "$SCREENS"; then
|
||||
SCREENS=1
|
||||
fi
|
||||
|
||||
MAX_SCREEN=`echo $SCREENS-1 | bc`
|
||||
|
||||
if test "$DEBUG" = none; then
|
||||
DEBUG=
|
||||
elif test -z "$DEBUG"; then
|
||||
DEBUG=
|
||||
fi
|
||||
|
||||
if test -z "$CLIENTS"; then
|
||||
CLIENTS=0
|
||||
fi
|
||||
|
||||
if test -z "$SM_CLIENTS"; then
|
||||
SM_CLIENTS=0
|
||||
fi
|
||||
|
||||
if test -n "$EVIL_TEST"; then
|
||||
TEST_CLIENT='./wm-tester/wm-tester --evil'
|
||||
fi
|
||||
|
||||
if test -n "$ICON_TEST"; then
|
||||
TEST_CLIENT='./wm-tester/wm-tester --icon-windows'
|
||||
fi
|
||||
|
||||
if test -n "$DEMO_TEST"; then
|
||||
TEST_CLIENT='./tools/mutter-window-demo'
|
||||
fi
|
||||
|
||||
if test -n "$XINERAMA"; then
|
||||
XINERAMA_FLAGS='+xinerama'
|
||||
fi
|
||||
|
||||
export EF_ALLOW_MALLOC_0=1
|
||||
|
||||
if test -z "$ONLY_WM"; then
|
||||
echo "Launching Xnest"
|
||||
Xnest -ac $XNEST_DISPLAY -scrns $SCREENS -geometry 640x480 -bw 15 $XINERAMA_FLAGS &
|
||||
## usleep 800000
|
||||
sleep 1
|
||||
|
||||
if test -n "$XMON_DIR"; then
|
||||
echo "Launching xmond"
|
||||
$XMON_DIR/xmonui | $XMON_DIR/xmond -server localhost:$XNEST_DISPLAY &
|
||||
sleep 1
|
||||
fi
|
||||
|
||||
if test -n "$XSCOPE_DIR"; then
|
||||
## xscope doesn't like to die when it should, it backgrounds itself
|
||||
killall -9 xscope
|
||||
killall -9 xscope
|
||||
echo "Launching xscope"
|
||||
DISPLAY= $XSCOPE_DIR/xscope -o1 -i28 > xscoped-replies.txt &
|
||||
export MUTTER_DISPLAY=localhost:28
|
||||
sleep 1
|
||||
fi
|
||||
|
||||
echo "Launching clients"
|
||||
if test -n "$TEST_CLIENT"; then
|
||||
for I in `seq 0 $MAX_SCREEN`; do
|
||||
DISPLAY=$CLIENT_DISPLAY.$I $TEST_CLIENT &
|
||||
done
|
||||
fi
|
||||
|
||||
if test $CLIENTS != 0; then
|
||||
for I in `seq 1 $CLIENTS`; do
|
||||
echo "Launching xterm $I"
|
||||
DISPLAY=$CLIENT_DISPLAY xterm -geometry 25x15 &
|
||||
done
|
||||
fi
|
||||
|
||||
if test $SM_CLIENTS != 0; then
|
||||
for I in `seq 1 $SM_CLIENTS`; do
|
||||
echo "Launching gnome-terminal $I"
|
||||
DISPLAY=$CLIENT_DISPLAY gnome-terminal --geometry 25x15 &
|
||||
done
|
||||
fi
|
||||
|
||||
if test -e ~/.Xmodmap; then
|
||||
DISPLAY=$CLIENT_DISPLAY xmodmap ~/.Xmodmap
|
||||
fi
|
||||
|
||||
usleep 50000
|
||||
|
||||
for I in `seq 0 $MAX_SCREEN`; do
|
||||
DISPLAY=$CLIENT_DISPLAY.$I xsetroot -solid royalblue3
|
||||
done
|
||||
fi
|
||||
|
||||
if test -z "$ONLY_SETUP"; then
|
||||
MUTTER_VERBOSE=1 MUTTER_USE_LOGFILE=1 MUTTER_DEBUG_BUTTON_GRABS=1 exec $DEBUG ./mutter $OPTIONS
|
||||
fi
|
@@ -1,224 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Draw a workspace */
|
||||
|
||||
/* This file should not be modified to depend on other files in
|
||||
* libwnck or mutter, since it's used in both of them
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2002 Red Hat Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "draw-workspace.h"
|
||||
#include "theme-private.h"
|
||||
|
||||
|
||||
static void
|
||||
get_window_rect (const WnckWindowDisplayInfo *win,
|
||||
int screen_width,
|
||||
int screen_height,
|
||||
const GdkRectangle *workspace_rect,
|
||||
GdkRectangle *rect)
|
||||
{
|
||||
double width_ratio, height_ratio;
|
||||
int x, y, width, height;
|
||||
|
||||
width_ratio = (double) workspace_rect->width / (double) screen_width;
|
||||
height_ratio = (double) workspace_rect->height / (double) screen_height;
|
||||
|
||||
x = win->x;
|
||||
y = win->y;
|
||||
width = win->width;
|
||||
height = win->height;
|
||||
|
||||
x *= width_ratio;
|
||||
y *= height_ratio;
|
||||
width *= width_ratio;
|
||||
height *= height_ratio;
|
||||
|
||||
x += workspace_rect->x;
|
||||
y += workspace_rect->y;
|
||||
|
||||
if (width < 3)
|
||||
width = 3;
|
||||
if (height < 3)
|
||||
height = 3;
|
||||
|
||||
rect->x = x;
|
||||
rect->y = y;
|
||||
rect->width = width;
|
||||
rect->height = height;
|
||||
}
|
||||
|
||||
static void
|
||||
draw_window (GtkWidget *widget,
|
||||
cairo_t *cr,
|
||||
const WnckWindowDisplayInfo *win,
|
||||
const GdkRectangle *winrect,
|
||||
GtkStateFlags state)
|
||||
{
|
||||
GdkPixbuf *icon;
|
||||
int icon_x, icon_y, icon_w, icon_h;
|
||||
gboolean is_active;
|
||||
GdkRGBA color;
|
||||
GtkStyleContext *style;
|
||||
|
||||
is_active = win->is_active;
|
||||
|
||||
cairo_save (cr);
|
||||
|
||||
cairo_rectangle (cr, winrect->x, winrect->y, winrect->width, winrect->height);
|
||||
cairo_clip (cr);
|
||||
|
||||
style = gtk_widget_get_style_context (widget);
|
||||
if (is_active)
|
||||
meta_gtk_style_get_light_color (style, state, &color);
|
||||
else
|
||||
gtk_style_context_get_background_color (style, state, &color);
|
||||
gdk_cairo_set_source_rgba (cr, &color);
|
||||
|
||||
cairo_rectangle (cr,
|
||||
winrect->x + 1, winrect->y + 1,
|
||||
MAX (0, winrect->width - 2), MAX (0, winrect->height - 2));
|
||||
cairo_fill (cr);
|
||||
|
||||
|
||||
icon = win->icon;
|
||||
|
||||
icon_w = icon_h = 0;
|
||||
|
||||
if (icon)
|
||||
{
|
||||
icon_w = gdk_pixbuf_get_width (icon);
|
||||
icon_h = gdk_pixbuf_get_height (icon);
|
||||
|
||||
/* If the icon is too big, fall back to mini icon.
|
||||
* We don't arbitrarily scale the icon, because it's
|
||||
* just too slow on my Athlon 850.
|
||||
*/
|
||||
if (icon_w > (winrect->width - 2) ||
|
||||
icon_h > (winrect->height - 2))
|
||||
{
|
||||
icon = win->mini_icon;
|
||||
if (icon)
|
||||
{
|
||||
icon_w = gdk_pixbuf_get_width (icon);
|
||||
icon_h = gdk_pixbuf_get_height (icon);
|
||||
|
||||
/* Give up. */
|
||||
if (icon_w > (winrect->width - 2) ||
|
||||
icon_h > (winrect->height - 2))
|
||||
icon = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (icon)
|
||||
{
|
||||
icon_x = winrect->x + (winrect->width - icon_w) / 2;
|
||||
icon_y = winrect->y + (winrect->height - icon_h) / 2;
|
||||
|
||||
cairo_save (cr);
|
||||
gdk_cairo_set_source_pixbuf (cr, icon, icon_x, icon_y);
|
||||
cairo_rectangle (cr, icon_x, icon_y, icon_w, icon_h);
|
||||
cairo_clip (cr);
|
||||
cairo_paint (cr);
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
gtk_style_context_get_color (style, state, &color);
|
||||
gdk_cairo_set_source_rgba (cr, &color);
|
||||
cairo_set_line_width (cr, 1.0);
|
||||
cairo_rectangle (cr,
|
||||
winrect->x + 0.5, winrect->y + 0.5,
|
||||
MAX (0, winrect->width - 1), MAX (0, winrect->height - 1));
|
||||
cairo_stroke (cr);
|
||||
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
void
|
||||
wnck_draw_workspace (GtkWidget *widget,
|
||||
cairo_t *cr,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
int screen_width,
|
||||
int screen_height,
|
||||
GdkPixbuf *workspace_background,
|
||||
gboolean is_active,
|
||||
const WnckWindowDisplayInfo *windows,
|
||||
int n_windows)
|
||||
{
|
||||
int i;
|
||||
GdkRectangle workspace_rect;
|
||||
GtkStateFlags state;
|
||||
GtkStyleContext *style;
|
||||
|
||||
workspace_rect.x = x;
|
||||
workspace_rect.y = y;
|
||||
workspace_rect.width = width;
|
||||
workspace_rect.height = height;
|
||||
|
||||
if (is_active)
|
||||
state = GTK_STATE_FLAG_SELECTED;
|
||||
else if (workspace_background)
|
||||
state = GTK_STATE_FLAG_PRELIGHT;
|
||||
else
|
||||
state = GTK_STATE_FLAG_NORMAL;
|
||||
|
||||
style = gtk_widget_get_style_context (widget);
|
||||
|
||||
cairo_save (cr);
|
||||
|
||||
if (workspace_background)
|
||||
{
|
||||
gdk_cairo_set_source_pixbuf (cr, workspace_background, x, y);
|
||||
cairo_paint (cr);
|
||||
}
|
||||
else
|
||||
{
|
||||
GdkRGBA color;
|
||||
|
||||
meta_gtk_style_get_dark_color (style,state, &color);
|
||||
gdk_cairo_set_source_rgba (cr, &color);
|
||||
cairo_rectangle (cr, x, y, width, height);
|
||||
cairo_fill (cr);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (i < n_windows)
|
||||
{
|
||||
const WnckWindowDisplayInfo *win = &windows[i];
|
||||
GdkRectangle winrect;
|
||||
|
||||
get_window_rect (win, screen_width,
|
||||
screen_height, &workspace_rect, &winrect);
|
||||
|
||||
draw_window (widget,
|
||||
cr,
|
||||
win,
|
||||
&winrect,
|
||||
state);
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
cairo_restore (cr);
|
||||
|
||||
}
|
@@ -1,59 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Draw a workspace */
|
||||
|
||||
/* This file should not be modified to depend on other files in
|
||||
* libwnck or metacity, since it's used in both of them
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2002 Red Hat Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef WNCK_DRAW_WORKSPACE_H
|
||||
#define WNCK_DRAW_WORKSPACE_H
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GdkPixbuf *icon;
|
||||
GdkPixbuf *mini_icon;
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
guint is_active : 1;
|
||||
|
||||
} WnckWindowDisplayInfo;
|
||||
|
||||
void wnck_draw_workspace (GtkWidget *widget,
|
||||
cairo_t *cr,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
int screen_width,
|
||||
int screen_height,
|
||||
GdkPixbuf *workspace_background,
|
||||
gboolean is_active,
|
||||
const WnckWindowDisplayInfo *windows,
|
||||
int n_windows);
|
||||
|
||||
#endif
|
@@ -44,8 +44,6 @@
|
||||
static void meta_frames_destroy (GtkWidget *object);
|
||||
static void meta_frames_finalize (GObject *object);
|
||||
static void meta_frames_style_updated (GtkWidget *widget);
|
||||
static void meta_frames_map (GtkWidget *widget);
|
||||
static void meta_frames_unmap (GtkWidget *widget);
|
||||
|
||||
static void meta_frames_update_prelit_control (MetaFrames *frames,
|
||||
MetaUIFrame *frame,
|
||||
@@ -134,9 +132,6 @@ meta_frames_class_init (MetaFramesClass *class)
|
||||
|
||||
widget_class->style_updated = meta_frames_style_updated;
|
||||
|
||||
widget_class->map = meta_frames_map;
|
||||
widget_class->unmap = meta_frames_unmap;
|
||||
|
||||
widget_class->draw = meta_frames_draw;
|
||||
widget_class->destroy_event = meta_frames_destroy_event;
|
||||
widget_class->button_press_event = meta_frames_button_press_event;
|
||||
@@ -231,6 +226,7 @@ meta_frames_init (MetaFrames *frames)
|
||||
|
||||
frames->style_variants = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, g_object_unref);
|
||||
|
||||
update_style_contexts (frames);
|
||||
|
||||
gtk_widget_set_double_buffered (GTK_WIDGET (frames), FALSE);
|
||||
@@ -522,13 +518,26 @@ MetaFrames*
|
||||
meta_frames_new (int screen_number)
|
||||
{
|
||||
GdkScreen *screen;
|
||||
MetaFrames *frames;
|
||||
|
||||
screen = gdk_display_get_screen (gdk_display_get_default (),
|
||||
screen_number);
|
||||
|
||||
return g_object_new (META_TYPE_FRAMES,
|
||||
"screen", screen,
|
||||
NULL);
|
||||
frames = g_object_new (META_TYPE_FRAMES,
|
||||
"screen", screen,
|
||||
"type", GTK_WINDOW_POPUP,
|
||||
NULL);
|
||||
|
||||
/* Put the window at an arbitrary offscreen location; the one place
|
||||
* it can't be is at -100x-100, since the meta_window_new() will
|
||||
* mistake it for a window created via meta_create_offscreen_window()
|
||||
* and ignore it, and we need this window to get frame-synchronization
|
||||
* messages so that GTK+'s style change handling works.
|
||||
*/
|
||||
gtk_window_move (GTK_WINDOW (frames), -200, -200);
|
||||
gtk_window_resize (GTK_WINDOW (frames), 1, 1);
|
||||
|
||||
return frames;
|
||||
}
|
||||
|
||||
/* In order to use a style with a window it has to be attached to that
|
||||
@@ -635,22 +644,6 @@ meta_frames_unmanage_window (MetaFrames *frames,
|
||||
meta_warning ("Frame 0x%lx not managed, can't unmanage\n", xwindow);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_frames_map (GtkWidget *widget)
|
||||
{
|
||||
/* We override the parent map function to a no-op because we don't
|
||||
* want to actually show the GDK window. But GTK needs to think that
|
||||
* the widget is mapped or it won't deliver the events we care about.
|
||||
*/
|
||||
gtk_widget_set_mapped (widget, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_frames_unmap (GtkWidget *widget)
|
||||
{
|
||||
gtk_widget_set_mapped (widget, FALSE);
|
||||
}
|
||||
|
||||
static MetaUIFrame*
|
||||
meta_frames_lookup_window (MetaFrames *frames,
|
||||
Window xwindow)
|
||||
|
@@ -1,963 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Mutter popup window thing showing windows you can tab to */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
* Copyright (C) 2002 Red Hat, Inc.
|
||||
* Copyright (C) 2005 Elijah Newren
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <meta/util.h>
|
||||
#include "core.h"
|
||||
#include "tabpopup.h"
|
||||
/* FIXME these two includes are 100% broken ...
|
||||
*/
|
||||
#include "workspace-private.h"
|
||||
#include "frame.h"
|
||||
#include "draw-workspace.h"
|
||||
#include <gtk/gtk.h>
|
||||
#include <math.h>
|
||||
|
||||
#define OUTSIDE_SELECT_RECT 2
|
||||
#define INSIDE_SELECT_RECT 2
|
||||
|
||||
typedef struct _TabEntry TabEntry;
|
||||
|
||||
struct _TabEntry
|
||||
{
|
||||
MetaTabEntryKey key;
|
||||
char *title;
|
||||
GdkPixbuf *icon, *dimmed_icon;
|
||||
GtkWidget *widget;
|
||||
GdkRectangle rect;
|
||||
GdkRectangle inner_rect;
|
||||
guint blank : 1;
|
||||
};
|
||||
|
||||
struct _MetaTabPopup
|
||||
{
|
||||
GtkWidget *window;
|
||||
GtkWidget *label;
|
||||
GList *current;
|
||||
GList *entries;
|
||||
TabEntry *current_selected_entry;
|
||||
GtkWidget *outline_window;
|
||||
gboolean outline;
|
||||
};
|
||||
|
||||
static GtkWidget* selectable_image_new (GdkPixbuf *pixbuf);
|
||||
static void select_image (GtkWidget *widget);
|
||||
static void unselect_image (GtkWidget *widget);
|
||||
|
||||
static GtkWidget* selectable_workspace_new (MetaWorkspace *workspace);
|
||||
static void select_workspace (GtkWidget *widget);
|
||||
static void unselect_workspace (GtkWidget *widget);
|
||||
|
||||
static gboolean
|
||||
outline_window_draw (GtkWidget *widget,
|
||||
cairo_t *cr,
|
||||
gpointer data)
|
||||
{
|
||||
MetaTabPopup *popup;
|
||||
TabEntry *te;
|
||||
|
||||
popup = data;
|
||||
|
||||
if (!popup->outline || popup->current_selected_entry == NULL)
|
||||
return FALSE;
|
||||
|
||||
te = popup->current_selected_entry;
|
||||
|
||||
cairo_set_line_width (cr, 1.0);
|
||||
cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
|
||||
|
||||
cairo_rectangle (cr,
|
||||
0.5, 0.5,
|
||||
te->rect.width - 1,
|
||||
te->rect.height - 1);
|
||||
cairo_stroke (cr);
|
||||
|
||||
cairo_rectangle (cr,
|
||||
te->inner_rect.x - 0.5, te->inner_rect.y - 0.5,
|
||||
te->inner_rect.width + 1,
|
||||
te->inner_rect.height + 1);
|
||||
cairo_stroke (cr);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static GdkPixbuf*
|
||||
dimm_icon (GdkPixbuf *pixbuf)
|
||||
{
|
||||
int x, y, pixel_stride, row_stride;
|
||||
guchar *row, *pixels;
|
||||
int w, h;
|
||||
GdkPixbuf *dimmed_pixbuf;
|
||||
|
||||
if (gdk_pixbuf_get_has_alpha (pixbuf))
|
||||
{
|
||||
dimmed_pixbuf = gdk_pixbuf_copy (pixbuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
dimmed_pixbuf = gdk_pixbuf_add_alpha (pixbuf, FALSE, 0, 0, 0);
|
||||
}
|
||||
|
||||
w = gdk_pixbuf_get_width (dimmed_pixbuf);
|
||||
h = gdk_pixbuf_get_height (dimmed_pixbuf);
|
||||
|
||||
pixel_stride = 4;
|
||||
|
||||
row = gdk_pixbuf_get_pixels (dimmed_pixbuf);
|
||||
row_stride = gdk_pixbuf_get_rowstride (dimmed_pixbuf);
|
||||
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
pixels = row;
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
pixels[3] /= 2;
|
||||
pixels += pixel_stride;
|
||||
}
|
||||
row += row_stride;
|
||||
}
|
||||
return dimmed_pixbuf;
|
||||
}
|
||||
|
||||
static TabEntry*
|
||||
tab_entry_new (const MetaTabEntry *entry,
|
||||
gint screen_width,
|
||||
gboolean outline)
|
||||
{
|
||||
TabEntry *te;
|
||||
|
||||
te = g_new (TabEntry, 1);
|
||||
te->key = entry->key;
|
||||
te->title = NULL;
|
||||
if (entry->title)
|
||||
{
|
||||
gchar *str;
|
||||
gchar *tmp;
|
||||
gchar *formatter = "%s";
|
||||
|
||||
str = meta_g_utf8_strndup (entry->title, 4096);
|
||||
|
||||
if (entry->hidden)
|
||||
{
|
||||
formatter = "[%s]";
|
||||
}
|
||||
|
||||
tmp = g_markup_printf_escaped (formatter, str);
|
||||
g_free (str);
|
||||
str = tmp;
|
||||
|
||||
if (entry->demands_attention)
|
||||
{
|
||||
/* Escape the whole line of text then markup the text and
|
||||
* copy it back into the original buffer.
|
||||
*/
|
||||
tmp = g_strdup_printf ("<b>%s</b>", str);
|
||||
g_free (str);
|
||||
str = tmp;
|
||||
}
|
||||
|
||||
te->title=g_strdup(str);
|
||||
|
||||
g_free (str);
|
||||
}
|
||||
te->widget = NULL;
|
||||
te->icon = entry->icon;
|
||||
te->blank = entry->blank;
|
||||
te->dimmed_icon = NULL;
|
||||
if (te->icon)
|
||||
{
|
||||
g_object_ref (G_OBJECT (te->icon));
|
||||
if (entry->hidden)
|
||||
te->dimmed_icon = dimm_icon (entry->icon);
|
||||
}
|
||||
|
||||
if (outline)
|
||||
{
|
||||
te->rect.x = entry->rect.x;
|
||||
te->rect.y = entry->rect.y;
|
||||
te->rect.width = entry->rect.width;
|
||||
te->rect.height = entry->rect.height;
|
||||
|
||||
te->inner_rect.x = entry->inner_rect.x;
|
||||
te->inner_rect.y = entry->inner_rect.y;
|
||||
te->inner_rect.width = entry->inner_rect.width;
|
||||
te->inner_rect.height = entry->inner_rect.height;
|
||||
}
|
||||
return te;
|
||||
}
|
||||
|
||||
MetaTabPopup*
|
||||
meta_ui_tab_popup_new (const MetaTabEntry *entries,
|
||||
int screen_number,
|
||||
int entry_count,
|
||||
int width,
|
||||
gboolean outline)
|
||||
{
|
||||
MetaTabPopup *popup;
|
||||
int i, left, top;
|
||||
int height;
|
||||
GtkWidget *grid;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *align;
|
||||
GList *tmp;
|
||||
GtkWidget *frame;
|
||||
int max_label_width; /* the actual max width of the labels we create */
|
||||
AtkObject *obj;
|
||||
GdkScreen *screen;
|
||||
int screen_width;
|
||||
|
||||
popup = g_new (MetaTabPopup, 1);
|
||||
|
||||
popup->outline_window = gtk_window_new (GTK_WINDOW_POPUP);
|
||||
|
||||
screen = gdk_display_get_screen (gdk_display_get_default (),
|
||||
screen_number);
|
||||
gtk_window_set_screen (GTK_WINDOW (popup->outline_window),
|
||||
screen);
|
||||
|
||||
gtk_widget_set_app_paintable (popup->outline_window, TRUE);
|
||||
gtk_widget_realize (popup->outline_window);
|
||||
|
||||
g_signal_connect (G_OBJECT (popup->outline_window), "draw",
|
||||
G_CALLBACK (outline_window_draw), popup);
|
||||
|
||||
popup->window = gtk_window_new (GTK_WINDOW_POPUP);
|
||||
|
||||
gtk_window_set_screen (GTK_WINDOW (popup->window),
|
||||
screen);
|
||||
|
||||
gtk_window_set_position (GTK_WINDOW (popup->window),
|
||||
GTK_WIN_POS_CENTER_ALWAYS);
|
||||
/* enable resizing, to get never-shrink behavior */
|
||||
gtk_window_set_resizable (GTK_WINDOW (popup->window),
|
||||
TRUE);
|
||||
popup->current = NULL;
|
||||
popup->entries = NULL;
|
||||
popup->current_selected_entry = NULL;
|
||||
popup->outline = outline;
|
||||
|
||||
screen_width = gdk_screen_get_width (screen);
|
||||
for (i = 0; i < entry_count; ++i)
|
||||
{
|
||||
TabEntry* new_entry = tab_entry_new (&entries[i], screen_width, outline);
|
||||
popup->entries = g_list_prepend (popup->entries, new_entry);
|
||||
}
|
||||
|
||||
popup->entries = g_list_reverse (popup->entries);
|
||||
|
||||
g_assert (width > 0);
|
||||
height = i / width;
|
||||
if (i % width)
|
||||
height += 1;
|
||||
|
||||
grid = gtk_grid_new ();
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
|
||||
frame = gtk_frame_new (NULL);
|
||||
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (grid), 1);
|
||||
gtk_container_add (GTK_CONTAINER (popup->window),
|
||||
frame);
|
||||
gtk_container_add (GTK_CONTAINER (frame),
|
||||
vbox);
|
||||
|
||||
align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (vbox), align, TRUE, TRUE, 0);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (align),
|
||||
grid);
|
||||
|
||||
popup->label = gtk_label_new ("");
|
||||
|
||||
/* Set the accessible role of the label to a status bar so it
|
||||
* will emit name changed events that can be used by screen
|
||||
* readers.
|
||||
*/
|
||||
obj = gtk_widget_get_accessible (popup->label);
|
||||
atk_object_set_role (obj, ATK_ROLE_STATUSBAR);
|
||||
|
||||
gtk_misc_set_padding (GTK_MISC (popup->label), 3, 3);
|
||||
|
||||
gtk_box_pack_end (GTK_BOX (vbox), popup->label, FALSE, FALSE, 0);
|
||||
|
||||
max_label_width = 0;
|
||||
top = 0;
|
||||
tmp = popup->entries;
|
||||
|
||||
while (tmp && top < height)
|
||||
{
|
||||
left = 0;
|
||||
|
||||
while (tmp && left < width)
|
||||
{
|
||||
GtkWidget *image;
|
||||
GtkRequisition req;
|
||||
|
||||
TabEntry *te;
|
||||
|
||||
te = tmp->data;
|
||||
|
||||
if (te->blank)
|
||||
{
|
||||
/* just stick a widget here to avoid special cases */
|
||||
image = gtk_alignment_new (0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
else if (outline)
|
||||
{
|
||||
if (te->dimmed_icon)
|
||||
{
|
||||
image = selectable_image_new (te->dimmed_icon);
|
||||
}
|
||||
else
|
||||
{
|
||||
image = selectable_image_new (te->icon);
|
||||
}
|
||||
|
||||
gtk_misc_set_padding (GTK_MISC (image),
|
||||
INSIDE_SELECT_RECT + OUTSIDE_SELECT_RECT + 1,
|
||||
INSIDE_SELECT_RECT + OUTSIDE_SELECT_RECT + 1);
|
||||
gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.5);
|
||||
}
|
||||
else
|
||||
{
|
||||
image = selectable_workspace_new ((MetaWorkspace *) te->key);
|
||||
}
|
||||
|
||||
te->widget = image;
|
||||
|
||||
gtk_grid_attach (GTK_GRID (grid),
|
||||
te->widget,
|
||||
left, top, 1, 1);
|
||||
|
||||
/* Efficiency rules! */
|
||||
gtk_label_set_markup (GTK_LABEL (popup->label),
|
||||
te->title);
|
||||
gtk_widget_get_preferred_size (popup->label, &req, NULL);
|
||||
max_label_width = MAX (max_label_width, req.width);
|
||||
|
||||
tmp = tmp->next;
|
||||
|
||||
++left;
|
||||
}
|
||||
|
||||
++top;
|
||||
}
|
||||
|
||||
/* remove all the temporary text */
|
||||
gtk_label_set_text (GTK_LABEL (popup->label), "");
|
||||
/* Make it so that we ellipsize if the text is too long */
|
||||
gtk_label_set_ellipsize (GTK_LABEL (popup->label), PANGO_ELLIPSIZE_END);
|
||||
|
||||
/* Limit the window size to no bigger than screen_width/4 */
|
||||
if (max_label_width>(screen_width/4))
|
||||
{
|
||||
max_label_width = screen_width/4;
|
||||
}
|
||||
|
||||
max_label_width += 20; /* add random padding */
|
||||
|
||||
gtk_window_set_default_size (GTK_WINDOW (popup->window),
|
||||
max_label_width,
|
||||
-1);
|
||||
|
||||
return popup;
|
||||
}
|
||||
|
||||
static void
|
||||
free_tab_entry (gpointer data, gpointer user_data)
|
||||
{
|
||||
TabEntry *te;
|
||||
|
||||
te = data;
|
||||
|
||||
g_free (te->title);
|
||||
if (te->icon)
|
||||
g_object_unref (G_OBJECT (te->icon));
|
||||
if (te->dimmed_icon)
|
||||
g_object_unref (G_OBJECT (te->dimmed_icon));
|
||||
|
||||
g_free (te);
|
||||
}
|
||||
|
||||
void
|
||||
meta_ui_tab_popup_free (MetaTabPopup *popup)
|
||||
{
|
||||
meta_verbose ("Destroying tab popup window\n");
|
||||
|
||||
if (!popup)
|
||||
{
|
||||
meta_warning ("NULL passed to meta_ui_tab_popup_free\n");
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_widget_destroy (popup->outline_window);
|
||||
gtk_widget_destroy (popup->window);
|
||||
|
||||
g_list_foreach (popup->entries, free_tab_entry, NULL);
|
||||
|
||||
g_list_free (popup->entries);
|
||||
|
||||
g_free (popup);
|
||||
}
|
||||
|
||||
void
|
||||
meta_ui_tab_popup_set_showing (MetaTabPopup *popup,
|
||||
gboolean showing)
|
||||
{
|
||||
if (showing)
|
||||
{
|
||||
gtk_widget_show_all (popup->window);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gtk_widget_get_visible (popup->window))
|
||||
{
|
||||
meta_verbose ("Hiding tab popup window\n");
|
||||
gtk_widget_hide (popup->window);
|
||||
meta_core_increment_event_serial (
|
||||
GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
display_entry (MetaTabPopup *popup,
|
||||
TabEntry *te)
|
||||
{
|
||||
GdkRectangle rect;
|
||||
GdkWindow *window;
|
||||
|
||||
|
||||
if (popup->current_selected_entry)
|
||||
{
|
||||
if (popup->outline)
|
||||
unselect_image (popup->current_selected_entry->widget);
|
||||
else
|
||||
unselect_workspace (popup->current_selected_entry->widget);
|
||||
}
|
||||
|
||||
gtk_label_set_markup (GTK_LABEL (popup->label), te->title);
|
||||
|
||||
if (popup->outline)
|
||||
select_image (te->widget);
|
||||
else
|
||||
select_workspace (te->widget);
|
||||
|
||||
if (popup->outline)
|
||||
{
|
||||
cairo_region_t *region;
|
||||
cairo_region_t *inner_region;
|
||||
GdkRGBA black = { 0.0, 0.0, 0.0, 1.0 };
|
||||
|
||||
window = gtk_widget_get_window (popup->outline_window);
|
||||
|
||||
/* Do stuff behind gtk's back */
|
||||
gdk_window_hide (window);
|
||||
meta_core_increment_event_serial (
|
||||
GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
|
||||
|
||||
rect = te->rect;
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
|
||||
gdk_window_move_resize (window,
|
||||
te->rect.x, te->rect.y,
|
||||
te->rect.width, te->rect.height);
|
||||
|
||||
gdk_window_set_background_rgba (window, &black);
|
||||
|
||||
|
||||
region = cairo_region_create_rectangle (&rect);
|
||||
inner_region = cairo_region_create_rectangle (&te->inner_rect);
|
||||
cairo_region_subtract (region, inner_region);
|
||||
cairo_region_destroy (inner_region);
|
||||
|
||||
gdk_window_shape_combine_region (window,
|
||||
region,
|
||||
0, 0);
|
||||
|
||||
cairo_region_destroy (region);
|
||||
|
||||
|
||||
/* This should piss off gtk a bit, but we don't want to raise
|
||||
* above the tab popup. So, instead of calling gtk_widget_show,
|
||||
* we manually set the window as mapped and then manually map it
|
||||
* with gdk functions.
|
||||
*/
|
||||
gtk_widget_set_mapped (popup->outline_window, TRUE);
|
||||
gdk_window_show_unraised (window);
|
||||
}
|
||||
|
||||
/* Must be before we handle an expose for the outline window */
|
||||
popup->current_selected_entry = te;
|
||||
}
|
||||
|
||||
void
|
||||
meta_ui_tab_popup_forward (MetaTabPopup *popup)
|
||||
{
|
||||
if (popup->current != NULL)
|
||||
popup->current = popup->current->next;
|
||||
|
||||
if (popup->current == NULL)
|
||||
popup->current = popup->entries;
|
||||
|
||||
if (popup->current != NULL)
|
||||
{
|
||||
TabEntry *te;
|
||||
|
||||
te = popup->current->data;
|
||||
|
||||
display_entry (popup, te);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_ui_tab_popup_backward (MetaTabPopup *popup)
|
||||
{
|
||||
if (popup->current != NULL)
|
||||
popup->current = popup->current->prev;
|
||||
|
||||
if (popup->current == NULL)
|
||||
popup->current = g_list_last (popup->entries);
|
||||
|
||||
if (popup->current != NULL)
|
||||
{
|
||||
TabEntry *te;
|
||||
|
||||
te = popup->current->data;
|
||||
|
||||
display_entry (popup, te);
|
||||
}
|
||||
}
|
||||
|
||||
MetaTabEntryKey
|
||||
meta_ui_tab_popup_get_selected (MetaTabPopup *popup)
|
||||
{
|
||||
if (popup->current)
|
||||
{
|
||||
TabEntry *te;
|
||||
|
||||
te = popup->current->data;
|
||||
|
||||
return te->key;
|
||||
}
|
||||
else
|
||||
return (MetaTabEntryKey)None;
|
||||
}
|
||||
|
||||
void
|
||||
meta_ui_tab_popup_select (MetaTabPopup *popup,
|
||||
MetaTabEntryKey key)
|
||||
{
|
||||
GList *tmp;
|
||||
|
||||
/* Note, "key" may not be in the list of entries; other code assumes
|
||||
* it's OK to pass in a key that isn't.
|
||||
*/
|
||||
|
||||
tmp = popup->entries;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
TabEntry *te;
|
||||
|
||||
te = tmp->data;
|
||||
|
||||
if (te->key == key)
|
||||
{
|
||||
popup->current = tmp;
|
||||
|
||||
display_entry (popup, te);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
}
|
||||
|
||||
#define META_TYPE_SELECT_IMAGE (meta_select_image_get_type ())
|
||||
#define META_SELECT_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SELECT_IMAGE, MetaSelectImage))
|
||||
|
||||
typedef struct _MetaSelectImage MetaSelectImage;
|
||||
typedef struct _MetaSelectImageClass MetaSelectImageClass;
|
||||
|
||||
struct _MetaSelectImage
|
||||
{
|
||||
GtkImage parent_instance;
|
||||
guint selected : 1;
|
||||
};
|
||||
|
||||
struct _MetaSelectImageClass
|
||||
{
|
||||
GtkImageClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
static GType meta_select_image_get_type (void) G_GNUC_CONST;
|
||||
|
||||
static GtkWidget*
|
||||
selectable_image_new (GdkPixbuf *pixbuf)
|
||||
{
|
||||
GtkWidget *w;
|
||||
|
||||
w = g_object_new (meta_select_image_get_type (), NULL);
|
||||
gtk_image_set_from_pixbuf (GTK_IMAGE (w), pixbuf);
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
static void
|
||||
select_image (GtkWidget *widget)
|
||||
{
|
||||
META_SELECT_IMAGE (widget)->selected = TRUE;
|
||||
gtk_widget_queue_draw (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
unselect_image (GtkWidget *widget)
|
||||
{
|
||||
META_SELECT_IMAGE (widget)->selected = FALSE;
|
||||
gtk_widget_queue_draw (widget);
|
||||
}
|
||||
|
||||
static void meta_select_image_class_init (MetaSelectImageClass *klass);
|
||||
static gboolean meta_select_image_draw (GtkWidget *widget,
|
||||
cairo_t *cr);
|
||||
|
||||
static GtkImageClass *parent_class;
|
||||
|
||||
GType
|
||||
meta_select_image_get_type (void)
|
||||
{
|
||||
static GType image_type = 0;
|
||||
|
||||
if (!image_type)
|
||||
{
|
||||
static const GTypeInfo image_info =
|
||||
{
|
||||
sizeof (MetaSelectImageClass),
|
||||
NULL, /* base_init */
|
||||
NULL, /* base_finalize */
|
||||
(GClassInitFunc) meta_select_image_class_init,
|
||||
NULL, /* class_finalize */
|
||||
NULL, /* class_data */
|
||||
sizeof (MetaSelectImage),
|
||||
16, /* n_preallocs */
|
||||
(GInstanceInitFunc) NULL,
|
||||
};
|
||||
|
||||
image_type = g_type_register_static (GTK_TYPE_IMAGE, "MetaSelectImage", &image_info, 0);
|
||||
}
|
||||
|
||||
return image_type;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_select_image_class_init (MetaSelectImageClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class;
|
||||
|
||||
parent_class = g_type_class_peek (gtk_image_get_type ());
|
||||
|
||||
widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
widget_class->draw = meta_select_image_draw;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_select_image_draw (GtkWidget *widget,
|
||||
cairo_t *cr)
|
||||
{
|
||||
GtkAllocation allocation;
|
||||
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
|
||||
if (META_SELECT_IMAGE (widget)->selected)
|
||||
{
|
||||
GtkMisc *misc;
|
||||
GtkRequisition requisition;
|
||||
GtkStyleContext *context;
|
||||
GdkRGBA color;
|
||||
int x, y, w, h;
|
||||
gint xpad, ypad;
|
||||
gfloat xalign, yalign;
|
||||
|
||||
misc = GTK_MISC (widget);
|
||||
|
||||
gtk_widget_get_requisition (widget, &requisition);
|
||||
gtk_misc_get_alignment (misc, &xalign, &yalign);
|
||||
gtk_misc_get_padding (misc, &xpad, &ypad);
|
||||
|
||||
x = (allocation.width - (requisition.width - xpad * 2)) * xalign + 0.5;
|
||||
y = (allocation.height - (requisition.height - ypad * 2)) * yalign + 0.5;
|
||||
|
||||
x -= INSIDE_SELECT_RECT + 1;
|
||||
y -= INSIDE_SELECT_RECT + 1;
|
||||
|
||||
w = requisition.width - OUTSIDE_SELECT_RECT * 2 - 1;
|
||||
h = requisition.height - OUTSIDE_SELECT_RECT * 2 - 1;
|
||||
|
||||
context = gtk_widget_get_style_context (widget);
|
||||
|
||||
gtk_style_context_set_state (context,
|
||||
gtk_widget_get_state_flags (widget));
|
||||
|
||||
gtk_style_context_lookup_color (context, "color", &color);
|
||||
|
||||
cairo_set_line_width (cr, 2.0);
|
||||
cairo_set_source_rgb (cr, color.red, color.green, color.blue);
|
||||
|
||||
cairo_rectangle (cr, x, y, w + 1, h + 1);
|
||||
cairo_stroke (cr);
|
||||
|
||||
cairo_set_line_width (cr, 1.0);
|
||||
}
|
||||
|
||||
return GTK_WIDGET_CLASS (parent_class)->draw (widget, cr);
|
||||
}
|
||||
|
||||
#define META_TYPE_SELECT_WORKSPACE (meta_select_workspace_get_type ())
|
||||
#define META_SELECT_WORKSPACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SELECT_WORKSPACE, MetaSelectWorkspace))
|
||||
|
||||
typedef struct _MetaSelectWorkspace MetaSelectWorkspace;
|
||||
typedef struct _MetaSelectWorkspaceClass MetaSelectWorkspaceClass;
|
||||
|
||||
struct _MetaSelectWorkspace
|
||||
{
|
||||
GtkDrawingArea parent_instance;
|
||||
MetaWorkspace *workspace;
|
||||
guint selected : 1;
|
||||
};
|
||||
|
||||
struct _MetaSelectWorkspaceClass
|
||||
{
|
||||
GtkDrawingAreaClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
static GType meta_select_workspace_get_type (void) G_GNUC_CONST;
|
||||
|
||||
#define SELECT_OUTLINE_WIDTH 2
|
||||
#define MINI_WORKSPACE_WIDTH 48
|
||||
|
||||
static GtkWidget*
|
||||
selectable_workspace_new (MetaWorkspace *workspace)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
double screen_aspect;
|
||||
|
||||
widget = g_object_new (meta_select_workspace_get_type (), NULL);
|
||||
|
||||
screen_aspect = (double) workspace->screen->rect.height /
|
||||
(double) workspace->screen->rect.width;
|
||||
|
||||
/* account for select rect */
|
||||
gtk_widget_set_size_request (widget,
|
||||
MINI_WORKSPACE_WIDTH + SELECT_OUTLINE_WIDTH * 2,
|
||||
MINI_WORKSPACE_WIDTH * screen_aspect + SELECT_OUTLINE_WIDTH * 2);
|
||||
|
||||
META_SELECT_WORKSPACE (widget)->workspace = workspace;
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
static void
|
||||
select_workspace (GtkWidget *widget)
|
||||
{
|
||||
META_SELECT_WORKSPACE(widget)->selected = TRUE;
|
||||
gtk_widget_queue_draw (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
unselect_workspace (GtkWidget *widget)
|
||||
{
|
||||
META_SELECT_WORKSPACE (widget)->selected = FALSE;
|
||||
gtk_widget_queue_draw (widget);
|
||||
}
|
||||
|
||||
static void meta_select_workspace_class_init (MetaSelectWorkspaceClass *klass);
|
||||
|
||||
static gboolean meta_select_workspace_draw (GtkWidget *widget,
|
||||
cairo_t *cr);
|
||||
|
||||
GType
|
||||
meta_select_workspace_get_type (void)
|
||||
{
|
||||
static GType workspace_type = 0;
|
||||
|
||||
if (!workspace_type)
|
||||
{
|
||||
static const GTypeInfo workspace_info =
|
||||
{
|
||||
sizeof (MetaSelectWorkspaceClass),
|
||||
NULL, /* base_init */
|
||||
NULL, /* base_finalize */
|
||||
(GClassInitFunc) meta_select_workspace_class_init,
|
||||
NULL, /* class_finalize */
|
||||
NULL, /* class_data */
|
||||
sizeof (MetaSelectWorkspace),
|
||||
16, /* n_preallocs */
|
||||
(GInstanceInitFunc) NULL,
|
||||
};
|
||||
|
||||
workspace_type = g_type_register_static (GTK_TYPE_DRAWING_AREA,
|
||||
"MetaSelectWorkspace",
|
||||
&workspace_info,
|
||||
0);
|
||||
}
|
||||
|
||||
return workspace_type;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_select_workspace_class_init (MetaSelectWorkspaceClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class;
|
||||
|
||||
widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
widget_class->draw = meta_select_workspace_draw;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_convert_meta_to_wnck:
|
||||
* @window: the #MetaWindow
|
||||
* @screen: the #MetaScreen the window is on
|
||||
*
|
||||
* Converts a #MetaWindow to a #WnckWindowDisplayInfo window
|
||||
* that is used to build a thumbnail of a workspace.
|
||||
**/
|
||||
static WnckWindowDisplayInfo
|
||||
meta_convert_meta_to_wnck (MetaWindow *window, MetaScreen *screen)
|
||||
{
|
||||
WnckWindowDisplayInfo wnck_window;
|
||||
wnck_window.icon = window->icon;
|
||||
wnck_window.mini_icon = window->mini_icon;
|
||||
wnck_window.is_active = window->has_focus;
|
||||
|
||||
if (window->frame)
|
||||
{
|
||||
wnck_window.x = window->frame->rect.x;
|
||||
wnck_window.y = window->frame->rect.y;
|
||||
wnck_window.width = window->frame->rect.width;
|
||||
wnck_window.height = window->frame->rect.height;
|
||||
}
|
||||
else
|
||||
{
|
||||
wnck_window.x = window->rect.x;
|
||||
wnck_window.y = window->rect.y;
|
||||
wnck_window.width = window->rect.width;
|
||||
wnck_window.height = window->rect.height;
|
||||
}
|
||||
return wnck_window;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
meta_select_workspace_draw (GtkWidget *widget,
|
||||
cairo_t *cr)
|
||||
{
|
||||
MetaWorkspace *workspace;
|
||||
WnckWindowDisplayInfo *windows;
|
||||
GtkAllocation allocation;
|
||||
int i, n_windows;
|
||||
GList *tmp, *list;
|
||||
|
||||
workspace = META_SELECT_WORKSPACE (widget)->workspace;
|
||||
|
||||
list = meta_stack_list_windows (workspace->screen->stack, workspace);
|
||||
n_windows = g_list_length (list);
|
||||
windows = g_new (WnckWindowDisplayInfo, n_windows);
|
||||
|
||||
tmp = list;
|
||||
i = 0;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
MetaWindow *window;
|
||||
gboolean ignoreable_sticky;
|
||||
|
||||
window = tmp->data;
|
||||
|
||||
ignoreable_sticky = window->on_all_workspaces &&
|
||||
workspace != workspace->screen->active_workspace;
|
||||
|
||||
if (window->skip_pager ||
|
||||
!meta_window_showing_on_its_workspace (window) ||
|
||||
window->unmaps_pending ||
|
||||
ignoreable_sticky)
|
||||
{
|
||||
--n_windows;
|
||||
}
|
||||
else
|
||||
{
|
||||
windows[i] = meta_convert_meta_to_wnck (window, workspace->screen);
|
||||
i++;
|
||||
}
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
g_list_free (list);
|
||||
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
|
||||
wnck_draw_workspace (widget,
|
||||
cr,
|
||||
SELECT_OUTLINE_WIDTH,
|
||||
SELECT_OUTLINE_WIDTH,
|
||||
allocation.width - SELECT_OUTLINE_WIDTH * 2,
|
||||
allocation.height - SELECT_OUTLINE_WIDTH * 2,
|
||||
workspace->screen->rect.width,
|
||||
workspace->screen->rect.height,
|
||||
NULL,
|
||||
(workspace->screen->active_workspace == workspace),
|
||||
windows,
|
||||
n_windows);
|
||||
|
||||
g_free (windows);
|
||||
|
||||
if (META_SELECT_WORKSPACE (widget)->selected)
|
||||
{
|
||||
GtkStyleContext *context;
|
||||
GdkRGBA color;
|
||||
|
||||
context = gtk_widget_get_style_context (widget);
|
||||
|
||||
gtk_style_context_set_state (context,
|
||||
gtk_widget_get_state_flags (widget));
|
||||
|
||||
gtk_style_context_lookup_color (context, "color", &color);
|
||||
|
||||
cairo_set_line_width (cr, SELECT_OUTLINE_WIDTH);
|
||||
cairo_set_source_rgb (cr, color.red, color.green, color.blue);
|
||||
|
||||
cairo_rectangle (cr,
|
||||
SELECT_OUTLINE_WIDTH / 2.0, SELECT_OUTLINE_WIDTH / 2.0,
|
||||
allocation.width - SELECT_OUTLINE_WIDTH,
|
||||
allocation.height - SELECT_OUTLINE_WIDTH);
|
||||
cairo_stroke (cr);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
@@ -1,65 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Mutter tab popup window */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
* Copyright (C) 2005 Elijah Newren
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef META_TABPOPUP_H
|
||||
#define META_TABPOPUP_H
|
||||
|
||||
/* Don't include gtk.h or gdk.h here */
|
||||
#include <meta/common.h>
|
||||
#include <meta/boxes.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <glib.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
|
||||
typedef struct _MetaTabEntry MetaTabEntry;
|
||||
typedef struct _MetaTabPopup MetaTabPopup;
|
||||
typedef void *MetaTabEntryKey;
|
||||
|
||||
struct _MetaTabEntry
|
||||
{
|
||||
MetaTabEntryKey key;
|
||||
const char *title;
|
||||
GdkPixbuf *icon;
|
||||
MetaRectangle rect;
|
||||
MetaRectangle inner_rect;
|
||||
guint blank : 1;
|
||||
guint hidden : 1;
|
||||
guint demands_attention : 1;
|
||||
};
|
||||
|
||||
MetaTabPopup* meta_ui_tab_popup_new (const MetaTabEntry *entries,
|
||||
int screen_number,
|
||||
int entry_count,
|
||||
int width,
|
||||
gboolean outline);
|
||||
void meta_ui_tab_popup_free (MetaTabPopup *popup);
|
||||
void meta_ui_tab_popup_set_showing (MetaTabPopup *popup,
|
||||
gboolean showing);
|
||||
void meta_ui_tab_popup_forward (MetaTabPopup *popup);
|
||||
void meta_ui_tab_popup_backward (MetaTabPopup *popup);
|
||||
MetaTabEntryKey meta_ui_tab_popup_get_selected (MetaTabPopup *popup);
|
||||
void meta_ui_tab_popup_select (MetaTabPopup *popup,
|
||||
MetaTabEntryKey key);
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -1,196 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Mutter tile-preview marks the area a window will *ehm* snap to */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 Florian Müllner
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <cairo.h>
|
||||
|
||||
#include "tile-preview.h"
|
||||
#include "core.h"
|
||||
|
||||
#define OUTLINE_WIDTH 5 /* frame width in non-composite case */
|
||||
|
||||
|
||||
struct _MetaTilePreview {
|
||||
GtkWidget *preview_window;
|
||||
gulong create_serial;
|
||||
|
||||
GdkRGBA *preview_color;
|
||||
|
||||
MetaRectangle tile_rect;
|
||||
};
|
||||
|
||||
static gboolean
|
||||
meta_tile_preview_draw (GtkWidget *widget,
|
||||
cairo_t *cr,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaTilePreview *preview = user_data;
|
||||
|
||||
cairo_set_line_width (cr, 1.0);
|
||||
|
||||
/* Fill the preview area with a transparent color */
|
||||
gdk_cairo_set_source_rgba (cr, preview->preview_color);
|
||||
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_paint (cr);
|
||||
|
||||
/* Use the opaque color for the border */
|
||||
cairo_set_source_rgb (cr,
|
||||
preview->preview_color->red,
|
||||
preview->preview_color->green,
|
||||
preview->preview_color->blue);
|
||||
|
||||
cairo_rectangle (cr,
|
||||
0.5, 0.5,
|
||||
preview->tile_rect.width - 1,
|
||||
preview->tile_rect.height - 1);
|
||||
cairo_stroke (cr);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
MetaTilePreview *
|
||||
meta_tile_preview_new (int screen_number)
|
||||
{
|
||||
MetaTilePreview *preview;
|
||||
GdkScreen *screen;
|
||||
GtkStyleContext *context;
|
||||
GtkWidgetPath *path;
|
||||
guchar selection_alpha = 0xFF;
|
||||
|
||||
screen = gdk_display_get_screen (gdk_display_get_default (), screen_number);
|
||||
|
||||
preview = g_new (MetaTilePreview, 1);
|
||||
|
||||
preview->preview_window = gtk_window_new (GTK_WINDOW_POPUP);
|
||||
|
||||
gtk_window_set_screen (GTK_WINDOW (preview->preview_window), screen);
|
||||
gtk_widget_set_app_paintable (preview->preview_window, TRUE);
|
||||
|
||||
preview->preview_color = NULL;
|
||||
|
||||
preview->tile_rect.x = preview->tile_rect.y = 0;
|
||||
preview->tile_rect.width = preview->tile_rect.height = 0;
|
||||
|
||||
gtk_widget_set_visual (preview->preview_window,
|
||||
gdk_screen_get_rgba_visual (screen));
|
||||
|
||||
path = gtk_widget_path_new ();
|
||||
gtk_widget_path_append_type (path, GTK_TYPE_ICON_VIEW);
|
||||
|
||||
context = gtk_style_context_new ();
|
||||
gtk_style_context_set_path (context, path);
|
||||
gtk_style_context_add_class (context,
|
||||
GTK_STYLE_CLASS_RUBBERBAND);
|
||||
|
||||
gtk_widget_path_free (path);
|
||||
|
||||
gtk_style_context_get (context, GTK_STATE_FLAG_SELECTED,
|
||||
"background-color", &preview->preview_color,
|
||||
NULL);
|
||||
|
||||
/* The background-color for the .rubberband class should probably
|
||||
* contain the correct alpha value - unfortunately, at least for now
|
||||
* it doesn't. Hopefully the following workaround can be removed
|
||||
* when GtkIconView gets ported to GtkStyleContext.
|
||||
*/
|
||||
gtk_style_context_get_style (context,
|
||||
"selection-box-alpha", &selection_alpha,
|
||||
NULL);
|
||||
preview->preview_color->alpha = (double)selection_alpha / 0xFF;
|
||||
|
||||
g_object_unref (context);
|
||||
|
||||
/* We make an assumption that XCreateWindow will be the first operation
|
||||
* when calling gtk_widget_realize() (via gdk_window_new()), or that it
|
||||
* is at least "close enough".
|
||||
*/
|
||||
preview->create_serial = XNextRequest (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
|
||||
gtk_widget_realize (preview->preview_window);
|
||||
g_signal_connect (preview->preview_window, "draw",
|
||||
G_CALLBACK (meta_tile_preview_draw), preview);
|
||||
|
||||
return preview;
|
||||
}
|
||||
|
||||
void
|
||||
meta_tile_preview_free (MetaTilePreview *preview)
|
||||
{
|
||||
gtk_widget_destroy (preview->preview_window);
|
||||
|
||||
if (preview->preview_color)
|
||||
gdk_rgba_free (preview->preview_color);
|
||||
|
||||
g_free (preview);
|
||||
}
|
||||
|
||||
void
|
||||
meta_tile_preview_show (MetaTilePreview *preview,
|
||||
MetaRectangle *tile_rect)
|
||||
{
|
||||
GdkWindow *window;
|
||||
GdkRectangle old_rect;
|
||||
|
||||
if (gtk_widget_get_visible (preview->preview_window)
|
||||
&& preview->tile_rect.x == tile_rect->x
|
||||
&& preview->tile_rect.y == tile_rect->y
|
||||
&& preview->tile_rect.width == tile_rect->width
|
||||
&& preview->tile_rect.height == tile_rect->height)
|
||||
return; /* nothing to do */
|
||||
|
||||
gtk_widget_show (preview->preview_window);
|
||||
window = gtk_widget_get_window (preview->preview_window);
|
||||
meta_core_lower_beneath_grab_window (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
|
||||
GDK_WINDOW_XID (window),
|
||||
gtk_get_current_event_time ());
|
||||
|
||||
old_rect.x = old_rect.y = 0;
|
||||
old_rect.width = preview->tile_rect.width;
|
||||
old_rect.height = preview->tile_rect.height;
|
||||
|
||||
gdk_window_invalidate_rect (window, &old_rect, FALSE);
|
||||
|
||||
preview->tile_rect = *tile_rect;
|
||||
|
||||
gdk_window_move_resize (window,
|
||||
preview->tile_rect.x, preview->tile_rect.y,
|
||||
preview->tile_rect.width, preview->tile_rect.height);
|
||||
}
|
||||
|
||||
void
|
||||
meta_tile_preview_hide (MetaTilePreview *preview)
|
||||
{
|
||||
gtk_widget_hide (preview->preview_window);
|
||||
}
|
||||
|
||||
Window
|
||||
meta_tile_preview_get_xwindow (MetaTilePreview *preview,
|
||||
gulong *create_serial)
|
||||
{
|
||||
GdkWindow *window = gtk_widget_get_window (preview->preview_window);
|
||||
|
||||
if (create_serial)
|
||||
*create_serial = preview->create_serial;
|
||||
|
||||
return GDK_WINDOW_XID (window);
|
||||
}
|
@@ -1,36 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Meta tile preview */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 Florian Müllner
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef META_TILE_PREVIEW_H
|
||||
#define META_TILE_PREVIEW_H
|
||||
|
||||
#include <meta/boxes.h>
|
||||
|
||||
typedef struct _MetaTilePreview MetaTilePreview;
|
||||
|
||||
MetaTilePreview *meta_tile_preview_new (int screen_number);
|
||||
void meta_tile_preview_free (MetaTilePreview *preview);
|
||||
void meta_tile_preview_show (MetaTilePreview *preview,
|
||||
MetaRectangle *rect);
|
||||
void meta_tile_preview_hide (MetaTilePreview *preview);
|
||||
Window meta_tile_preview_get_xwindow (MetaTilePreview *preview,
|
||||
gulong *create_serial);
|
||||
|
||||
#endif /* META_TILE_PREVIEW_H */
|
@@ -295,9 +295,12 @@ meta_ui_new (Display *xdisplay,
|
||||
g_assert (gdisplay == gdk_display_get_default ());
|
||||
|
||||
ui->frames = meta_frames_new (XScreenNumberOfScreen (screen));
|
||||
/* This does not actually show any widget. MetaFrames has been hacked so
|
||||
* that showing it doesn't actually do anything. But we need the flags
|
||||
* set for GTK to deliver events properly. */
|
||||
/* GTK+ needs the frame-sync protocol to work in order to properly
|
||||
* handle style changes. This means that the dummy widget we create
|
||||
* to get the style for title bars actually needs to be mapped
|
||||
* and fully tracked as a MetaWindow. Horrible, but mostly harmless -
|
||||
* the window is a 1x1 overide redirect window positioned offscreen.
|
||||
*/
|
||||
gtk_widget_show (GTK_WIDGET (ui->frames));
|
||||
|
||||
g_object_set_data (G_OBJECT (gdisplay), "meta-ui", ui);
|
||||
|
@@ -178,7 +178,4 @@ int meta_ui_get_drag_threshold (MetaUI *ui);
|
||||
|
||||
MetaUIDirection meta_ui_get_direction (void);
|
||||
|
||||
#include "tabpopup.h"
|
||||
#include "tile-preview.h"
|
||||
|
||||
#endif
|
||||
|
@@ -48,7 +48,7 @@ data_offer_accept (struct wl_client *client,
|
||||
* this be a wl_data_device request? */
|
||||
|
||||
if (offer->source)
|
||||
offer->source->accept (offer->source, serial, mime_type);
|
||||
wl_data_source_send_target (offer->source->resource, mime_type);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -58,9 +58,9 @@ data_offer_receive (struct wl_client *client, struct wl_resource *resource,
|
||||
MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource);
|
||||
|
||||
if (offer->source)
|
||||
offer->source->send (offer->source, mime_type, fd);
|
||||
else
|
||||
close (fd);
|
||||
wl_data_source_send_send (offer->source->resource, mime_type, fd);
|
||||
|
||||
close (fd);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -82,7 +82,8 @@ destroy_data_offer (struct wl_resource *resource)
|
||||
|
||||
if (offer->source)
|
||||
wl_list_remove (&offer->source_destroy_listener.link);
|
||||
free (offer);
|
||||
|
||||
g_slice_free (MetaWaylandDataOffer, offer);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -99,13 +100,9 @@ static struct wl_resource *
|
||||
meta_wayland_data_source_send_offer (MetaWaylandDataSource *source,
|
||||
struct wl_resource *target)
|
||||
{
|
||||
MetaWaylandDataOffer *offer;
|
||||
MetaWaylandDataOffer *offer = g_slice_new0 (MetaWaylandDataOffer);
|
||||
char **p;
|
||||
|
||||
offer = malloc (sizeof *offer);
|
||||
if (offer == NULL)
|
||||
return NULL;
|
||||
|
||||
offer->source = source;
|
||||
offer->source_destroy_listener.notify = destroy_offer_data_source;
|
||||
|
||||
@@ -178,8 +175,7 @@ destroy_drag_focus (struct wl_listener *listener, void *data)
|
||||
|
||||
static void
|
||||
drag_grab_focus (MetaWaylandPointerGrab *grab,
|
||||
MetaWaylandSurface *surface,
|
||||
const ClutterEvent *event)
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab;
|
||||
MetaWaylandSeat *seat = drag_grab->seat;
|
||||
@@ -260,7 +256,7 @@ data_device_end_drag_grab (MetaWaylandDragGrab *drag_grab)
|
||||
if (drag_grab->drag_data_source)
|
||||
wl_list_remove (&drag_grab->drag_data_source_listener.link);
|
||||
|
||||
drag_grab_focus (&drag_grab->generic, NULL, NULL);
|
||||
drag_grab_focus (&drag_grab->generic, NULL);
|
||||
|
||||
meta_wayland_pointer_end_grab (drag_grab->generic.pointer);
|
||||
g_slice_free (MetaWaylandDragGrab, drag_grab);
|
||||
@@ -318,8 +314,12 @@ data_device_start_drag (struct wl_client *client,
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (resource);
|
||||
MetaWaylandDragGrab *drag_grab;
|
||||
/* FIXME: Check that client has implicit grab on the origin
|
||||
* surface that matches the given time. */
|
||||
|
||||
if ((seat->pointer.button_count == 0 ||
|
||||
seat->pointer.grab_serial != serial ||
|
||||
!seat->pointer.focus_surface ||
|
||||
seat->pointer.focus_surface != wl_resource_get_user_data (origin_resource)))
|
||||
return;
|
||||
|
||||
/* FIXME: Check that the data source type array isn't empty. */
|
||||
|
||||
@@ -332,6 +332,7 @@ data_device_start_drag (struct wl_client *client,
|
||||
drag_grab->generic.pointer = &seat->pointer;
|
||||
|
||||
drag_grab->drag_client = client;
|
||||
drag_grab->seat = seat;
|
||||
|
||||
if (source_resource)
|
||||
{
|
||||
@@ -375,7 +376,7 @@ destroy_selection_data_source (struct wl_listener *listener, void *data)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
meta_wayland_seat_set_selection (MetaWaylandSeat *seat,
|
||||
MetaWaylandDataSource *source,
|
||||
guint32 serial)
|
||||
@@ -389,7 +390,7 @@ meta_wayland_seat_set_selection (MetaWaylandSeat *seat,
|
||||
|
||||
if (seat->selection_data_source)
|
||||
{
|
||||
seat->selection_data_source->cancel (seat->selection_data_source);
|
||||
wl_data_source_send_cancelled (seat->selection_data_source->resource);
|
||||
wl_list_remove (&seat->selection_data_source_listener.link);
|
||||
seat->selection_data_source = NULL;
|
||||
}
|
||||
@@ -449,47 +450,21 @@ static const struct wl_data_device_interface data_device_interface = {
|
||||
static void
|
||||
destroy_data_source (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandDataSource *source = wl_container_of (resource, source, resource);
|
||||
MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
|
||||
char **p;
|
||||
|
||||
wl_array_for_each (p, &source->mime_types) free (*p);
|
||||
|
||||
wl_array_release (&source->mime_types);
|
||||
}
|
||||
|
||||
static void
|
||||
client_source_accept (MetaWaylandDataSource *source,
|
||||
guint32 time, const char *mime_type)
|
||||
{
|
||||
wl_data_source_send_target (source->resource, mime_type);
|
||||
}
|
||||
|
||||
static void
|
||||
client_source_send (MetaWaylandDataSource *source,
|
||||
const char *mime_type, int32_t fd)
|
||||
{
|
||||
wl_data_source_send_send (source->resource, mime_type, fd);
|
||||
close (fd);
|
||||
}
|
||||
|
||||
static void
|
||||
client_source_cancel (MetaWaylandDataSource *source)
|
||||
{
|
||||
wl_data_source_send_cancelled (source->resource);
|
||||
g_slice_free (MetaWaylandDataSource, source);
|
||||
}
|
||||
|
||||
static void
|
||||
create_data_source (struct wl_client *client,
|
||||
struct wl_resource *resource, guint32 id)
|
||||
{
|
||||
MetaWaylandDataSource *source;
|
||||
|
||||
source = malloc (sizeof *source);
|
||||
if (source == NULL)
|
||||
{
|
||||
wl_resource_post_no_memory (resource);
|
||||
return;
|
||||
}
|
||||
MetaWaylandDataSource *source = g_slice_new0 (MetaWaylandDataSource);
|
||||
|
||||
source->resource = wl_resource_create (client, &wl_data_source_interface,
|
||||
MIN (META_WL_DATA_SOURCE_VERSION,
|
||||
@@ -497,10 +472,6 @@ create_data_source (struct wl_client *client,
|
||||
wl_resource_set_implementation (source->resource, &data_source_interface,
|
||||
source, destroy_data_source);
|
||||
|
||||
source->accept = client_source_accept;
|
||||
source->send = client_source_send;
|
||||
source->cancel = client_source_cancel;
|
||||
|
||||
wl_array_init (&source->mime_types);
|
||||
}
|
||||
|
||||
|
@@ -33,10 +33,4 @@ meta_wayland_data_device_set_keyboard_focus (MetaWaylandSeat *seat);
|
||||
int
|
||||
meta_wayland_data_device_manager_init (struct wl_display *display);
|
||||
|
||||
void
|
||||
meta_wayland_seat_set_selection (MetaWaylandSeat *seat,
|
||||
MetaWaylandDataSource *source,
|
||||
uint32_t serial);
|
||||
|
||||
|
||||
#endif /* __META_WAYLAND_DATA_DEVICE_H__ */
|
||||
|
@@ -60,14 +60,6 @@
|
||||
|
||||
#include "meta-wayland-private.h"
|
||||
|
||||
static MetaWaylandSeat *
|
||||
meta_wayland_keyboard_get_seat (MetaWaylandKeyboard *keyboard)
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_container_of (keyboard, seat, keyboard);
|
||||
|
||||
return seat;
|
||||
}
|
||||
|
||||
static int
|
||||
create_anonymous_file (off_t size,
|
||||
GError **error)
|
||||
@@ -115,7 +107,7 @@ inform_clients_of_new_keymap (MetaWaylandKeyboard *keyboard,
|
||||
struct wl_resource *keyboard_resource;
|
||||
|
||||
compositor = meta_wayland_compositor_get_default ();
|
||||
xclient = compositor->xwayland_client;
|
||||
xclient = compositor->xwayland_manager.client;
|
||||
|
||||
wl_resource_for_each (keyboard_resource, &keyboard->resource_list)
|
||||
{
|
||||
@@ -146,23 +138,11 @@ meta_wayland_keyboard_take_keymap (MetaWaylandKeyboard *keyboard,
|
||||
return;
|
||||
}
|
||||
|
||||
if (xkb_info->keymap)
|
||||
xkb_keymap_unref (xkb_info->keymap);
|
||||
xkb_keymap_unref (xkb_info->keymap);
|
||||
xkb_info->keymap = keymap;
|
||||
|
||||
xkb_info->shift_mod =
|
||||
xkb_map_mod_get_index (xkb_info->keymap, XKB_MOD_NAME_SHIFT);
|
||||
xkb_info->caps_mod =
|
||||
xkb_map_mod_get_index (xkb_info->keymap, XKB_MOD_NAME_CAPS);
|
||||
xkb_info->ctrl_mod =
|
||||
xkb_map_mod_get_index (xkb_info->keymap, XKB_MOD_NAME_CTRL);
|
||||
xkb_info->alt_mod =
|
||||
xkb_map_mod_get_index (xkb_info->keymap, XKB_MOD_NAME_ALT);
|
||||
xkb_info->mod2_mod = xkb_map_mod_get_index (xkb_info->keymap, "Mod2");
|
||||
xkb_info->mod3_mod = xkb_map_mod_get_index (xkb_info->keymap, "Mod3");
|
||||
xkb_info->super_mod =
|
||||
xkb_map_mod_get_index (xkb_info->keymap, XKB_MOD_NAME_LOGO);
|
||||
xkb_info->mod5_mod = xkb_map_mod_get_index (xkb_info->keymap, "Mod5");
|
||||
xkb_state_unref (xkb_info->state);
|
||||
xkb_info->state = xkb_state_new (keymap);
|
||||
|
||||
keymap_str = xkb_map_get_as_string (xkb_info->keymap);
|
||||
if (keymap_str == NULL)
|
||||
@@ -201,13 +181,17 @@ meta_wayland_keyboard_take_keymap (MetaWaylandKeyboard *keyboard,
|
||||
strcpy (xkb_info->keymap_area, keymap_str);
|
||||
free (keymap_str);
|
||||
|
||||
if (keyboard->is_evdev)
|
||||
#if defined(CLUTTER_WINDOWING_EGL)
|
||||
/* XXX -- the evdev backend can be used regardless of the
|
||||
* windowing backend. To do this properly we need a Clutter
|
||||
* API to check the input backend. */
|
||||
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
|
||||
{
|
||||
ClutterDeviceManager *manager;
|
||||
|
||||
manager = clutter_device_manager_get_default ();
|
||||
clutter_evdev_set_keyboard_map (manager, xkb_info->keymap);
|
||||
}
|
||||
#endif
|
||||
|
||||
inform_clients_of_new_keymap (keyboard, flags);
|
||||
|
||||
@@ -222,13 +206,25 @@ err_keymap_str:
|
||||
}
|
||||
|
||||
static void
|
||||
lose_keyboard_focus (struct wl_listener *listener, void *data)
|
||||
keyboard_handle_focus_surface_destroy (struct wl_listener *listener, void *data)
|
||||
{
|
||||
MetaWaylandKeyboard *keyboard =
|
||||
wl_container_of (listener, keyboard, focus_listener);
|
||||
MetaWaylandKeyboard *keyboard = wl_container_of (listener, keyboard, focus_surface_listener);
|
||||
|
||||
keyboard->focus_surface = NULL;
|
||||
|
||||
if (keyboard->focus_resource)
|
||||
{
|
||||
wl_list_remove (&keyboard->focus_resource_listener.link);
|
||||
keyboard->focus_resource = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
keyboard_handle_focus_resource_destroy (struct wl_listener *listener, void *data)
|
||||
{
|
||||
MetaWaylandKeyboard *keyboard = wl_container_of (listener, keyboard, focus_resource_listener);
|
||||
|
||||
keyboard->focus_resource = NULL;
|
||||
keyboard->focus = NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -273,29 +269,11 @@ default_grab_modifiers (MetaWaylandKeyboardGrab *grab, uint32_t serial,
|
||||
uint32_t mods_locked, uint32_t group)
|
||||
{
|
||||
MetaWaylandKeyboard *keyboard = grab->keyboard;
|
||||
MetaWaylandSeat *seat = meta_wayland_keyboard_get_seat (keyboard);
|
||||
MetaWaylandPointer *pointer = &seat->pointer;
|
||||
struct wl_resource *resource, *pr;
|
||||
|
||||
resource = keyboard->focus_resource;
|
||||
if (!resource)
|
||||
return;
|
||||
|
||||
wl_keyboard_send_modifiers (resource, serial, mods_depressed,
|
||||
mods_latched, mods_locked, group);
|
||||
|
||||
if (pointer && pointer->focus && pointer->focus != keyboard->focus)
|
||||
if (keyboard->focus_resource)
|
||||
{
|
||||
pr = find_resource_for_surface (&keyboard->resource_list,
|
||||
pointer->focus);
|
||||
if (pr)
|
||||
{
|
||||
wl_keyboard_send_modifiers (pr, serial,
|
||||
mods_depressed,
|
||||
mods_latched,
|
||||
mods_locked,
|
||||
group);
|
||||
}
|
||||
wl_keyboard_send_modifiers (keyboard->focus_resource, serial, mods_depressed,
|
||||
mods_latched, mods_locked, group);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -305,42 +283,19 @@ static const MetaWaylandKeyboardGrabInterface
|
||||
default_grab_modifiers,
|
||||
};
|
||||
|
||||
static gboolean
|
||||
modal_key (MetaWaylandKeyboardGrab *grab,
|
||||
uint32_t time,
|
||||
uint32_t key,
|
||||
uint32_t state)
|
||||
{
|
||||
/* FALSE means: let the event through to clutter */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
modal_modifiers (MetaWaylandKeyboardGrab *grab,
|
||||
uint32_t serial,
|
||||
uint32_t mods_depressed,
|
||||
uint32_t mods_latched,
|
||||
uint32_t mods_locked,
|
||||
uint32_t group)
|
||||
{
|
||||
}
|
||||
|
||||
static MetaWaylandKeyboardGrabInterface modal_grab = {
|
||||
modal_key,
|
||||
modal_modifiers,
|
||||
};
|
||||
|
||||
gboolean
|
||||
meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
|
||||
struct wl_display *display,
|
||||
gboolean is_evdev)
|
||||
struct wl_display *display)
|
||||
{
|
||||
memset (keyboard, 0, sizeof *keyboard);
|
||||
keyboard->xkb_info.keymap_fd = -1;
|
||||
|
||||
wl_list_init (&keyboard->resource_list);
|
||||
wl_array_init (&keyboard->keys);
|
||||
keyboard->focus_listener.notify = lose_keyboard_focus;
|
||||
|
||||
keyboard->focus_surface_listener.notify = keyboard_handle_focus_surface_destroy;
|
||||
keyboard->focus_resource_listener.notify = keyboard_handle_focus_resource_destroy;
|
||||
|
||||
keyboard->default_grab.interface = &default_keyboard_grab_interface;
|
||||
keyboard->default_grab.keyboard = keyboard;
|
||||
keyboard->grab = &keyboard->default_grab;
|
||||
@@ -348,7 +303,6 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
|
||||
keyboard->display = display;
|
||||
|
||||
keyboard->xkb_context = xkb_context_new (0 /* flags */);
|
||||
keyboard->is_evdev = is_evdev;
|
||||
|
||||
/* Compute a default until gnome-settings-daemon starts and sets
|
||||
the appropriate values
|
||||
@@ -364,8 +318,8 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
|
||||
static void
|
||||
meta_wayland_xkb_info_destroy (MetaWaylandXkbInfo *xkb_info)
|
||||
{
|
||||
if (xkb_info->keymap)
|
||||
xkb_map_unref (xkb_info->keymap);
|
||||
xkb_keymap_unref (xkb_info->keymap);
|
||||
xkb_state_unref (xkb_info->state);
|
||||
|
||||
if (xkb_info->keymap_area)
|
||||
munmap (xkb_info->keymap_area, xkb_info->keymap_size);
|
||||
@@ -373,47 +327,7 @@ meta_wayland_xkb_info_destroy (MetaWaylandXkbInfo *xkb_info)
|
||||
close (xkb_info->keymap_fd);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
state_equal (MetaWaylandXkbState *one,
|
||||
MetaWaylandXkbState *two)
|
||||
{
|
||||
return one->mods_depressed == two->mods_depressed &&
|
||||
one->mods_latched == two->mods_latched &&
|
||||
one->mods_locked == two->mods_locked &&
|
||||
one->group == two->group;
|
||||
}
|
||||
|
||||
static void
|
||||
set_modifiers (MetaWaylandKeyboard *keyboard,
|
||||
guint32 serial,
|
||||
ClutterEvent *event)
|
||||
{
|
||||
MetaWaylandKeyboardGrab *grab = keyboard->grab;
|
||||
MetaWaylandXkbState new_state;
|
||||
guint effective_state;
|
||||
|
||||
clutter_event_get_state_full (event,
|
||||
NULL,
|
||||
&new_state.mods_depressed,
|
||||
&new_state.mods_latched,
|
||||
&new_state.mods_locked,
|
||||
&effective_state);
|
||||
new_state.group = (effective_state >> 13) & 0x3;
|
||||
|
||||
if (state_equal (&keyboard->modifier_state, &new_state))
|
||||
return;
|
||||
|
||||
keyboard->modifier_state = new_state;
|
||||
|
||||
grab->interface->modifiers (grab,
|
||||
serial,
|
||||
new_state.mods_depressed,
|
||||
new_state.mods_latched,
|
||||
new_state.mods_locked,
|
||||
new_state.group);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
update_pressed_keys (MetaWaylandKeyboard *keyboard,
|
||||
uint32_t evdev_code,
|
||||
gboolean is_press)
|
||||
@@ -424,13 +338,10 @@ update_pressed_keys (MetaWaylandKeyboard *keyboard,
|
||||
keyboard->keys.size);
|
||||
uint32_t *k;
|
||||
|
||||
/* We want to ignore events that are sent because of auto-repeat. In
|
||||
the Clutter event stream these appear as a single key press
|
||||
event. We can detect that because the key will already have been
|
||||
pressed */
|
||||
/* Make sure we don't already have this key. */
|
||||
for (k = keyboard->keys.data; k < end; k++)
|
||||
if (*k == evdev_code)
|
||||
return TRUE;
|
||||
return;
|
||||
|
||||
/* Otherwise add the key to the list of pressed keys */
|
||||
k = wl_array_add (&keyboard->keys, sizeof (*k));
|
||||
@@ -448,18 +359,44 @@ update_pressed_keys (MetaWaylandKeyboard *keyboard,
|
||||
{
|
||||
*k = *(end - 1);
|
||||
keyboard->keys.size -= sizeof (*k);
|
||||
|
||||
goto found;
|
||||
return;
|
||||
}
|
||||
|
||||
g_warning ("unexpected key release event for key 0x%x", evdev_code);
|
||||
return FALSE;
|
||||
|
||||
found:
|
||||
(void) 0;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
static guint
|
||||
evdev_code (const ClutterKeyEvent *event)
|
||||
{
|
||||
/* clutter-xkb-utils.c adds a fixed offset of 8 to go into XKB's
|
||||
* range, so we do the reverse here. */
|
||||
return event->hardware_keycode - 8;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_keyboard_update (MetaWaylandKeyboard *keyboard,
|
||||
const ClutterKeyEvent *event)
|
||||
{
|
||||
MetaWaylandKeyboardGrab *grab = keyboard->grab;
|
||||
gboolean is_press = event->type == CLUTTER_KEY_PRESS;
|
||||
struct xkb_state *state = keyboard->xkb_info.state;
|
||||
enum xkb_state_component changed_state;
|
||||
|
||||
update_pressed_keys (keyboard, evdev_code (event), is_press);
|
||||
|
||||
changed_state = xkb_state_update_key (state,
|
||||
event->hardware_keycode,
|
||||
is_press ? XKB_KEY_DOWN : XKB_KEY_UP);
|
||||
if (changed_state == 0)
|
||||
return;
|
||||
|
||||
grab->interface->modifiers (grab,
|
||||
wl_display_next_serial (keyboard->display),
|
||||
xkb_state_serialize_mods (state, XKB_STATE_MODS_DEPRESSED),
|
||||
xkb_state_serialize_mods (state, XKB_STATE_MODS_LATCHED),
|
||||
xkb_state_serialize_mods (state, XKB_STATE_MODS_LOCKED),
|
||||
xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_EFFECTIVE));
|
||||
}
|
||||
|
||||
gboolean
|
||||
@@ -467,34 +404,20 @@ meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard,
|
||||
const ClutterKeyEvent *event)
|
||||
{
|
||||
gboolean is_press = event->type == CLUTTER_KEY_PRESS;
|
||||
guint xkb_keycode, evdev_code;
|
||||
uint32_t serial;
|
||||
gboolean autorepeat;
|
||||
gboolean handled;
|
||||
|
||||
xkb_keycode = event->hardware_keycode;
|
||||
if (event->device == NULL ||
|
||||
!clutter_input_device_keycode_to_evdev (event->device,
|
||||
xkb_keycode, &evdev_code))
|
||||
evdev_code = xkb_keycode - 8; /* What everyone is doing in practice... */
|
||||
|
||||
autorepeat = update_pressed_keys (keyboard, evdev_code, is_press);
|
||||
|
||||
meta_verbose ("Handling key %s%s event code %d\n",
|
||||
is_press ? "press" : "release",
|
||||
autorepeat ? " (autorepeat)" : "",
|
||||
xkb_keycode);
|
||||
|
||||
if (autorepeat)
|
||||
/* Synthetic key events are for autorepeat. Ignore those, as
|
||||
* autorepeat in Wayland is done on the client side. */
|
||||
if (event->flags & CLUTTER_EVENT_FLAG_SYNTHETIC)
|
||||
return FALSE;
|
||||
|
||||
serial = wl_display_next_serial (keyboard->display);
|
||||
|
||||
set_modifiers (keyboard, serial, (ClutterEvent*)event);
|
||||
meta_verbose ("Handling key %s event code %d\n",
|
||||
is_press ? "press" : "release",
|
||||
event->hardware_keycode);
|
||||
|
||||
handled = keyboard->grab->interface->key (keyboard->grab,
|
||||
event->time,
|
||||
evdev_code,
|
||||
evdev_code (event),
|
||||
is_press);
|
||||
|
||||
if (handled)
|
||||
@@ -509,62 +432,54 @@ void
|
||||
meta_wayland_keyboard_set_focus (MetaWaylandKeyboard *keyboard,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
uint32_t serial;
|
||||
|
||||
if (keyboard->focus == surface && keyboard->focus_resource != NULL)
|
||||
if (keyboard->focus_surface == surface && keyboard->focus_resource != NULL)
|
||||
return;
|
||||
|
||||
resource = keyboard->focus_resource;
|
||||
if (keyboard->focus_resource && keyboard->focus->resource)
|
||||
if (keyboard->focus_surface != NULL)
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
serial = wl_display_next_serial (display);
|
||||
wl_keyboard_send_leave (resource, serial, keyboard->focus->resource);
|
||||
wl_list_remove (&keyboard->focus_listener.link);
|
||||
if (keyboard->focus_resource)
|
||||
{
|
||||
if (keyboard->focus_surface->resource)
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (keyboard->focus_resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
uint32_t serial = wl_display_next_serial (display);
|
||||
wl_keyboard_send_leave (keyboard->focus_resource, serial, keyboard->focus_surface->resource);
|
||||
}
|
||||
|
||||
meta_wayland_surface_focused_unset (keyboard->focus);
|
||||
wl_list_remove (&keyboard->focus_resource_listener.link);
|
||||
keyboard->focus_resource = NULL;
|
||||
}
|
||||
|
||||
wl_list_remove (&keyboard->focus_surface_listener.link);
|
||||
keyboard->focus_surface = NULL;
|
||||
}
|
||||
|
||||
resource = find_resource_for_surface (&keyboard->resource_list, surface);
|
||||
if (resource)
|
||||
if (surface != NULL)
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
keyboard->focus_surface = surface;
|
||||
wl_resource_add_destroy_listener (keyboard->focus_surface->resource, &keyboard->focus_surface_listener);
|
||||
|
||||
serial = wl_display_next_serial (display);
|
||||
keyboard->focus_resource = find_resource_for_surface (&keyboard->resource_list, surface);
|
||||
if (keyboard->focus_resource)
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (keyboard->focus_resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
struct xkb_state *state = keyboard->xkb_info.state;
|
||||
uint32_t serial = wl_display_next_serial (display);
|
||||
|
||||
/* If we're in a modal grab, the client is focused but doesn't see
|
||||
modifiers or pressed keys (and fix that up when we exit the modal) */
|
||||
if (keyboard->grab->interface == &modal_grab)
|
||||
{
|
||||
struct wl_array empty;
|
||||
wl_array_init (&empty);
|
||||
wl_keyboard_send_modifiers (keyboard->focus_resource, serial,
|
||||
xkb_state_serialize_mods (state, XKB_STATE_MODS_DEPRESSED),
|
||||
xkb_state_serialize_mods (state, XKB_STATE_MODS_LATCHED),
|
||||
xkb_state_serialize_mods (state, XKB_STATE_MODS_LOCKED),
|
||||
xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_EFFECTIVE));
|
||||
wl_keyboard_send_enter (keyboard->focus_resource, serial, keyboard->focus_surface->resource,
|
||||
&keyboard->keys);
|
||||
|
||||
wl_keyboard_send_modifiers (resource, serial,
|
||||
0, 0, 0, 0);
|
||||
wl_keyboard_send_enter (resource, serial, surface->resource,
|
||||
&empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
wl_keyboard_send_modifiers (resource, serial,
|
||||
keyboard->modifier_state.mods_depressed,
|
||||
keyboard->modifier_state.mods_latched,
|
||||
keyboard->modifier_state.mods_locked,
|
||||
keyboard->modifier_state.group);
|
||||
wl_keyboard_send_enter (resource, serial, surface->resource,
|
||||
&keyboard->keys);
|
||||
}
|
||||
wl_resource_add_destroy_listener (resource, &keyboard->focus_listener);
|
||||
keyboard->focus_serial = serial;
|
||||
|
||||
meta_wayland_surface_focused_set (surface);
|
||||
wl_resource_add_destroy_listener (keyboard->focus_resource, &keyboard->focus_resource_listener);
|
||||
keyboard->focus_serial = serial;
|
||||
}
|
||||
}
|
||||
|
||||
keyboard->focus_resource = resource;
|
||||
keyboard->focus = surface;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -590,90 +505,9 @@ meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard)
|
||||
xkb_context_unref (keyboard->xkb_context);
|
||||
|
||||
/* XXX: What about keyboard->resource_list? */
|
||||
if (keyboard->focus_resource)
|
||||
wl_list_remove (&keyboard->focus_listener.link);
|
||||
wl_array_release (&keyboard->keys);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_keyboard_begin_modal (MetaWaylandKeyboard *keyboard,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaWaylandKeyboardGrab *grab;
|
||||
uint32_t *end = (void *) ((char *) keyboard->keys.data +
|
||||
keyboard->keys.size);
|
||||
uint32_t *k;
|
||||
uint32_t serial;
|
||||
|
||||
meta_verbose ("Asked to acquire modal keyboard grab, timestamp %d\n", timestamp);
|
||||
|
||||
if (keyboard->grab != &keyboard->default_grab)
|
||||
return FALSE;
|
||||
|
||||
if (keyboard->focus)
|
||||
{
|
||||
/* Fake key release events for the focused app */
|
||||
serial = wl_display_next_serial (keyboard->display);
|
||||
keyboard->grab->interface->modifiers (keyboard->grab,
|
||||
serial,
|
||||
0, 0, 0, 0);
|
||||
|
||||
for (k = keyboard->keys.data; k < end; k++)
|
||||
{
|
||||
keyboard->grab->interface->key (keyboard->grab,
|
||||
timestamp,
|
||||
*k, 0);
|
||||
}
|
||||
}
|
||||
|
||||
grab = g_slice_new0 (MetaWaylandKeyboardGrab);
|
||||
grab->interface = &modal_grab;
|
||||
meta_wayland_keyboard_start_grab (keyboard, grab);
|
||||
|
||||
meta_verbose ("Acquired modal keyboard grab, timestamp %d\n", timestamp);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_keyboard_end_modal (MetaWaylandKeyboard *keyboard,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaWaylandKeyboardGrab *grab;
|
||||
uint32_t *end = (void *) ((char *) keyboard->keys.data +
|
||||
keyboard->keys.size);
|
||||
uint32_t *k;
|
||||
uint32_t serial;
|
||||
|
||||
grab = keyboard->grab;
|
||||
|
||||
g_assert (grab->interface == &modal_grab);
|
||||
|
||||
meta_wayland_keyboard_end_grab (keyboard);
|
||||
g_slice_free (MetaWaylandKeyboardGrab, grab);
|
||||
|
||||
if (keyboard->focus)
|
||||
{
|
||||
/* Fake key press events for the focused app */
|
||||
serial = wl_display_next_serial (keyboard->display);
|
||||
keyboard->grab->interface->modifiers (keyboard->grab,
|
||||
serial,
|
||||
keyboard->modifier_state.mods_depressed,
|
||||
keyboard->modifier_state.mods_latched,
|
||||
keyboard->modifier_state.mods_locked,
|
||||
keyboard->modifier_state.group);
|
||||
|
||||
for (k = keyboard->keys.data; k < end; k++)
|
||||
{
|
||||
keyboard->grab->interface->key (keyboard->grab,
|
||||
timestamp,
|
||||
*k, 1);
|
||||
}
|
||||
}
|
||||
|
||||
meta_verbose ("Released modal keyboard grab, timestamp %d\n", timestamp);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_keyboard_set_keymap_names (MetaWaylandKeyboard *keyboard,
|
||||
const char *rules,
|
||||
|
@@ -47,6 +47,7 @@
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <wayland-server.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
struct _MetaWaylandKeyboardGrabInterface
|
||||
{
|
||||
@@ -68,33 +69,20 @@ struct _MetaWaylandKeyboardGrab
|
||||
typedef struct
|
||||
{
|
||||
struct xkb_keymap *keymap;
|
||||
struct xkb_state *state;
|
||||
int keymap_fd;
|
||||
size_t keymap_size;
|
||||
char *keymap_area;
|
||||
xkb_mod_index_t shift_mod;
|
||||
xkb_mod_index_t caps_mod;
|
||||
xkb_mod_index_t ctrl_mod;
|
||||
xkb_mod_index_t alt_mod;
|
||||
xkb_mod_index_t mod2_mod;
|
||||
xkb_mod_index_t mod3_mod;
|
||||
xkb_mod_index_t super_mod;
|
||||
xkb_mod_index_t mod5_mod;
|
||||
} MetaWaylandXkbInfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t mods_depressed;
|
||||
uint32_t mods_latched;
|
||||
uint32_t mods_locked;
|
||||
uint32_t group;
|
||||
} MetaWaylandXkbState;
|
||||
|
||||
struct _MetaWaylandKeyboard
|
||||
{
|
||||
struct wl_list resource_list;
|
||||
MetaWaylandSurface *focus;
|
||||
|
||||
MetaWaylandSurface *focus_surface;
|
||||
struct wl_listener focus_surface_listener;
|
||||
struct wl_resource *focus_resource;
|
||||
struct wl_listener focus_listener;
|
||||
struct wl_listener focus_resource_listener;
|
||||
uint32_t focus_serial;
|
||||
|
||||
MetaWaylandKeyboardGrab *grab;
|
||||
@@ -105,12 +93,9 @@ struct _MetaWaylandKeyboard
|
||||
|
||||
struct wl_array keys;
|
||||
|
||||
MetaWaylandXkbState modifier_state;
|
||||
|
||||
struct wl_display *display;
|
||||
|
||||
struct xkb_context *xkb_context;
|
||||
gboolean is_evdev;
|
||||
MetaWaylandXkbInfo xkb_info;
|
||||
|
||||
MetaWaylandKeyboardGrab input_method_grab;
|
||||
@@ -119,8 +104,7 @@ struct _MetaWaylandKeyboard
|
||||
|
||||
gboolean
|
||||
meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
|
||||
struct wl_display *display,
|
||||
gboolean is_evdev);
|
||||
struct wl_display *display);
|
||||
|
||||
typedef enum {
|
||||
META_WAYLAND_KEYBOARD_SKIP_XCLIENTS = 1,
|
||||
@@ -149,14 +133,11 @@ meta_wayland_keyboard_start_grab (MetaWaylandKeyboard *device,
|
||||
void
|
||||
meta_wayland_keyboard_end_grab (MetaWaylandKeyboard *keyboard);
|
||||
|
||||
gboolean
|
||||
meta_wayland_keyboard_begin_modal (MetaWaylandKeyboard *keyboard,
|
||||
guint32 timestamp);
|
||||
void
|
||||
meta_wayland_keyboard_end_modal (MetaWaylandKeyboard *keyboard,
|
||||
guint32 timestamp);
|
||||
|
||||
void
|
||||
meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard);
|
||||
|
||||
void
|
||||
meta_wayland_keyboard_update (MetaWaylandKeyboard *keyboard,
|
||||
const ClutterKeyEvent *event);
|
||||
|
||||
#endif /* __META_WAYLAND_KEYBOARD_H__ */
|
||||
|
@@ -49,34 +49,36 @@
|
||||
|
||||
#include "meta-wayland-pointer.h"
|
||||
#include "meta-wayland-private.h"
|
||||
#include "xdg-shell-server-protocol.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static void meta_wayland_pointer_end_popup_grab (MetaWaylandPointer *pointer);
|
||||
|
||||
static MetaWaylandSeat *
|
||||
meta_wayland_pointer_get_seat (MetaWaylandPointer *pointer)
|
||||
static void
|
||||
pointer_handle_focus_surface_destroy (struct wl_listener *listener, void *data)
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_container_of (pointer, seat, pointer);
|
||||
MetaWaylandPointer *pointer = wl_container_of (listener, pointer, focus_surface_listener);
|
||||
|
||||
return seat;
|
||||
pointer->focus_surface = NULL;
|
||||
|
||||
if (pointer->focus_resource)
|
||||
{
|
||||
wl_list_remove (&pointer->focus_resource_listener.link);
|
||||
pointer->focus_resource = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
lose_pointer_focus (struct wl_listener *listener, void *data)
|
||||
pointer_handle_focus_resource_destroy (struct wl_listener *listener, void *data)
|
||||
{
|
||||
MetaWaylandPointer *pointer =
|
||||
wl_container_of (listener, pointer, focus_listener);
|
||||
MetaWaylandPointer *pointer = wl_container_of (listener, pointer, focus_resource_listener);
|
||||
|
||||
pointer->focus_resource = NULL;
|
||||
pointer->focus = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
default_grab_focus (MetaWaylandPointerGrab *grab,
|
||||
MetaWaylandSurface *surface,
|
||||
const ClutterEvent *event)
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
MetaWaylandPointer *pointer = grab->pointer;
|
||||
|
||||
@@ -98,7 +100,7 @@ default_grab_motion (MetaWaylandPointerGrab *grab,
|
||||
wl_fixed_t sx, sy;
|
||||
|
||||
meta_wayland_pointer_get_relative_coordinates (grab->pointer,
|
||||
grab->pointer->focus,
|
||||
grab->pointer->focus_surface,
|
||||
&sx, &sy);
|
||||
wl_pointer_send_motion (resource, clutter_event_get_time (event), sx, sy);
|
||||
}
|
||||
@@ -258,8 +260,7 @@ pointer_constrain_callback (ClutterInputDevice *device,
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_pointer_init (MetaWaylandPointer *pointer,
|
||||
gboolean is_native)
|
||||
meta_wayland_pointer_init (MetaWaylandPointer *pointer)
|
||||
{
|
||||
ClutterDeviceManager *manager;
|
||||
ClutterInputDevice *device;
|
||||
@@ -267,7 +268,10 @@ meta_wayland_pointer_init (MetaWaylandPointer *pointer,
|
||||
|
||||
memset (pointer, 0, sizeof *pointer);
|
||||
wl_list_init (&pointer->resource_list);
|
||||
pointer->focus_listener.notify = lose_pointer_focus;
|
||||
|
||||
pointer->focus_surface_listener.notify = pointer_handle_focus_surface_destroy;
|
||||
pointer->focus_resource_listener.notify = pointer_handle_focus_resource_destroy;
|
||||
|
||||
pointer->default_grab.interface = &default_pointer_grab_interface;
|
||||
pointer->default_grab.pointer = pointer;
|
||||
pointer->grab = &pointer->default_grab;
|
||||
@@ -275,9 +279,16 @@ meta_wayland_pointer_init (MetaWaylandPointer *pointer,
|
||||
manager = clutter_device_manager_get_default ();
|
||||
device = clutter_device_manager_get_core_device (manager, CLUTTER_POINTER_DEVICE);
|
||||
|
||||
if (is_native)
|
||||
clutter_evdev_set_pointer_constrain_callback (manager, pointer_constrain_callback,
|
||||
pointer, NULL);
|
||||
#if defined(CLUTTER_WINDOWING_EGL)
|
||||
/* XXX -- the evdev backend can be used regardless of the
|
||||
* windowing backend. To do this properly we need a Clutter
|
||||
* API to check the input backend. */
|
||||
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
|
||||
{
|
||||
clutter_evdev_set_pointer_constrain_callback (manager, pointer_constrain_callback,
|
||||
pointer, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
clutter_input_device_get_coords (device, NULL, ¤t);
|
||||
pointer->x = wl_fixed_from_double (current.x);
|
||||
@@ -287,12 +298,7 @@ meta_wayland_pointer_init (MetaWaylandPointer *pointer,
|
||||
void
|
||||
meta_wayland_pointer_release (MetaWaylandPointer *pointer)
|
||||
{
|
||||
/* XXX: What about pointer->resource_list? */
|
||||
if (pointer->focus_resource)
|
||||
wl_list_remove (&pointer->focus_listener.link);
|
||||
|
||||
pointer->focus = NULL;
|
||||
pointer->focus_resource = NULL;
|
||||
/* Do nothing. */
|
||||
}
|
||||
|
||||
static struct wl_resource *
|
||||
@@ -313,64 +319,58 @@ void
|
||||
meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
MetaWaylandSeat *seat = meta_wayland_pointer_get_seat (pointer);
|
||||
MetaWaylandKeyboard *kbd = &seat->keyboard;
|
||||
struct wl_resource *resource, *kr;
|
||||
uint32_t serial;
|
||||
|
||||
if (pointer->focus == surface && pointer->focus_resource != NULL)
|
||||
if (pointer->focus_surface == surface && pointer->focus_resource != NULL)
|
||||
return;
|
||||
|
||||
resource = pointer->focus_resource;
|
||||
if (resource)
|
||||
if (pointer->focus_surface)
|
||||
{
|
||||
if (pointer->focus->resource)
|
||||
if (pointer->focus_resource)
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
serial = wl_display_next_serial (display);
|
||||
wl_pointer_send_leave (resource, serial, pointer->focus->resource);
|
||||
}
|
||||
|
||||
wl_list_remove (&pointer->focus_listener.link);
|
||||
}
|
||||
|
||||
resource = find_resource_for_surface (&pointer->resource_list, surface);
|
||||
if (resource)
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
wl_fixed_t sx, sy;
|
||||
|
||||
serial = wl_display_next_serial (display);
|
||||
|
||||
if (kbd)
|
||||
{
|
||||
kr = find_resource_for_surface (&kbd->resource_list, surface);
|
||||
if (kr)
|
||||
if (pointer->focus_surface->resource)
|
||||
{
|
||||
wl_keyboard_send_modifiers (kr,
|
||||
serial,
|
||||
kbd->modifier_state.mods_depressed,
|
||||
kbd->modifier_state.mods_latched,
|
||||
kbd->modifier_state.mods_locked,
|
||||
kbd->modifier_state.group);
|
||||
struct wl_client *client = wl_resource_get_client (pointer->focus_resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
uint32_t serial = wl_display_next_serial (display);
|
||||
wl_pointer_send_leave (pointer->focus_resource, serial, pointer->focus_surface->resource);
|
||||
}
|
||||
|
||||
wl_list_remove (&pointer->focus_resource_listener.link);
|
||||
pointer->focus_resource = NULL;
|
||||
}
|
||||
|
||||
meta_wayland_pointer_get_relative_coordinates (pointer, surface, &sx, &sy);
|
||||
meta_window_handle_enter (surface->window,
|
||||
/* XXX -- can we reliably get a timestamp for setting focus? */
|
||||
clutter_get_current_event_time (),
|
||||
wl_fixed_to_int (pointer->x),
|
||||
wl_fixed_to_int (pointer->y));
|
||||
wl_pointer_send_enter (resource, serial, surface->resource, sx, sy);
|
||||
wl_resource_add_destroy_listener (resource, &pointer->focus_listener);
|
||||
pointer->focus_serial = serial;
|
||||
wl_list_remove (&pointer->focus_surface_listener.link);
|
||||
pointer->focus_surface = NULL;
|
||||
}
|
||||
|
||||
pointer->focus_resource = resource;
|
||||
pointer->focus = surface;
|
||||
if (surface != NULL)
|
||||
{
|
||||
pointer->focus_surface = surface;
|
||||
wl_resource_add_destroy_listener (pointer->focus_surface->resource, &pointer->focus_surface_listener);
|
||||
|
||||
pointer->focus_resource = find_resource_for_surface (&pointer->resource_list, surface);
|
||||
if (pointer->focus_resource)
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (pointer->focus_resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
uint32_t serial = wl_display_next_serial (display);
|
||||
|
||||
meta_window_handle_enter (pointer->focus_surface->window,
|
||||
/* XXX -- can we reliably get a timestamp for setting focus? */
|
||||
clutter_get_current_event_time (),
|
||||
wl_fixed_to_int (pointer->x),
|
||||
wl_fixed_to_int (pointer->y));
|
||||
|
||||
{
|
||||
wl_fixed_t sx, sy;
|
||||
|
||||
meta_wayland_pointer_get_relative_coordinates (pointer, pointer->focus_surface, &sx, &sy);
|
||||
wl_pointer_send_enter (pointer->focus_resource, serial, pointer->focus_surface->resource, sx, sy);
|
||||
}
|
||||
|
||||
wl_resource_add_destroy_listener (pointer->focus_resource, &pointer->focus_resource_listener);
|
||||
pointer->focus_serial = serial;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -384,7 +384,7 @@ meta_wayland_pointer_start_grab (MetaWaylandPointer *pointer,
|
||||
grab->pointer = pointer;
|
||||
|
||||
if (pointer->current)
|
||||
interface->focus (pointer->grab, pointer->current, NULL);
|
||||
interface->focus (pointer->grab, pointer->current);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -394,62 +394,7 @@ meta_wayland_pointer_end_grab (MetaWaylandPointer *pointer)
|
||||
|
||||
pointer->grab = &pointer->default_grab;
|
||||
interface = pointer->grab->interface;
|
||||
interface->focus (pointer->grab, pointer->current, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
modal_focus (MetaWaylandPointerGrab *grab,
|
||||
MetaWaylandSurface *surface,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
modal_motion (MetaWaylandPointerGrab *grab,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
modal_button (MetaWaylandPointerGrab *grab,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
}
|
||||
|
||||
static MetaWaylandPointerGrabInterface modal_grab = {
|
||||
modal_focus,
|
||||
modal_motion,
|
||||
modal_button
|
||||
};
|
||||
|
||||
gboolean
|
||||
meta_wayland_pointer_begin_modal (MetaWaylandPointer *pointer)
|
||||
{
|
||||
MetaWaylandPointerGrab *grab;
|
||||
|
||||
if (pointer->grab != &pointer->default_grab)
|
||||
return FALSE;
|
||||
|
||||
meta_wayland_pointer_set_focus (pointer, NULL);
|
||||
|
||||
grab = g_slice_new0 (MetaWaylandPointerGrab);
|
||||
grab->interface = &modal_grab;
|
||||
meta_wayland_pointer_start_grab (pointer, grab);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_pointer_end_modal (MetaWaylandPointer *pointer)
|
||||
{
|
||||
MetaWaylandPointerGrab *grab;
|
||||
|
||||
grab = pointer->grab;
|
||||
|
||||
g_assert (grab->interface == &modal_grab);
|
||||
|
||||
meta_wayland_pointer_end_grab (pointer);
|
||||
g_slice_free (MetaWaylandPointerGrab, grab);
|
||||
interface->focus (pointer->grab, pointer->current);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
@@ -469,15 +414,14 @@ typedef struct {
|
||||
|
||||
static void
|
||||
popup_grab_focus (MetaWaylandPointerGrab *grab,
|
||||
MetaWaylandSurface *surface,
|
||||
const ClutterEvent *event)
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
MetaWaylandPopupGrab *popup_grab = (MetaWaylandPopupGrab*)grab;
|
||||
|
||||
/* Popup grabs are in owner-events mode (ie, events for the same client
|
||||
are reported as normal) */
|
||||
if (surface && wl_resource_get_client (surface->resource) == popup_grab->grab_client)
|
||||
default_grab_focus (grab, surface, event);
|
||||
default_grab_focus (grab, surface);
|
||||
else
|
||||
meta_wayland_pointer_set_focus (grab->pointer, NULL);
|
||||
}
|
||||
@@ -526,19 +470,18 @@ meta_wayland_pointer_end_popup_grab (MetaWaylandPointer *pointer)
|
||||
|
||||
wl_list_for_each_safe (popup, tmp, &popup_grab->all_popups, link)
|
||||
{
|
||||
MetaWaylandSurfaceExtension *xdg_popup = &popup->surface->xdg_popup;
|
||||
struct wl_client *client = wl_resource_get_client (xdg_popup->resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
uint32_t serial;
|
||||
|
||||
serial = wl_display_next_serial (display);
|
||||
|
||||
xdg_popup_send_popup_done (xdg_popup->resource, serial);
|
||||
meta_wayland_surface_popup_done (popup->surface);
|
||||
wl_list_remove (&popup->surface_destroy_listener.link);
|
||||
wl_list_remove (&popup->link);
|
||||
g_slice_free (MetaWaylandPopup, popup);
|
||||
}
|
||||
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
meta_display_end_grab_op (display,
|
||||
meta_display_get_current_time_roundtrip (display));
|
||||
}
|
||||
|
||||
meta_wayland_pointer_end_grab (pointer);
|
||||
g_slice_free (MetaWaylandPopupGrab, popup_grab);
|
||||
}
|
||||
@@ -567,19 +510,19 @@ meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
|
||||
|
||||
if (pointer->grab != &pointer->default_grab)
|
||||
{
|
||||
if (pointer->grab->interface == &popup_grab_interface)
|
||||
{
|
||||
grab = (MetaWaylandPopupGrab*)pointer->grab;
|
||||
if (pointer->grab->interface != &popup_grab_interface)
|
||||
return FALSE;
|
||||
|
||||
if (wl_resource_get_client (surface->resource) != grab->grab_client)
|
||||
return FALSE;
|
||||
}
|
||||
grab = (MetaWaylandPopupGrab*)pointer->grab;
|
||||
|
||||
return FALSE;
|
||||
if (wl_resource_get_client (surface->resource) != grab->grab_client)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (pointer->grab == &pointer->default_grab)
|
||||
{
|
||||
MetaWindow *window = surface->window;
|
||||
|
||||
grab = g_slice_new0 (MetaWaylandPopupGrab);
|
||||
grab->generic.interface = &popup_grab_interface;
|
||||
grab->generic.pointer = pointer;
|
||||
@@ -587,6 +530,19 @@ meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
|
||||
wl_list_init (&grab->all_popups);
|
||||
|
||||
meta_wayland_pointer_start_grab (pointer, (MetaWaylandPointerGrab*)grab);
|
||||
|
||||
meta_display_begin_grab_op (window->display,
|
||||
window->screen,
|
||||
window,
|
||||
META_GRAB_OP_WAYLAND_CLIENT,
|
||||
FALSE, /* pointer_already_grabbed */
|
||||
FALSE, /* frame_action */
|
||||
1, /* button. XXX? */
|
||||
0, /* modmask */
|
||||
meta_display_get_current_time_roundtrip (window->display),
|
||||
wl_fixed_to_int (pointer->grab_x),
|
||||
wl_fixed_to_int (pointer->grab_y));
|
||||
|
||||
}
|
||||
else
|
||||
grab = (MetaWaylandPopupGrab*)pointer->grab;
|
||||
@@ -595,10 +551,12 @@ meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
|
||||
popup->grab = grab;
|
||||
popup->surface = surface;
|
||||
popup->surface_destroy_listener.notify = on_popup_surface_destroy;
|
||||
wl_resource_add_destroy_listener (surface->xdg_popup.resource, &popup->surface_destroy_listener);
|
||||
if (surface->xdg_popup.resource)
|
||||
wl_resource_add_destroy_listener (surface->xdg_popup.resource, &popup->surface_destroy_listener);
|
||||
else if (surface->wl_shell_surface.resource)
|
||||
wl_resource_add_destroy_listener (surface->wl_shell_surface.resource, &popup->surface_destroy_listener);
|
||||
|
||||
wl_list_insert (&grab->all_popups, &popup->link);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -625,3 +583,16 @@ meta_wayland_pointer_get_relative_coordinates (MetaWaylandPointer *pointer,
|
||||
*sx = wl_fixed_from_double (xf);
|
||||
*sy = wl_fixed_from_double (yf);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_pointer_update_current_focus (MetaWaylandPointer *pointer,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
pointer->current = surface;
|
||||
if (surface != pointer->focus_surface)
|
||||
{
|
||||
const MetaWaylandPointerGrabInterface *interface =
|
||||
pointer->grab->interface;
|
||||
interface->focus (pointer->grab, surface);
|
||||
}
|
||||
}
|
||||
|
@@ -29,8 +29,7 @@
|
||||
struct _MetaWaylandPointerGrabInterface
|
||||
{
|
||||
void (*focus) (MetaWaylandPointerGrab *grab,
|
||||
MetaWaylandSurface *surface,
|
||||
const ClutterEvent *event);
|
||||
MetaWaylandSurface *surface);
|
||||
void (*motion) (MetaWaylandPointerGrab *grab,
|
||||
const ClutterEvent *event);
|
||||
void (*button) (MetaWaylandPointerGrab *grab,
|
||||
@@ -46,9 +45,11 @@ struct _MetaWaylandPointerGrab
|
||||
struct _MetaWaylandPointer
|
||||
{
|
||||
struct wl_list resource_list;
|
||||
MetaWaylandSurface *focus;
|
||||
|
||||
MetaWaylandSurface *focus_surface;
|
||||
struct wl_listener focus_surface_listener;
|
||||
struct wl_resource *focus_resource;
|
||||
struct wl_listener focus_listener;
|
||||
struct wl_listener focus_resource_listener;
|
||||
guint32 focus_serial;
|
||||
guint32 click_serial;
|
||||
|
||||
@@ -67,8 +68,7 @@ struct _MetaWaylandPointer
|
||||
};
|
||||
|
||||
void
|
||||
meta_wayland_pointer_init (MetaWaylandPointer *pointer,
|
||||
gboolean is_native);
|
||||
meta_wayland_pointer_init (MetaWaylandPointer *pointer);
|
||||
|
||||
void
|
||||
meta_wayland_pointer_release (MetaWaylandPointer *pointer);
|
||||
@@ -84,11 +84,6 @@ meta_wayland_pointer_start_grab (MetaWaylandPointer *pointer,
|
||||
void
|
||||
meta_wayland_pointer_end_grab (MetaWaylandPointer *pointer);
|
||||
|
||||
gboolean
|
||||
meta_wayland_pointer_begin_modal (MetaWaylandPointer *pointer);
|
||||
void
|
||||
meta_wayland_pointer_end_modal (MetaWaylandPointer *pointer);
|
||||
|
||||
gboolean
|
||||
meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
|
||||
MetaWaylandSurface *popup);
|
||||
@@ -99,4 +94,8 @@ meta_wayland_pointer_get_relative_coordinates (MetaWaylandPointer *pointer,
|
||||
wl_fixed_t *x,
|
||||
wl_fixed_t *y);
|
||||
|
||||
void
|
||||
meta_wayland_pointer_update_current_focus (MetaWaylandPointer *pointer,
|
||||
MetaWaylandSurface *surface);
|
||||
|
||||
#endif /* __META_WAYLAND_POINTER_H__ */
|
||||
|
@@ -21,7 +21,6 @@
|
||||
#define META_WAYLAND_PRIVATE_H
|
||||
|
||||
#include <wayland-server.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include <glib.h>
|
||||
@@ -31,7 +30,7 @@
|
||||
#include "meta-weston-launch.h"
|
||||
#include <meta/meta-cursor-tracker.h>
|
||||
|
||||
#include "meta-wayland-types.h"
|
||||
#include "meta-wayland.h"
|
||||
#include "meta-wayland-versions.h"
|
||||
#include "meta-wayland-surface.h"
|
||||
#include "meta-wayland-seat.h"
|
||||
@@ -59,58 +58,40 @@ typedef struct
|
||||
struct wl_resource *resource;
|
||||
} MetaWaylandFrameCallback;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int display_index;
|
||||
char *lockfile;
|
||||
int abstract_fd;
|
||||
int unix_fd;
|
||||
pid_t pid;
|
||||
struct wl_client *client;
|
||||
struct wl_resource *xserver_resource;
|
||||
char *display_name;
|
||||
|
||||
GMainLoop *init_loop;
|
||||
} MetaXWaylandManager;
|
||||
|
||||
struct _MetaWaylandCompositor
|
||||
{
|
||||
struct wl_display *wayland_display;
|
||||
char *display_name;
|
||||
struct wl_event_loop *wayland_loop;
|
||||
GMainLoop *init_loop;
|
||||
ClutterActor *stage;
|
||||
GHashTable *outputs;
|
||||
GSource *wayland_event_source;
|
||||
GList *surfaces;
|
||||
struct wl_list frame_callbacks;
|
||||
|
||||
int xwayland_display_index;
|
||||
char *xwayland_lockfile;
|
||||
int xwayland_abstract_fd;
|
||||
int xwayland_unix_fd;
|
||||
pid_t xwayland_pid;
|
||||
struct wl_client *xwayland_client;
|
||||
struct wl_resource *xserver_resource;
|
||||
MetaXWaylandManager xwayland_manager;
|
||||
|
||||
MetaLauncher *launcher;
|
||||
gboolean native;
|
||||
|
||||
MetaWaylandSeat *seat;
|
||||
};
|
||||
|
||||
void meta_wayland_init (void);
|
||||
void meta_wayland_finalize (void);
|
||||
|
||||
/* We maintain a singleton MetaWaylandCompositor which can be got at via this
|
||||
* API after meta_wayland_init() has been called. */
|
||||
MetaWaylandCompositor *meta_wayland_compositor_get_default (void);
|
||||
|
||||
void meta_wayland_compositor_repick (MetaWaylandCompositor *compositor);
|
||||
|
||||
void meta_wayland_compositor_set_input_focus (MetaWaylandCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
gboolean meta_wayland_compositor_handle_event (MetaWaylandCompositor *compositor,
|
||||
const ClutterEvent *event);
|
||||
|
||||
gboolean meta_wayland_compositor_is_native (MetaWaylandCompositor *compositor);
|
||||
|
||||
MetaWaylandBuffer * meta_wayland_buffer_from_resource (struct wl_resource *resource);
|
||||
void meta_wayland_buffer_ref (MetaWaylandBuffer *buffer);
|
||||
void meta_wayland_buffer_unref (MetaWaylandBuffer *buffer);
|
||||
|
||||
void meta_wayland_compositor_update (MetaWaylandCompositor *compositor,
|
||||
const ClutterEvent *event);
|
||||
void meta_wayland_compositor_paint_finished (MetaWaylandCompositor *compositor);
|
||||
|
||||
gboolean meta_wayland_compositor_activate_vt (MetaWaylandCompositor *compositor,
|
||||
int vt,
|
||||
GError **error);
|
||||
|
||||
#endif /* META_WAYLAND_PRIVATE_H */
|
||||
|
@@ -38,6 +38,7 @@
|
||||
#include "meta-shaped-texture-private.h"
|
||||
#include "meta-wayland-stage.h"
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
#include "meta-surface-actor-wayland.h"
|
||||
|
||||
#define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int (10)
|
||||
|
||||
@@ -95,9 +96,9 @@ pointer_set_cursor (struct wl_client *client,
|
||||
|
||||
surface = (surface_resource ? wl_resource_get_user_data (surface_resource) : NULL);
|
||||
|
||||
if (seat->pointer.focus == NULL)
|
||||
if (seat->pointer.focus_surface == NULL)
|
||||
return;
|
||||
if (wl_resource_get_client (seat->pointer.focus->resource) != client)
|
||||
if (wl_resource_get_client (seat->pointer.focus_surface->resource) != client)
|
||||
return;
|
||||
if (seat->pointer.focus_serial - serial > G_MAXUINT32 / 2)
|
||||
return;
|
||||
@@ -125,9 +126,9 @@ seat_get_pointer (struct wl_client *client,
|
||||
wl_resource_set_implementation (cr, &pointer_interface, seat, unbind_resource);
|
||||
wl_list_insert (&seat->pointer.resource_list, wl_resource_get_link (cr));
|
||||
|
||||
if (seat->pointer.focus &&
|
||||
wl_resource_get_client (seat->pointer.focus->resource) == client)
|
||||
meta_wayland_pointer_set_focus (&seat->pointer, seat->pointer.focus);
|
||||
if (seat->pointer.focus_surface &&
|
||||
wl_resource_get_client (seat->pointer.focus_surface->resource) == client)
|
||||
meta_wayland_pointer_set_focus (&seat->pointer, seat->pointer.focus_surface);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -148,10 +149,10 @@ seat_get_keyboard (struct wl_client *client,
|
||||
seat->keyboard.xkb_info.keymap_fd,
|
||||
seat->keyboard.xkb_info.keymap_size);
|
||||
|
||||
if (seat->keyboard.focus &&
|
||||
wl_resource_get_client (seat->keyboard.focus->resource) == client)
|
||||
if (seat->keyboard.focus_surface &&
|
||||
wl_resource_get_client (seat->keyboard.focus_surface->resource) == client)
|
||||
{
|
||||
meta_wayland_keyboard_set_focus (&seat->keyboard, seat->keyboard.focus);
|
||||
meta_wayland_keyboard_set_focus (&seat->keyboard, seat->keyboard.focus_surface);
|
||||
meta_wayland_data_device_set_keyboard_focus (seat);
|
||||
}
|
||||
}
|
||||
@@ -204,8 +205,7 @@ pointer_handle_cursor_surface_destroy (struct wl_listener *listener, void *data)
|
||||
}
|
||||
|
||||
MetaWaylandSeat *
|
||||
meta_wayland_seat_new (struct wl_display *display,
|
||||
gboolean is_native)
|
||||
meta_wayland_seat_new (struct wl_display *display)
|
||||
{
|
||||
MetaWaylandSeat *seat = g_new0 (MetaWaylandSeat, 1);
|
||||
|
||||
@@ -213,9 +213,8 @@ meta_wayland_seat_new (struct wl_display *display,
|
||||
wl_list_init (&seat->base_resource_list);
|
||||
wl_list_init (&seat->data_device_resource_list);
|
||||
|
||||
meta_wayland_pointer_init (&seat->pointer, is_native);
|
||||
|
||||
meta_wayland_keyboard_init (&seat->keyboard, display, is_native);
|
||||
meta_wayland_pointer_init (&seat->pointer);
|
||||
meta_wayland_keyboard_init (&seat->keyboard, display);
|
||||
|
||||
seat->display = display;
|
||||
|
||||
@@ -277,42 +276,53 @@ static void
|
||||
handle_scroll_event (MetaWaylandSeat *seat,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
enum wl_pointer_axis axis;
|
||||
wl_fixed_t value;
|
||||
wl_fixed_t x_value = 0, y_value = 0;
|
||||
|
||||
notify_motion (seat, event);
|
||||
|
||||
if (!seat->pointer.focus_resource)
|
||||
return;
|
||||
|
||||
if (clutter_event_is_pointer_emulated (event))
|
||||
return;
|
||||
|
||||
switch (clutter_event_get_scroll_direction (event))
|
||||
{
|
||||
case CLUTTER_SCROLL_UP:
|
||||
axis = WL_POINTER_AXIS_VERTICAL_SCROLL;
|
||||
value = -DEFAULT_AXIS_STEP_DISTANCE;
|
||||
y_value = -DEFAULT_AXIS_STEP_DISTANCE;
|
||||
break;
|
||||
|
||||
case CLUTTER_SCROLL_DOWN:
|
||||
axis = WL_POINTER_AXIS_VERTICAL_SCROLL;
|
||||
value = DEFAULT_AXIS_STEP_DISTANCE;
|
||||
y_value = DEFAULT_AXIS_STEP_DISTANCE;
|
||||
break;
|
||||
|
||||
case CLUTTER_SCROLL_LEFT:
|
||||
axis = WL_POINTER_AXIS_HORIZONTAL_SCROLL;
|
||||
value = -DEFAULT_AXIS_STEP_DISTANCE;
|
||||
x_value = -DEFAULT_AXIS_STEP_DISTANCE;
|
||||
break;
|
||||
|
||||
case CLUTTER_SCROLL_RIGHT:
|
||||
axis = WL_POINTER_AXIS_HORIZONTAL_SCROLL;
|
||||
value = DEFAULT_AXIS_STEP_DISTANCE;
|
||||
x_value = DEFAULT_AXIS_STEP_DISTANCE;
|
||||
break;
|
||||
|
||||
case CLUTTER_SCROLL_SMOOTH:
|
||||
{
|
||||
double dx, dy;
|
||||
clutter_event_get_scroll_delta (event, &dx, &dy);
|
||||
x_value = wl_fixed_from_double (dx);
|
||||
y_value = wl_fixed_from_double (dy);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (seat->pointer.focus_resource)
|
||||
wl_pointer_send_axis (seat->pointer.focus_resource,
|
||||
clutter_event_get_time (event),
|
||||
axis,
|
||||
value);
|
||||
if (x_value)
|
||||
wl_pointer_send_axis (seat->pointer.focus_resource, clutter_event_get_time (event),
|
||||
WL_POINTER_AXIS_HORIZONTAL_SCROLL, x_value);
|
||||
if (y_value)
|
||||
wl_pointer_send_axis (seat->pointer.focus_resource, clutter_event_get_time (event),
|
||||
WL_POINTER_AXIS_VERTICAL_SCROLL, y_value);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -337,7 +347,7 @@ count_buttons (const ClutterEvent *event)
|
||||
return count;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
meta_wayland_seat_update_pointer (MetaWaylandSeat *seat,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
@@ -360,6 +370,27 @@ meta_wayland_seat_update_pointer (MetaWaylandSeat *seat,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_seat_update (MetaWaylandSeat *seat,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_MOTION:
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
case CLUTTER_SCROLL:
|
||||
meta_wayland_seat_update_pointer (seat, event);
|
||||
break;
|
||||
case CLUTTER_KEY_PRESS:
|
||||
case CLUTTER_KEY_RELEASE:
|
||||
meta_wayland_keyboard_update (&seat->keyboard, (const ClutterKeyEvent *) event);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
|
||||
const ClutterEvent *event)
|
||||
@@ -403,6 +434,13 @@ meta_wayland_seat_repick (MetaWaylandSeat *seat,
|
||||
ClutterActor *actor = NULL;
|
||||
MetaWaylandPointer *pointer = &seat->pointer;
|
||||
MetaWaylandSurface *surface = NULL;
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
|
||||
if (meta_grab_op_is_wayland (display->grab_op))
|
||||
{
|
||||
meta_wayland_pointer_update_current_focus (pointer, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (for_event)
|
||||
{
|
||||
@@ -422,22 +460,10 @@ meta_wayland_seat_repick (MetaWaylandSeat *seat,
|
||||
else
|
||||
seat->current_stage = NULL;
|
||||
|
||||
if (META_IS_WINDOW_ACTOR (actor))
|
||||
{
|
||||
MetaWindow *window =
|
||||
meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor));
|
||||
if (META_IS_SURFACE_ACTOR_WAYLAND (actor))
|
||||
surface = meta_surface_actor_wayland_get_surface (META_SURFACE_ACTOR_WAYLAND (actor));
|
||||
|
||||
surface = window->surface;
|
||||
}
|
||||
|
||||
pointer->current = surface;
|
||||
if (surface != pointer->focus)
|
||||
{
|
||||
const MetaWaylandPointerGrabInterface *interface =
|
||||
pointer->grab->interface;
|
||||
interface->focus (pointer->grab,
|
||||
surface, for_event);
|
||||
}
|
||||
meta_wayland_pointer_update_current_focus (pointer, surface);
|
||||
}
|
||||
|
||||
void
|
||||
|
@@ -43,12 +43,6 @@ struct _MetaWaylandDataSource
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
struct wl_array mime_types;
|
||||
|
||||
void (*accept) (MetaWaylandDataSource * source,
|
||||
uint32_t serial, const char *mime_type);
|
||||
void (*send) (MetaWaylandDataSource * source,
|
||||
const char *mime_type, int32_t fd);
|
||||
void (*cancel) (MetaWaylandDataSource * source);
|
||||
};
|
||||
|
||||
struct _MetaWaylandSeat
|
||||
@@ -74,12 +68,11 @@ struct _MetaWaylandSeat
|
||||
};
|
||||
|
||||
MetaWaylandSeat *
|
||||
meta_wayland_seat_new (struct wl_display *display,
|
||||
gboolean is_native);
|
||||
meta_wayland_seat_new (struct wl_display *display);
|
||||
|
||||
void
|
||||
meta_wayland_seat_update_pointer (MetaWaylandSeat *seat,
|
||||
const ClutterEvent *event);
|
||||
meta_wayland_seat_update (MetaWaylandSeat *seat,
|
||||
const ClutterEvent *event);
|
||||
|
||||
gboolean
|
||||
meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -38,7 +38,6 @@ struct _MetaWaylandBuffer
|
||||
struct wl_listener destroy_listener;
|
||||
|
||||
CoglTexture *texture;
|
||||
int32_t width, height;
|
||||
uint32_t ref_count;
|
||||
};
|
||||
|
||||
@@ -59,12 +58,14 @@ typedef struct
|
||||
|
||||
/* wl_surface.frame */
|
||||
struct wl_list frame_callback_list;
|
||||
|
||||
gboolean frame_extents_changed;
|
||||
GtkBorder frame_extents;
|
||||
} MetaWaylandDoubleBufferedState;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
struct wl_listener surface_destroy_listener;
|
||||
} MetaWaylandSurfaceExtension;
|
||||
|
||||
struct _MetaWaylandSurface
|
||||
@@ -75,6 +76,7 @@ struct _MetaWaylandSurface
|
||||
MetaWindow *window;
|
||||
MetaWaylandSurfaceExtension xdg_surface;
|
||||
MetaWaylandSurfaceExtension xdg_popup;
|
||||
MetaWaylandSurfaceExtension wl_shell_surface;
|
||||
MetaWaylandSurfaceExtension gtk_surface;
|
||||
MetaWaylandSurfaceExtension subsurface;
|
||||
|
||||
@@ -96,6 +98,8 @@ struct _MetaWaylandSurface
|
||||
GSList *pending_placement_ops;
|
||||
} sub;
|
||||
|
||||
uint32_t state_changed_serial;
|
||||
|
||||
/* All the pending state, that wl_surface.commit will apply. */
|
||||
MetaWaylandDoubleBufferedState pending;
|
||||
};
|
||||
@@ -106,15 +110,26 @@ MetaWaylandSurface *meta_wayland_surface_create (MetaWaylandCompositor *composit
|
||||
struct wl_client *client,
|
||||
guint32 id,
|
||||
guint32 version);
|
||||
|
||||
void meta_wayland_surface_make_toplevel (MetaWaylandSurface *surface);
|
||||
void meta_wayland_surface_window_unmanaged (MetaWaylandSurface *surface);
|
||||
|
||||
void meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
|
||||
int width,
|
||||
int height,
|
||||
int edges);
|
||||
int height);
|
||||
void meta_wayland_surface_send_maximized (MetaWaylandSurface *surface);
|
||||
void meta_wayland_surface_send_unmaximized (MetaWaylandSurface *surface);
|
||||
void meta_wayland_surface_send_fullscreened (MetaWaylandSurface *surface);
|
||||
void meta_wayland_surface_send_unfullscreened (MetaWaylandSurface *surface);
|
||||
|
||||
void meta_wayland_surface_focused_set (MetaWaylandSurface *surface);
|
||||
void meta_wayland_surface_focused_unset (MetaWaylandSurface *surface);
|
||||
void meta_wayland_surface_activated (MetaWaylandSurface *surface);
|
||||
void meta_wayland_surface_deactivated (MetaWaylandSurface *surface);
|
||||
|
||||
void meta_wayland_surface_ping (MetaWaylandSurface *surface,
|
||||
guint32 serial);
|
||||
void meta_wayland_surface_delete (MetaWaylandSurface *surface);
|
||||
|
||||
void meta_wayland_surface_popup_done (MetaWaylandSurface *surface);
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -37,11 +37,11 @@
|
||||
/* Global/master objects (version exported by wl_registry and negotiated through bind) */
|
||||
#define META_WL_COMPOSITOR_VERSION 3
|
||||
#define META_WL_DATA_DEVICE_MANAGER_VERSION 1
|
||||
#define META_WL_SHELL_VERSION 1
|
||||
#define META_WL_SEAT_VERSION 2 /* 3 not implemented yet */
|
||||
#define META_WL_OUTPUT_VERSION 2
|
||||
#define META_XSERVER_VERSION 1
|
||||
#define META_GTK_SHELL_VERSION 1
|
||||
#define META_XDG_SHELL_VERSION 1
|
||||
#define META_WL_SUBCOMPOSITOR_VERSION 1
|
||||
|
||||
/* Slave objects (version inherited from a master object) */
|
||||
@@ -53,9 +53,10 @@
|
||||
#define META_WL_KEYBOARD_VERSION 2 /* from wl_seat; 3 not implemented yet */
|
||||
#define META_WL_TOUCH_VERSION 0 /* from wl_seat; wl_touch not supported */
|
||||
#define META_WL_REGION_VERSION 1 /* from wl_compositor */
|
||||
#define META_GTK_SURFACE_VERSION 1 /* from gtk_shell */
|
||||
#define META_XDG_SURFACE_VERSION 1 /* from xdg_shell */
|
||||
#define META_XDG_POPUP_VERSION 1 /* from xdg_shell */
|
||||
#define META_WL_SHELL_SURFACE_VERSION 1 /* from wl_shell */
|
||||
#define META_GTK_SURFACE_VERSION 1 /* from gtk_shell */
|
||||
#define META_WL_SUBSURFACE_VERSION 1 /* from wl_subcompositor */
|
||||
|
||||
/* The first version to implement a specific event */
|
||||
|
@@ -151,7 +151,6 @@ meta_wayland_buffer_unref (MetaWaylandBuffer *buffer)
|
||||
if (buffer->ref_count == 0)
|
||||
{
|
||||
g_clear_pointer (&buffer->texture, cogl_object_unref);
|
||||
g_assert (wl_resource_get_client (buffer->resource));
|
||||
wl_resource_queue_event (buffer->resource, WL_BUFFER_RELEASE);
|
||||
}
|
||||
}
|
||||
@@ -508,6 +507,15 @@ stage_destroy_cb (void)
|
||||
meta_quit (META_EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_wayland_compositor_update:
|
||||
* @compositor: the #MetaWaylandCompositor instance
|
||||
* @event: the #ClutterEvent used to update @seat's state
|
||||
*
|
||||
* This is used to update display server state like updating cursor
|
||||
* position and keeping track of buttons and keys pressed. It must be
|
||||
* called for all input events coming from the underlying devices.
|
||||
*/
|
||||
void
|
||||
meta_wayland_compositor_update (MetaWaylandCompositor *compositor,
|
||||
const ClutterEvent *event)
|
||||
@@ -536,18 +544,18 @@ meta_wayland_compositor_update (MetaWaylandCompositor *compositor,
|
||||
meta_idle_monitor_reset_idletime (device_monitor);
|
||||
}
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_MOTION:
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
case CLUTTER_SCROLL:
|
||||
meta_wayland_seat_update_pointer (compositor->seat, event);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
meta_wayland_seat_update (compositor->seat, event);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_wayland_compositor_handle_event:
|
||||
* @compositor: the #MetaWaylandCompositor instance
|
||||
* @event: the #ClutterEvent to be sent
|
||||
*
|
||||
* This method sends events to the focused wayland client, if any.
|
||||
*
|
||||
* Return value: whether @event was sent to a wayland client.
|
||||
*/
|
||||
gboolean
|
||||
meta_wayland_compositor_handle_event (MetaWaylandCompositor *compositor,
|
||||
const ClutterEvent *event)
|
||||
@@ -600,31 +608,11 @@ meta_wayland_log_func (const char *fmt,
|
||||
g_free (str);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
are_we_native (int *out_drm_fd)
|
||||
{
|
||||
ClutterBackend *backend = clutter_get_default_backend ();
|
||||
CoglContext *cogl_context = clutter_backend_get_cogl_context (backend);
|
||||
CoglRenderer *cogl_renderer = cogl_display_get_renderer (cogl_context_get_display (cogl_context));
|
||||
|
||||
if (cogl_renderer_get_winsys_id (cogl_renderer) == COGL_WINSYS_ID_EGL_KMS)
|
||||
{
|
||||
*out_drm_fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_init (void)
|
||||
{
|
||||
MetaWaylandCompositor *compositor = &_meta_wayland_compositor;
|
||||
MetaMonitorManager *monitors;
|
||||
char *display_name;
|
||||
int drm_fd;
|
||||
|
||||
memset (compositor, 0, sizeof (MetaWaylandCompositor));
|
||||
|
||||
@@ -663,28 +651,16 @@ meta_wayland_init (void)
|
||||
|
||||
clutter_wayland_set_compositor_display (compositor->wayland_display);
|
||||
|
||||
if (getenv ("WESTON_LAUNCHER_SOCK"))
|
||||
/* If we're running on bare metal, we're a display server,
|
||||
* so start talking to weston-launch. */
|
||||
#if defined(CLUTTER_WINDOWING_EGL)
|
||||
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
|
||||
compositor->launcher = meta_launcher_new ();
|
||||
#endif
|
||||
|
||||
if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
|
||||
g_error ("Failed to initialize Clutter");
|
||||
|
||||
if (are_we_native (&drm_fd))
|
||||
{
|
||||
GError *error = NULL;
|
||||
if (!meta_launcher_set_drm_fd (compositor->launcher, drm_fd, &error))
|
||||
{
|
||||
g_error ("Failed to set DRM fd to weston-launch and become DRM master: %s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
compositor->native = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
compositor->native = FALSE;
|
||||
}
|
||||
|
||||
meta_monitor_manager_initialize ();
|
||||
monitors = meta_monitor_manager_get ();
|
||||
g_signal_connect (monitors, "monitors-changed",
|
||||
@@ -699,7 +675,7 @@ meta_wayland_init (void)
|
||||
|
||||
meta_wayland_data_device_manager_init (compositor->wayland_display);
|
||||
|
||||
compositor->seat = meta_wayland_seat_new (compositor->wayland_display, compositor->native);
|
||||
compositor->seat = meta_wayland_seat_new (compositor->wayland_display);
|
||||
|
||||
meta_wayland_init_shell (compositor);
|
||||
|
||||
@@ -720,13 +696,10 @@ meta_wayland_init (void)
|
||||
* and so EGL must be initialized by this point.
|
||||
*/
|
||||
|
||||
if (!meta_xwayland_start (compositor))
|
||||
if (!meta_xwayland_start (&compositor->xwayland_manager, compositor->wayland_display))
|
||||
g_error ("Failed to start X Wayland");
|
||||
|
||||
display_name = g_strdup_printf (":%d", compositor->xwayland_display_index);
|
||||
set_gnome_env ("DISPLAY", display_name);
|
||||
g_free (display_name);
|
||||
|
||||
set_gnome_env ("DISPLAY", compositor->xwayland_manager.display_name);
|
||||
set_gnome_env ("WAYLAND_DISPLAY", compositor->display_name);
|
||||
}
|
||||
|
||||
@@ -737,18 +710,12 @@ meta_wayland_finalize (void)
|
||||
|
||||
compositor = meta_wayland_compositor_get_default ();
|
||||
|
||||
meta_xwayland_stop (compositor);
|
||||
meta_xwayland_stop (&compositor->xwayland_manager);
|
||||
|
||||
if (compositor->launcher)
|
||||
meta_launcher_free (compositor->launcher);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_compositor_is_native (MetaWaylandCompositor *compositor)
|
||||
{
|
||||
return compositor->native;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_compositor_activate_vt (MetaWaylandCompositor *compositor,
|
||||
int vt,
|
||||
@@ -760,7 +727,22 @@ meta_wayland_compositor_activate_vt (MetaWaylandCompositor *compositor,
|
||||
}
|
||||
else
|
||||
{
|
||||
g_debug ("Ignoring VT switch keybinding, not running as VT manager");
|
||||
g_debug ("Ignoring VT switch keybinding, not running as display server");
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_compositor_activate_session (MetaWaylandCompositor *compositor,
|
||||
GError **error)
|
||||
{
|
||||
if (compositor->launcher)
|
||||
{
|
||||
return meta_launcher_activate_vt (compositor->launcher, -1, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_debug ("Ignoring activate_session, not running as display server");
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user