Compare commits
	
		
			192 Commits
		
	
	
		
			wip/xdg-sh
			...
			3.11.92-wa
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 56e8c3b625 | ||
|   | ce3d9fb89f | ||
|   | 27c018ab98 | ||
|   | a1427c7130 | ||
|   | 91ad92c968 | ||
|   | f0c7b518e6 | ||
|   | 5fa5ace5e6 | ||
|   | 044c06bff3 | ||
|   | a3ccc4fd1c | ||
|   | 0a20f7458c | ||
|   | 9c94f8ae47 | ||
|   | f940292cfe | ||
|   | 48a36356dd | ||
|   | f05983be42 | ||
|   | dfcefd3315 | ||
|   | 3fe755e684 | ||
|   | 0eb86de807 | ||
|   | ff635bad3b | ||
|   | 43a409dec4 | ||
|   | b087fce062 | ||
|   | 420f322910 | ||
|   | 4bf6e0ae8c | ||
|   | 97872e70a5 | ||
|   | be57308663 | ||
|   | 33f1bd96f5 | ||
|   | 9ba49358e5 | ||
|   | 8b2b65246a | ||
|   | 4fdbb466e1 | ||
|   | da48b18188 | ||
|   | a5f1790828 | ||
|   | 6efcf2526d | ||
|   | d6a27195d3 | ||
|   | 8f151842fb | ||
|   | 6f7023bc6b | ||
|   | 63b158e4da | ||
|   | b3364cad3e | ||
|   | 3502cfba34 | ||
|   | 5cc6becb63 | ||
|   | ae8f21a3dc | ||
|   | 0cdf3bd383 | ||
|   | 3de58189c0 | ||
|   | 5270c469a3 | ||
|   | 7504f16e59 | ||
|   | cdb7947dd1 | ||
|   | cdfc6f5b53 | ||
|   | fcb2ab41b2 | ||
|   | f5bd7c5f50 | ||
|   | cb549154aa | ||
|   | ada9610e30 | ||
|   | f11bf44525 | ||
|   | 1f15c85c00 | ||
|   | 8b4c5459c0 | ||
|   | d07d5d1328 | ||
|   | 535685742a | ||
|   | 62e45b6d5e | ||
|   | 3c6dd5bf6d | ||
|   | 0f85986340 | ||
|   | 93ac0329db | ||
|   | c539dfe0d7 | ||
|   | 1502d2a79f | ||
|   | a9d8107c3d | ||
|   | a5d2c51392 | ||
|   | d1ea17e6a4 | ||
|   | b37ad66e9d | ||
|   | c1f15348a5 | ||
|   | 857561baed | ||
|   | a44cc9ef47 | ||
|   | d47b7ba038 | ||
|   | f21312e2fd | ||
|   | 394af33607 | ||
|   | 7314cdac94 | ||
|   | 81025e37ea | ||
|   | 1bb9f1e333 | ||
|   | b11c75c1c9 | ||
|   | 757b626aee | ||
|   | fb3df5243f | ||
|   | e34792d9f0 | ||
|   | f397c32192 | ||
|   | f79314d7b5 | ||
|   | 55c61259d8 | ||
|   | 5298cf0a3a | ||
|   | f1dc1a0cbc | ||
|   | 2cf80bc647 | ||
|   | 40c15f6e2a | ||
|   | a8849621c9 | ||
|   | 49c0be11d6 | ||
|   | 9df8e831be | ||
|   | 84c6b2a3fa | ||
|   | 06cd669ccb | ||
|   | 81eb7d9537 | ||
|   | dd8d8e436d | ||
|   | d6b6b363ad | ||
|   | 254e2e993c | ||
|   | c595a9c29f | ||
|   | dfc7f7222b | ||
|   | ef278eb547 | ||
|   | 38e26e5cc3 | ||
|   | 9773a879c3 | ||
|   | abd2abcde6 | ||
|   | a8f4651c72 | ||
|   | 54df7934ea | ||
|   | 9052efb0d9 | ||
|   | b346f98eb0 | ||
|   | 365af53797 | ||
|   | bee59ec0e1 | ||
|   | 91384a32b4 | ||
|   | 72bd5fb814 | ||
|   | 46af3ef9f6 | ||
|   | d417c615d5 | ||
|   | 46cbd0bf48 | ||
|   | f3b6fead4d | ||
|   | 80de8ec643 | ||
|   | 4f7e2a9f3f | ||
|   | 701e06d55d | ||
|   | 94f39a493f | ||
|   | ddc171220a | ||
|   | 0313b38dd6 | ||
|   | d41fba6558 | ||
|   | 770b58b367 | ||
|   | 77838c2ca3 | ||
|   | e56cbfbd0f | ||
|   | a27fb19473 | ||
|   | 674bcef6da | ||
|   | 86c1c30245 | ||
|   | 283546b379 | ||
|   | 98e3e5e50f | ||
|   | b6a0d4d368 | ||
|   | 28859c604f | ||
|   | 9e51d98f4a | ||
|   | 268a4c92ba | ||
|   | 71367e14d5 | ||
|   | 5c99eae8a9 | ||
|   | 89aa5df711 | ||
|   | b9a5d710b7 | ||
|   | 65dd54a4db | ||
|   | b00fa70d91 | ||
|   | 360d423faa | ||
|   | 394b44a2c2 | ||
|   | ed6821a819 | ||
|   | 23b0f7be43 | ||
|   | 7f195aec7a | ||
|   | da13e3d237 | ||
|   | 75184d4c55 | ||
|   | eb75306f8a | ||
|   | 98c4b82907 | ||
|   | 640102c03b | ||
|   | c0d791cd6e | ||
|   | 41d5e69de5 | ||
|   | 2dc7371944 | ||
|   | ec2c3e1438 | ||
|   | c5c3806a04 | ||
|   | ac0c7df4a3 | ||
|   | d85845426c | ||
|   | 060e60f2a0 | ||
|   | 26cf75d5a4 | ||
|   | 9f5087e97d | ||
|   | 45624f2edf | ||
|   | 153f843ea6 | ||
|   | f0cd9b0687 | ||
|   | 1783bf20ec | ||
|   | 9b24ae2033 | ||
|   | 0be4622e14 | ||
|   | bcd5446cdc | ||
|   | 04b5232960 | ||
|   | f860df4b2d | ||
|   | ff8c4b1bcf | ||
|   | 337c69e223 | ||
|   | 14841475b5 | ||
|   | 7283fb320f | ||
|   | 020cfa7283 | ||
|   | 83aca0b53d | ||
|   | 0b055fae2e | ||
|   | bc79259398 | ||
|   | 7ebf5aa69a | ||
|   | 7499621ecb | ||
|   | 4de3f7ca29 | ||
|   | 17462c21e8 | ||
|   | c964ef4e01 | ||
|   | 0dccc440b6 | ||
|   | 48f7232492 | ||
|   | ff5867e4d3 | ||
|   | a5d950f453 | ||
|   | 7615d17293 | ||
|   | 374e30043b | ||
|   | f771bb88d6 | ||
|   | 7ef8d21e48 | ||
|   | c251eb8ec0 | ||
|   | 1e6b3faa83 | ||
|   | e62fe956fd | ||
|   | 24c5290d7f | ||
|   | 00c8d3c897 | ||
|   | cc13f8f65e | 
							
								
								
									
										19
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										19
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -78,12 +78,12 @@ src/stamp-mutter-marshal.h | ||||
| src/meta-dbus-xrandr.[ch] | ||||
| src/meta-dbus-idle-monitor.[ch] | ||||
| src/mutter-plugins.pc | ||||
| src/wayland/gtk-shell-protocol.c | ||||
| src/wayland/gtk-shell-server-protocol.h | ||||
| src/wayland/xdg-shell-protocol.c | ||||
| src/wayland/xdg-shell-server-protocol.h | ||||
| src/wayland/xserver-protocol.c | ||||
| src/wayland/xserver-server-protocol.h | ||||
| src/gtk-shell-protocol.c | ||||
| src/gtk-shell-server-protocol.h | ||||
| src/xdg-shell-protocol.c | ||||
| src/xdg-shell-server-protocol.h | ||||
| src/xserver-protocol.c | ||||
| src/xserver-server-protocol.h | ||||
| doc/reference/*.args | ||||
| doc/reference/*.bak | ||||
| doc/reference/*.hierarchy | ||||
| @@ -101,3 +101,10 @@ doc/reference/meta-undocumented.txt | ||||
| doc/reference/meta-unused.txt | ||||
| doc/reference/meta-docs.sgml | ||||
| doc/reference/meta.types | ||||
| gtk-doc.m4 | ||||
| intltool.m4 | ||||
| libtool.m4 | ||||
| ltoptions.m4 | ||||
| ltsugar.m4 | ||||
| ltversion.m4 | ||||
| lt~obsolete.m4 | ||||
|   | ||||
							
								
								
									
										159
									
								
								COMPLIANCE
									
									
									
									
									
								
							
							
						
						
									
										159
									
								
								COMPLIANCE
									
									
									
									
									
								
							| @@ -1,159 +0,0 @@ | ||||
| Metacity Standards Compliance | ||||
| ============================= | ||||
| $Id$ | ||||
|  | ||||
| 1) Introduction | ||||
| 2) EWMH Compliance | ||||
|   a. Root Window Properties | ||||
|   b. Root Window Messages | ||||
|   c. Application Window Properties | ||||
|   d. Window Manager Protocols | ||||
| 3) ICCCM Compliance | ||||
|  | ||||
| 1) Introduction | ||||
| --------------- | ||||
|  | ||||
| This document details metacity compliance with the relevent standards. | ||||
| The format of this document is as follows: | ||||
|  | ||||
| [-/+?] Hint Name/Feature Name (Version number) | ||||
|        Errata/Comments | ||||
|  | ||||
| The first character indicates the level of compliance as follows: | ||||
|     -   none | ||||
|     /   partial | ||||
|     +   complete | ||||
|     ?   unknown | ||||
|  | ||||
| The title indicates a feature or a hint in the specification, and the | ||||
| version number indicates the minimum version of the specification | ||||
| supported by metacity.  Later versions may be supported if no | ||||
| incompatible changes have been made in the specification. | ||||
|  | ||||
| 2) EWMH Compliance | ||||
| ------------------ | ||||
|  | ||||
| The EWMH, or Extended Window Manager Hints is a freedesktop.org- | ||||
| developed standard to support a number of conventions for | ||||
| communication between the window manager and clients.  It builds on | ||||
| and extends the ICCCM (See Section 3).  A copy of the current EWMH | ||||
| standard is available at http://freedesktop.org/Standards/wm-spec/ | ||||
|  | ||||
|   a. Root Window Properties | ||||
|   ------------------------- | ||||
|  | ||||
| + _NET_SUPPORTED (1.3) | ||||
|  | ||||
| + _NET_CLIENT_LIST (1.3) | ||||
|  | ||||
| + _NET_NUMBER_OF_DESKTOPS (1.3) | ||||
|  | ||||
| + _NET_DESKTOP_GEOMETRY (1.3) | ||||
|   Metacity does not implement large desktops, so this is kept set to | ||||
|   the screen size. | ||||
|  | ||||
| + _NET_DESKTOP_VIEWPORT (1.3) | ||||
|   Metacity does not implement viewports, so this is a constant (0,0). | ||||
|  | ||||
| + _NET_CURRENT_DESKTOP (1.3) | ||||
|  | ||||
| + _NET_DESKTOP_NAMES (1.3) | ||||
|  | ||||
| + _NET_ACTIVE_WINDOW (1.3) | ||||
|  | ||||
| + _NET_WORKAREA (1.3) | ||||
|  | ||||
| + _NET_SUPPORTING_WM_CHECK (1.3) | ||||
|  | ||||
| + _NET_VIRTUAL_ROOTS (1.3) | ||||
|   Metacity does not read or set this property, but it does not use | ||||
|   virtual roots to implement virtual desktops, so it complies with the | ||||
|   specification. | ||||
|  | ||||
| + _NET_DESKTOP_LAYOUT (1.3) | ||||
|  | ||||
| + _NET_SHOWING_DESKTOP (1.3) | ||||
|  | ||||
|   b. Root Window Messages | ||||
|   ----------------------- | ||||
|  | ||||
| + _NET_CLOSE_WINDOW (1.3) | ||||
|  | ||||
| - _NET_MOVERESIZE_WINDOW (1.3) | ||||
|   Metacity supports this message, but the specification is unclear on | ||||
|   the layout of the detail value, and as such it is #if 0'd in the code | ||||
|  | ||||
| + _NET_WM_MOVERESIZE (1.3) | ||||
|  | ||||
| - _NET_RESTACK_WINDOW (1.3) | ||||
|   Metacity will raise or lower windows in response to this message, | ||||
|   but the sibling restack modes are not supported, and it is currently | ||||
|   #if 0'd in the code. | ||||
|  | ||||
| + _NET_REQUEST_FRAME_EXTENTS (1.3)   | ||||
|  | ||||
|   c. Application Window Properties | ||||
|   -------------------------------- | ||||
|  | ||||
| + _NET_WM_NAME (1.3) | ||||
|  | ||||
| + _NET_WM_VISIBLE_NAME (1.3) | ||||
|   Metacity does not set this property, but metacity will never display | ||||
|   a name different from _NET_WM_NAME | ||||
|  | ||||
| + _NET_WM_ICON_NAME (1.3) | ||||
|  | ||||
| + _NET_WM_VISIBLE_ICON_NAME (1.3) | ||||
|   Metacity does not set this property, but metacity will never display | ||||
|   a name different from _NET_WM_NAME | ||||
|  | ||||
| + _NET_WM_DESKTOP (1.3) | ||||
|  | ||||
| + _NET_WM_WINDOW_TYPE (1.3) | ||||
|  | ||||
| / _NET_WM_STATE (1.3) | ||||
|   This property is read and updated according to the specification, | ||||
|   but see caveat below. | ||||
|   Metacity does not recognize separate vertical and horizontal | ||||
|   maximization states.  Currently metacity will do a two-dimensional | ||||
|   maximization if either property is set. | ||||
|   See: http://bugzilla.gnome.org/show_bug.cgi?id=113601 | ||||
|   Metacity doesn't implement viewports so _NET_WM_STATE_STICKY is | ||||
|   unimplemented. | ||||
|  | ||||
| + _NET_WM_ALLOWED_ACTIONS (1.3) | ||||
|   Metacity keeps this hint up to date.  The code is somewhat crufty | ||||
|   and should be rewritten, though it is functional. | ||||
|   See: http://bugzilla.gnome.org/show_bug.cgi?id=90420 | ||||
|  | ||||
| + _NET_WM_STRUT (1.3) | ||||
|  | ||||
| + _NET_WM_STRUT_PARTIAL (1.3) | ||||
|  | ||||
| + _NET_WM_ICON_GEOMETRY (1.3) | ||||
|   Metacity uses this property to draw minimize/restore animations | ||||
|  | ||||
| + _NET_WM_ICON (1.3) | ||||
|  | ||||
| + _NET_WM_PID (1.3) | ||||
|  | ||||
| + _NET_WM_HANDLED_ICONS (1.3) | ||||
|   Metacity does not read or set this property.  However, metacity | ||||
|   never manages iconified windows, and so has no need to do so. | ||||
|  | ||||
| + _NET_WM_USER_TIME (1.3) | ||||
|   Metacity uses this property to prevent applications from stealing | ||||
|   focus if supported by the toolkit. | ||||
|  | ||||
| + _NET_FRAME_EXTENTS (1.3) | ||||
|   If set in response to a _NET_REQUEST_FRAME_EXTENTS message received | ||||
|   prior to the window being mapped, this may be an estimate.  This is, | ||||
|   however, expressly allowed by the specification. | ||||
|  | ||||
|   d. Window Manager Protocols | ||||
|   --------------------------- | ||||
| + _NET_WM_PING (1.3) | ||||
|  | ||||
| 3) ICCCM Compliance | ||||
| ------------------- | ||||
| TODO | ||||
							
								
								
									
										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 | ||||
|  | ||||
|   | ||||
							
								
								
									
										36
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								NEWS
									
									
									
									
									
								
							| @@ -1,3 +1,39 @@ | ||||
| 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. | ||||
| @@ -5,7 +5,7 @@ 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) || { | ||||
|   | ||||
							
								
								
									
										10
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								configure.ac
									
									
									
									
									
								
							| @@ -3,7 +3,7 @@ AC_CONFIG_MACRO_DIR([m4]) | ||||
|  | ||||
| m4_define([mutter_major_version], [3]) | ||||
| m4_define([mutter_minor_version], [11]) | ||||
| m4_define([mutter_micro_version], [5]) | ||||
| m4_define([mutter_micro_version], [92]) | ||||
|  | ||||
| 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) | ||||
| @@ -458,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 | ||||
|   | ||||
| @@ -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"/> | ||||
|  | ||||
|   | ||||
| @@ -6,6 +6,7 @@ lib_LTLIBRARIES = libmutter-wayland.la | ||||
| SUBDIRS=compositor/plugins | ||||
|  | ||||
| INCLUDES=								\ | ||||
| 	-DCLUTTER_ENABLE_COMPOSITOR_API					\ | ||||
| 	-DCLUTTER_ENABLE_EXPERIMENTAL_API				\ | ||||
| 	-DCOGL_ENABLE_EXPERIMENTAL_API					\ | ||||
| 	-DCOGL_ENABLE_EXPERIMENTAL_2_0_API                              \ | ||||
| @@ -28,11 +29,7 @@ INCLUDES=								\ | ||||
| 	-DMUTTER_PLUGIN_API_VERSION=$(MUTTER_PLUGIN_API_VERSION)	\ | ||||
| 	-DMUTTER_PKGLIBDIR=\"$(pkglibdir)\"				\ | ||||
| 	-DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\"			\ | ||||
| 	-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" | ||||
|  | ||||
| INCLUDES += \ | ||||
| 	-I$(srcdir)/wayland						\ | ||||
| 	-I$(builddir)/wayland						\ | ||||
| 	-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\"			\ | ||||
| 	-DXWAYLAND_PATH='"@XWAYLAND_PATH@"' | ||||
|  | ||||
| mutter_built_sources = \ | ||||
| @@ -40,16 +37,20 @@ mutter_built_sources = \ | ||||
| 	$(dbus_xrandr_built_sources)		\ | ||||
| 	mutter-enum-types.h 			\ | ||||
| 	mutter-enum-types.c			\ | ||||
| 	wayland/gtk-shell-protocol.c		\ | ||||
| 	wayland/gtk-shell-server-protocol.h	\ | ||||
| 	wayland/xdg-shell-protocol.c		\ | ||||
| 	wayland/xdg-shell-server-protocol.h	\ | ||||
| 	wayland/xserver-protocol.c		\ | ||||
| 	wayland/xserver-server-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				\ | ||||
| @@ -80,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		\ | ||||
| @@ -100,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				\ | ||||
| @@ -108,8 +112,6 @@ libmutter_wayland_la_SOURCES =			\ | ||||
| 	core/display.c				\ | ||||
| 	core/display-private.h			\ | ||||
| 	meta/display.h				\ | ||||
| 	ui/draw-workspace.c			\ | ||||
| 	ui/draw-workspace.h			\ | ||||
| 	core/edge-resistance.c			\ | ||||
| 	core/edge-resistance.h			\ | ||||
| 	core/edid-parse.c			\ | ||||
| @@ -120,13 +122,6 @@ libmutter_wayland_la_SOURCES =			\ | ||||
| 	core/frame.h				\ | ||||
| 	ui/gradient.c				\ | ||||
| 	meta/gradient.h				\ | ||||
| 	core/group-private.h			\ | ||||
| 	core/group-props.c			\ | ||||
| 	core/group-props.h			\ | ||||
| 	core/group.c				\ | ||||
| 	meta/group.h				\ | ||||
| 	core/iconcache.c			\ | ||||
| 	core/iconcache.h			\ | ||||
| 	core/keybindings.c			\ | ||||
| 	core/keybindings-private.h		\ | ||||
| 	core/main.c				\ | ||||
| @@ -149,8 +144,6 @@ libmutter_wayland_la_SOURCES =			\ | ||||
| 	core/screen-private.h			\ | ||||
| 	meta/screen.h				\ | ||||
| 	meta/types.h				\ | ||||
| 	core/session.c				\ | ||||
| 	core/session.h				\ | ||||
| 	core/stack.c				\ | ||||
| 	core/stack.h				\ | ||||
| 	core/stack-tracker.c			\ | ||||
| @@ -158,17 +151,11 @@ libmutter_wayland_la_SOURCES =			\ | ||||
| 	core/util.c				\ | ||||
| 	meta/util.h				\ | ||||
| 	core/util-private.h			\ | ||||
| 	core/window-props.c			\ | ||||
| 	core/window-props.h			\ | ||||
| 	core/window-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					\ | ||||
| @@ -180,16 +167,31 @@ libmutter_wayland_la_SOURCES =			\ | ||||
| 	ui/metaaccellabel.h			\ | ||||
| 	ui/resizepopup.c			\ | ||||
| 	ui/resizepopup.h			\ | ||||
| 	ui/tabpopup.c				\ | ||||
| 	ui/tabpopup.h				\ | ||||
| 	ui/tile-preview.c			\ | ||||
| 	ui/tile-preview.h			\ | ||||
| 	ui/theme-parser.c			\ | ||||
| 	ui/theme.c				\ | ||||
| 	meta/theme.h				\ | ||||
| 	ui/theme-private.h			\ | ||||
| 	ui/ui.c					\ | ||||
| 	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			\ | ||||
| @@ -309,7 +311,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 | ||||
|  | ||||
| @@ -360,6 +362,7 @@ EXTRA_DIST=$(desktopfiles_files) 	\ | ||||
| 	$(desktopfiles_in_files)	\ | ||||
| 	$(wmproperties_in_files)	\ | ||||
| 	$(xml_in_files)			\ | ||||
| 	$(wayland_protocols)		\ | ||||
| 	org.gnome.mutter.gschema.xml.in \ | ||||
| 	org.gnome.mutter.wayland.gschema.xml.in \ | ||||
| 	mutter-schemas.convert \ | ||||
| @@ -409,9 +412,7 @@ $(dbus_idle_built_sources) : Makefile.am idle-monitor.xml | ||||
| 		--c-generate-object-manager						\ | ||||
| 		$(srcdir)/idle-monitor.xml | ||||
|  | ||||
| wayland/%-protocol.c : $(top_builddir)/protocol/%.xml | ||||
| 	mkdir -p wayland | ||||
| %-protocol.c : $(srcdir)/wayland/protocol/%.xml | ||||
| 	$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@ | ||||
| wayland/%-server-protocol.h : $(top_builddir)/protocol/%.xml | ||||
| 	mkdir -p wayland | ||||
| %-server-protocol.h : $(srcdir)/wayland/protocol/%.xml | ||||
| 	$(AM_V_GEN)$(WAYLAND_SCANNER) server-header < $< > $@ | ||||
|   | ||||
| @@ -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 */ | ||||
|   | ||||
| @@ -65,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> | ||||
| @@ -76,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) | ||||
| @@ -108,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 | ||||
| @@ -145,15 +142,7 @@ 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); | ||||
| } | ||||
|  | ||||
| @@ -316,8 +305,6 @@ meta_focus_stage_window (MetaScreen *screen, | ||||
|   if (!stage) | ||||
|     return; | ||||
|  | ||||
|   if (!meta_is_wayland_compositor ()) | ||||
|     { | ||||
|   window = clutter_x11_get_stage_window (stage); | ||||
|  | ||||
|   if (window == None) | ||||
| @@ -325,30 +312,29 @@ meta_focus_stage_window (MetaScreen *screen, | ||||
|  | ||||
|   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); | ||||
|     } | ||||
| } | ||||
|  | ||||
| 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 | ||||
| @@ -361,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; | ||||
| @@ -381,7 +366,7 @@ begin_modal_x11 (MetaScreen       *screen, | ||||
|                              META_VIRTUAL_CORE_POINTER_ID, | ||||
|                              grab_window, | ||||
|                              timestamp, | ||||
|                              cursor, | ||||
|                              None, | ||||
|                              XIGrabModeAsync, XIGrabModeAsync, | ||||
|                              False, /* owner_events */ | ||||
|                              &mask); | ||||
| @@ -425,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, | ||||
| @@ -475,14 +421,13 @@ meta_begin_modal_for_plugin (MetaScreen       *screen, | ||||
|    * merge the two. | ||||
|    */ | ||||
|   MetaDisplay *display = meta_screen_get_display (screen); | ||||
|   MetaCompositor *compositor = display->compositor; | ||||
|   gboolean ok; | ||||
|  | ||||
|   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); | ||||
|     ok = TRUE; | ||||
|   else | ||||
|     ok = begin_modal_x11 (screen, plugin, options, timestamp); | ||||
|   if (!ok) | ||||
| @@ -494,8 +439,6 @@ meta_begin_modal_for_plugin (MetaScreen       *screen, | ||||
|   display->grab_have_pointer = TRUE; | ||||
|   display->grab_have_keyboard = TRUE; | ||||
|  | ||||
|   compositor->modal_plugin = plugin; | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| @@ -506,19 +449,10 @@ meta_end_modal_for_plugin (MetaScreen     *screen, | ||||
| { | ||||
|   MetaDisplay *display = meta_screen_get_display (screen); | ||||
|   Display *xdpy = meta_display_get_xdisplay (display); | ||||
|   MetaCompositor *compositor = display->compositor; | ||||
|  | ||||
|   g_return_if_fail (compositor->modal_plugin == plugin); | ||||
|   g_return_if_fail (is_modal (display)); | ||||
|  | ||||
|   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 | ||||
|   if (!meta_is_wayland_compositor ()) | ||||
|     { | ||||
|       XIUngrabDevice (xdpy, META_VIRTUAL_CORE_POINTER_ID, timestamp); | ||||
|       XIUngrabDevice (xdpy, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp); | ||||
| @@ -529,27 +463,6 @@ meta_end_modal_for_plugin (MetaScreen     *screen, | ||||
|   display->grab_screen = NULL; | ||||
|   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) | ||||
|     { | ||||
|       meta_end_modal_for_plugin (screen, | ||||
|                                    compositor->modal_plugin, | ||||
|  | ||||
|                                  CurrentTime); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -751,18 +664,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 | ||||
|     { | ||||
| @@ -771,7 +691,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; | ||||
| @@ -824,35 +744,21 @@ meta_compositor_add_window (MetaCompositor    *compositor, | ||||
|   MetaDisplay *display = meta_screen_get_display (screen); | ||||
|   MetaCompScreen *info = meta_screen_get_compositor_data (screen); | ||||
|  | ||||
|   g_return_if_fail (info != NULL); | ||||
|  | ||||
|   /* Window was already added previously, probably coming | ||||
|    * back from hiding */ | ||||
|   if (window->compositor_private != NULL) | ||||
|     return; | ||||
|  | ||||
|   meta_error_trap_push (display); | ||||
|   meta_window_actor_new (window); | ||||
|   meta_error_trap_pop (display); | ||||
|  | ||||
|   meta_window_actor_new (window); | ||||
|   sync_actor_stacking (info); | ||||
|  | ||||
|   meta_error_trap_pop (display); | ||||
| } | ||||
|  | ||||
| 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); | ||||
| @@ -865,13 +771,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); | ||||
| } | ||||
|  | ||||
| @@ -880,13 +780,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); | ||||
| } | ||||
|  | ||||
| @@ -937,6 +831,66 @@ 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 | ||||
| grab_op_is_clicking (MetaGrabOp grab_op) | ||||
| { | ||||
|   switch (grab_op) | ||||
|     { | ||||
|     case META_GRAB_OP_CLICKING_MINIMIZE: | ||||
|     case META_GRAB_OP_CLICKING_MAXIMIZE: | ||||
|     case META_GRAB_OP_CLICKING_UNMAXIMIZE: | ||||
|     case META_GRAB_OP_CLICKING_DELETE: | ||||
|     case META_GRAB_OP_CLICKING_MENU: | ||||
|     case META_GRAB_OP_CLICKING_SHADE: | ||||
|     case META_GRAB_OP_CLICKING_UNSHADE: | ||||
|     case META_GRAB_OP_CLICKING_ABOVE: | ||||
|     case META_GRAB_OP_CLICKING_UNABOVE: | ||||
|     case META_GRAB_OP_CLICKING_STICK: | ||||
|     case META_GRAB_OP_CLICKING_UNSTICK: | ||||
|       return TRUE; | ||||
|  | ||||
|     default: | ||||
|       return FALSE; | ||||
|     } | ||||
| } | ||||
|  | ||||
| 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 | ||||
| @@ -948,6 +902,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); | ||||
| @@ -956,24 +911,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 && | ||||
|               (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; | ||||
| @@ -993,53 +954,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; | ||||
|  | ||||
|       screen = meta_window_get_screen (window); | ||||
|       info = meta_screen_get_compositor_data (screen); | ||||
|   if (!meta_is_wayland_compositor ()) | ||||
|     maybe_spoof_event_as_stage_event (info, window, event); | ||||
|  | ||||
|   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_is_wayland_compositor () && | ||||
|       event->type == meta_display_get_damage_event_base (compositor->display) + XDamageNotify) | ||||
| @@ -1053,7 +987,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); | ||||
|     } | ||||
|  | ||||
| @@ -1075,11 +1008,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; | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -1088,10 +1017,6 @@ 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); | ||||
| } | ||||
|  | ||||
| @@ -1101,10 +1026,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); | ||||
| } | ||||
|  | ||||
| @@ -1115,10 +1036,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); | ||||
| } | ||||
|  | ||||
| @@ -1129,10 +1046,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); | ||||
| } | ||||
|  | ||||
| @@ -1150,17 +1063,13 @@ 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, | ||||
|   if (!meta_plugin_manager_switch_workspace (info->plugin_mgr, | ||||
|                                              from_indx, to_indx, | ||||
|                                              direction)) | ||||
|     { | ||||
|       info->switch_workspace_in_progress--; | ||||
| @@ -1270,8 +1179,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 | ||||
| @@ -1360,15 +1267,6 @@ meta_compositor_sync_window_geometry (MetaCompositor *compositor, | ||||
|                                       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); | ||||
| } | ||||
|  | ||||
| @@ -1400,7 +1298,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); | ||||
| @@ -1695,3 +1592,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); | ||||
| } | ||||
|   | ||||
| @@ -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; | ||||
| }; | ||||
|  | ||||
| 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) | ||||
|   | ||||
| @@ -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,8 +72,6 @@ struct _MetaShapedTexturePrivate | ||||
|   CoglTexture *texture; | ||||
|   CoglTexture *mask_texture; | ||||
|  | ||||
|   cairo_region_t *input_shape_region; | ||||
|  | ||||
|   /* The region containing only fully opaque pixels */ | ||||
|   cairo_region_t *opaque_region; | ||||
|  | ||||
| @@ -98,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)); | ||||
| @@ -463,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, | ||||
| @@ -646,8 +577,18 @@ static cairo_region_t * | ||||
| effective_unobscured_region (MetaShapedTexture *self) | ||||
| { | ||||
|   MetaShapedTexturePrivate *priv = self->priv; | ||||
|   ClutterActor *parent = clutter_actor_get_parent (CLUTTER_ACTOR (self)); | ||||
|  | ||||
|   return clutter_actor_has_mapped_clones (CLUTTER_ACTOR (self)) ? NULL : priv->unobscured_region; | ||||
|   if (clutter_actor_has_mapped_clones (CLUTTER_ACTOR (self))) | ||||
|     return NULL; | ||||
|  | ||||
|   while (parent && !META_IS_WINDOW_ACTOR (parent)) | ||||
|     parent = clutter_actor_get_parent (parent); | ||||
|  | ||||
|   if (parent && clutter_actor_has_mapped_clones (parent)) | ||||
|     return NULL; | ||||
|  | ||||
|   return priv->unobscured_region; | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| @@ -764,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 | ||||
|   | ||||
							
								
								
									
										165
									
								
								src/compositor/meta-surface-actor-wayland.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								src/compositor/meta-surface-actor-wayland.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,165 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2013 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Jasper St. Pierre <jstpierre@mecheye.net> | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include "meta-surface-actor-wayland.h" | ||||
|  | ||||
| #include <cogl/cogl-wayland-server.h> | ||||
| #include "meta-shaped-texture-private.h" | ||||
|  | ||||
| #include "wayland/meta-wayland-private.h" | ||||
|  | ||||
| struct _MetaSurfaceActorWaylandPrivate | ||||
| { | ||||
|   MetaWaylandSurface *surface; | ||||
|   MetaWaylandBuffer *buffer; | ||||
| }; | ||||
| typedef struct _MetaSurfaceActorWaylandPrivate MetaSurfaceActorWaylandPrivate; | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_PRIVATE (MetaSurfaceActorWayland, meta_surface_actor_wayland, META_TYPE_SURFACE_ACTOR) | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_wayland_process_damage (MetaSurfaceActor *actor, | ||||
|                                            int x, int y, int width, int height) | ||||
| { | ||||
|   MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor); | ||||
|   MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self); | ||||
|  | ||||
|   struct wl_resource *resource = priv->buffer->resource; | ||||
|   struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (resource); | ||||
|  | ||||
|   if (shm_buffer) | ||||
|     { | ||||
|       CoglTexture2D *texture = COGL_TEXTURE_2D (priv->buffer->texture); | ||||
|       cogl_wayland_texture_set_region_from_shm_buffer (texture, x, y, width, height, shm_buffer, x, y, 0, NULL); | ||||
|     } | ||||
|  | ||||
|   meta_surface_actor_update_area (META_SURFACE_ACTOR (self), x, y, width, height); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_wayland_pre_paint (MetaSurfaceActor *actor) | ||||
| { | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_surface_actor_wayland_is_argb32 (MetaSurfaceActor *actor) | ||||
| { | ||||
|   /* XXX -- look at the SHM buffer format. */ | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_surface_actor_wayland_is_visible (MetaSurfaceActor *actor) | ||||
| { | ||||
|   /* TODO: ensure that the buffer isn't NULL, implement | ||||
|    * wayland mapping semantics */ | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_surface_actor_wayland_should_unredirect (MetaSurfaceActor *actor) | ||||
| { | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_wayland_set_unredirected (MetaSurfaceActor *actor, | ||||
|                                              gboolean          unredirected) | ||||
| { | ||||
|   /* Do nothing. In the future, we'll use KMS to set this | ||||
|    * up as a hardware overlay or something. */ | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_surface_actor_wayland_is_unredirected (MetaSurfaceActor *actor) | ||||
| { | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static MetaWindow * | ||||
| meta_surface_actor_wayland_get_window (MetaSurfaceActor *actor) | ||||
| { | ||||
|   MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (META_SURFACE_ACTOR_WAYLAND (actor)); | ||||
|  | ||||
|   return priv->surface->window; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass) | ||||
| { | ||||
|   MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass); | ||||
|  | ||||
|   surface_actor_class->process_damage = meta_surface_actor_wayland_process_damage; | ||||
|   surface_actor_class->pre_paint = meta_surface_actor_wayland_pre_paint; | ||||
|   surface_actor_class->is_argb32 = meta_surface_actor_wayland_is_argb32; | ||||
|   surface_actor_class->is_visible = meta_surface_actor_wayland_is_visible; | ||||
|  | ||||
|   surface_actor_class->should_unredirect = meta_surface_actor_wayland_should_unredirect; | ||||
|   surface_actor_class->set_unredirected = meta_surface_actor_wayland_set_unredirected; | ||||
|   surface_actor_class->is_unredirected = meta_surface_actor_wayland_is_unredirected; | ||||
|  | ||||
|   surface_actor_class->get_window = meta_surface_actor_wayland_get_window; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_wayland_init (MetaSurfaceActorWayland *self) | ||||
| { | ||||
| } | ||||
|  | ||||
| MetaSurfaceActor * | ||||
| meta_surface_actor_wayland_new (MetaWaylandSurface *surface) | ||||
| { | ||||
|   MetaSurfaceActorWayland *self = g_object_new (META_TYPE_SURFACE_ACTOR_WAYLAND, NULL); | ||||
|   MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self); | ||||
|  | ||||
|   g_assert (meta_is_wayland_compositor ()); | ||||
|  | ||||
|   priv->surface = surface; | ||||
|  | ||||
|   return META_SURFACE_ACTOR (self); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self, | ||||
|                                        MetaWaylandBuffer       *buffer) | ||||
| { | ||||
|   MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self); | ||||
|   MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); | ||||
|  | ||||
|   priv->buffer = buffer; | ||||
|  | ||||
|   if (buffer) | ||||
|     meta_shaped_texture_set_texture (stex, buffer->texture); | ||||
|   else | ||||
|     meta_shaped_texture_set_texture (stex, NULL); | ||||
| } | ||||
|  | ||||
| MetaWaylandSurface * | ||||
| meta_surface_actor_wayland_get_surface (MetaSurfaceActorWayland *self) | ||||
| { | ||||
|   MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self); | ||||
|   return priv->surface; | ||||
| } | ||||
							
								
								
									
										66
									
								
								src/compositor/meta-surface-actor-wayland.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								src/compositor/meta-surface-actor-wayland.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2013 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Jasper St. Pierre <jstpierre@mecheye.net> | ||||
|  */ | ||||
|  | ||||
| #ifndef __META_SURFACE_ACTOR_WAYLAND_H__ | ||||
| #define __META_SURFACE_ACTOR_WAYLAND_H__ | ||||
|  | ||||
| #include <glib-object.h> | ||||
|  | ||||
| #include "meta-surface-actor.h" | ||||
|  | ||||
| #include "wayland/meta-wayland.h" | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define META_TYPE_SURFACE_ACTOR_WAYLAND            (meta_surface_actor_wayland_get_type ()) | ||||
| #define META_SURFACE_ACTOR_WAYLAND(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWayland)) | ||||
| #define META_SURFACE_ACTOR_WAYLAND_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWaylandClass)) | ||||
| #define META_IS_SURFACE_ACTOR_WAYLAND(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SURFACE_ACTOR_WAYLAND)) | ||||
| #define META_IS_SURFACE_ACTOR_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_SURFACE_ACTOR_WAYLAND)) | ||||
| #define META_SURFACE_ACTOR_WAYLAND_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWaylandClass)) | ||||
|  | ||||
| typedef struct _MetaSurfaceActorWayland      MetaSurfaceActorWayland; | ||||
| typedef struct _MetaSurfaceActorWaylandClass MetaSurfaceActorWaylandClass; | ||||
|  | ||||
| struct _MetaSurfaceActorWayland | ||||
| { | ||||
|   MetaSurfaceActor parent; | ||||
| }; | ||||
|  | ||||
| struct _MetaSurfaceActorWaylandClass | ||||
| { | ||||
|   MetaSurfaceActorClass parent_class; | ||||
| }; | ||||
|  | ||||
| GType meta_surface_actor_wayland_get_type (void); | ||||
|  | ||||
| MetaSurfaceActor * meta_surface_actor_wayland_new (MetaWaylandSurface *surface); | ||||
| MetaWaylandSurface * meta_surface_actor_wayland_get_surface (MetaSurfaceActorWayland *self); | ||||
|  | ||||
| void meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self, | ||||
|                                             MetaWaylandBuffer         *buffer); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __META_SURFACE_ACTOR_WAYLAND_H__ */ | ||||
							
								
								
									
										486
									
								
								src/compositor/meta-surface-actor-x11.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										486
									
								
								src/compositor/meta-surface-actor-x11.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,486 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2013 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Owen Taylor <otaylor@redhat.com> | ||||
|  *     Jasper St. Pierre <jstpierre@mecheye.net> | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include "meta-surface-actor-x11.h" | ||||
|  | ||||
| #include <X11/extensions/Xcomposite.h> | ||||
| #include <X11/extensions/Xrender.h> | ||||
| #include <cogl/cogl-texture-pixmap-x11.h> | ||||
|  | ||||
| #include <meta/errors.h> | ||||
| #include "window-private.h" | ||||
| #include "meta-shaped-texture-private.h" | ||||
| #include "meta-cullable.h" | ||||
|  | ||||
| struct _MetaSurfaceActorX11Private | ||||
| { | ||||
|   MetaWindow *window; | ||||
|  | ||||
|   MetaDisplay *display; | ||||
|  | ||||
|   CoglTexture *texture; | ||||
|   Pixmap pixmap; | ||||
|   Damage damage; | ||||
|  | ||||
|   int last_width; | ||||
|   int last_height; | ||||
|  | ||||
|   /* This is used to detect fullscreen windows that need to be unredirected */ | ||||
|   guint full_damage_frames_count; | ||||
|   guint does_full_damage  : 1; | ||||
|  | ||||
|   /* Other state... */ | ||||
|   guint argb32 : 1; | ||||
|   guint received_damage : 1; | ||||
|   guint size_changed : 1; | ||||
|  | ||||
|   guint unredirected   : 1; | ||||
| }; | ||||
| typedef struct _MetaSurfaceActorX11Private MetaSurfaceActorX11Private; | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_PRIVATE (MetaSurfaceActorX11, meta_surface_actor_x11, META_TYPE_SURFACE_ACTOR) | ||||
|  | ||||
| static void | ||||
| free_damage (MetaSurfaceActorX11 *self) | ||||
| { | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|   MetaDisplay *display = priv->display; | ||||
|   Display *xdisplay = meta_display_get_xdisplay (display); | ||||
|  | ||||
|   if (priv->damage == None) | ||||
|     return; | ||||
|  | ||||
|   meta_error_trap_push (display); | ||||
|   XDamageDestroy (xdisplay, priv->damage); | ||||
|   priv->damage = None; | ||||
|   meta_error_trap_pop (display); | ||||
| } | ||||
|  | ||||
| static void | ||||
| detach_pixmap (MetaSurfaceActorX11 *self) | ||||
| { | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|   MetaDisplay *display = priv->display; | ||||
|   Display *xdisplay = meta_display_get_xdisplay (display); | ||||
|   MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); | ||||
|  | ||||
|   if (priv->pixmap == None) | ||||
|     return; | ||||
|  | ||||
|   /* Get rid of all references to the pixmap before freeing it; it's unclear whether | ||||
|    * you are supposed to be able to free a GLXPixmap after freeing the underlying | ||||
|    * pixmap, but it certainly doesn't work with current DRI/Mesa | ||||
|    */ | ||||
|   meta_shaped_texture_set_texture (stex, NULL); | ||||
|   cogl_flush (); | ||||
|  | ||||
|   meta_error_trap_push (display); | ||||
|   XFreePixmap (xdisplay, priv->pixmap); | ||||
|   priv->pixmap = None; | ||||
|   meta_error_trap_pop (display); | ||||
|  | ||||
|   cogl_object_unref (priv->texture); | ||||
|   priv->texture = NULL; | ||||
| } | ||||
|  | ||||
| static void | ||||
| set_pixmap (MetaSurfaceActorX11 *self, | ||||
|             Pixmap               pixmap) | ||||
| { | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|  | ||||
|   CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); | ||||
|   MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); | ||||
|   CoglTexture *texture; | ||||
|  | ||||
|   g_assert (priv->pixmap == None); | ||||
|   priv->pixmap = pixmap; | ||||
|  | ||||
|   texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (ctx, priv->pixmap, FALSE, NULL)); | ||||
|  | ||||
|   if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (COGL_TEXTURE_PIXMAP_X11 (texture)))) | ||||
|     g_warning ("NOTE: Not using GLX TFP!\n"); | ||||
|  | ||||
|   priv->texture = texture; | ||||
|   meta_shaped_texture_set_texture (stex, texture); | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_pixmap (MetaSurfaceActorX11 *self) | ||||
| { | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|   MetaDisplay *display = priv->display; | ||||
|   Display *xdisplay = meta_display_get_xdisplay (display); | ||||
|  | ||||
|   if (priv->size_changed) | ||||
|     { | ||||
|       detach_pixmap (self); | ||||
|       priv->size_changed = FALSE; | ||||
|     } | ||||
|  | ||||
|   if (priv->pixmap == None) | ||||
|     { | ||||
|       Pixmap new_pixmap; | ||||
|       Window xwindow = meta_window_get_toplevel_xwindow (priv->window); | ||||
|  | ||||
|       meta_error_trap_push (display); | ||||
|       new_pixmap = XCompositeNameWindowPixmap (xdisplay, xwindow); | ||||
|  | ||||
|       if (meta_error_trap_pop_with_return (display) != Success) | ||||
|         { | ||||
|           /* Probably a BadMatch if the window isn't viewable; we could | ||||
|            * GrabServer/GetWindowAttributes/NameWindowPixmap/UngrabServer/Sync | ||||
|            * to avoid this, but there's no reason to take two round trips | ||||
|            * when one will do. (We need that Sync if we want to handle failures | ||||
|            * for any reason other than !viewable. That's unlikely, but maybe | ||||
|            * we'll BadAlloc or something.) | ||||
|            */ | ||||
|           new_pixmap = None; | ||||
|         } | ||||
|  | ||||
|       if (new_pixmap == None) | ||||
|         { | ||||
|           meta_verbose ("Unable to get named pixmap for %s\n", | ||||
|                         meta_window_get_description (priv->window)); | ||||
|           return; | ||||
|         } | ||||
|  | ||||
|       set_pixmap (self, new_pixmap); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| is_visible (MetaSurfaceActorX11 *self) | ||||
| { | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|   return (priv->pixmap != None) && !priv->unredirected; | ||||
| } | ||||
|  | ||||
| static void | ||||
| damage_area (MetaSurfaceActorX11 *self, | ||||
|              int x, int y, int width, int height) | ||||
| { | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|  | ||||
|   if (!is_visible (self)) | ||||
|     return; | ||||
|  | ||||
|   cogl_texture_pixmap_x11_update_area (priv->texture, x, y, width, height); | ||||
|   meta_surface_actor_update_area (META_SURFACE_ACTOR (self), x, y, width, height); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_x11_process_damage (MetaSurfaceActor *actor, | ||||
|                                        int x, int y, int width, int height) | ||||
| { | ||||
|   MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor); | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|  | ||||
|   priv->received_damage = TRUE; | ||||
|  | ||||
|   if (meta_window_is_fullscreen (priv->window) && !priv->unredirected && !priv->does_full_damage) | ||||
|     { | ||||
|       MetaRectangle window_rect; | ||||
|       meta_window_get_frame_rect (priv->window, &window_rect); | ||||
|  | ||||
|       if (window_rect.x == x && | ||||
|           window_rect.y == y && | ||||
|           window_rect.width == width && | ||||
|           window_rect.height == height) | ||||
|         priv->full_damage_frames_count++; | ||||
|       else | ||||
|         priv->full_damage_frames_count = 0; | ||||
|  | ||||
|       if (priv->full_damage_frames_count >= 100) | ||||
|         priv->does_full_damage = TRUE; | ||||
|     } | ||||
|  | ||||
|   /* Drop damage event for unredirected windows */ | ||||
|   if (priv->unredirected) | ||||
|     return; | ||||
|  | ||||
|   damage_area (self, x, y, width, height); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_x11_pre_paint (MetaSurfaceActor *actor) | ||||
| { | ||||
|   MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor); | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|   MetaDisplay *display = priv->display; | ||||
|   Display *xdisplay = meta_display_get_xdisplay (display); | ||||
|  | ||||
|   if (priv->received_damage) | ||||
|     { | ||||
|       meta_error_trap_push (display); | ||||
|       XDamageSubtract (xdisplay, priv->damage, None, None); | ||||
|       meta_error_trap_pop (display); | ||||
|  | ||||
|       /* We need to make sure that any X drawing that happens before the | ||||
|        * XDamageSubtract() above is visible to subsequent GL rendering; | ||||
|        * the only standardized way to do this is EXT_x11_sync_object, | ||||
|        * which isn't yet widely available. For now, we count on details | ||||
|        * of Xorg and the open source drivers, and hope for the best | ||||
|        * otherwise. | ||||
|        * | ||||
|        * Xorg and open source driver specifics: | ||||
|        * | ||||
|        * The X server makes sure to flush drawing to the kernel before | ||||
|        * sending out damage events, but since we use DamageReportBoundingBox | ||||
|        * there may be drawing between the last damage event and the | ||||
|        * XDamageSubtract() that needs to be flushed as well. | ||||
|        * | ||||
|        * Xorg always makes sure that drawing is flushed to the kernel | ||||
|        * before writing events or responses to the client, so any round trip | ||||
|        * request at this point is sufficient to flush the GLX buffers. | ||||
|        */ | ||||
|       XSync (xdisplay, False); | ||||
|  | ||||
|       priv->received_damage = FALSE; | ||||
|     } | ||||
|  | ||||
|   update_pixmap (self); | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_is_argb32 (MetaSurfaceActorX11 *self) | ||||
| { | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|   MetaDisplay *display = priv->display; | ||||
|   Display *xdisplay = meta_display_get_xdisplay (display); | ||||
|  | ||||
|   XRenderPictFormat *format; | ||||
|   format = XRenderFindVisualFormat (xdisplay, priv->window->xvisual); | ||||
|  | ||||
|   priv->argb32 = (format && format->type == PictTypeDirect && format->direct.alphaMask); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_surface_actor_x11_is_argb32 (MetaSurfaceActor *actor) | ||||
| { | ||||
|   MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor); | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|  | ||||
|   return priv->argb32; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_surface_actor_x11_is_visible (MetaSurfaceActor *actor) | ||||
| { | ||||
|   MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor); | ||||
|   return is_visible (self); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_surface_actor_x11_should_unredirect (MetaSurfaceActor *actor) | ||||
| { | ||||
|   MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor); | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|  | ||||
|   MetaWindow *window = priv->window; | ||||
|  | ||||
|   if (meta_window_requested_dont_bypass_compositor (window)) | ||||
|     return FALSE; | ||||
|  | ||||
|   if (window->opacity != 0xFF) | ||||
|     return FALSE; | ||||
|  | ||||
|   if (window->shape_region != NULL) | ||||
|     return FALSE; | ||||
|  | ||||
|   if (priv->argb32 && !meta_window_requested_bypass_compositor (window)) | ||||
|     return FALSE; | ||||
|  | ||||
|   if (!meta_window_is_monitor_sized (window)) | ||||
|     return FALSE; | ||||
|  | ||||
|   if (meta_window_requested_bypass_compositor (window)) | ||||
|     return TRUE; | ||||
|  | ||||
|   if (meta_window_is_override_redirect (window)) | ||||
|     return TRUE; | ||||
|  | ||||
|   if (priv->does_full_damage) | ||||
|     return TRUE; | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| sync_unredirected (MetaSurfaceActorX11 *self) | ||||
| { | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|   MetaDisplay *display = priv->display; | ||||
|   Display *xdisplay = meta_display_get_xdisplay (display); | ||||
|   Window xwindow = meta_window_get_toplevel_xwindow (priv->window); | ||||
|  | ||||
|   meta_error_trap_push (display); | ||||
|  | ||||
|   if (priv->unredirected) | ||||
|     { | ||||
|       detach_pixmap (self); | ||||
|       XCompositeUnredirectWindow (xdisplay, xwindow, CompositeRedirectManual); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       XCompositeRedirectWindow (xdisplay, xwindow, CompositeRedirectManual); | ||||
|     } | ||||
|  | ||||
|   meta_error_trap_pop (display); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_x11_set_unredirected (MetaSurfaceActor *actor, | ||||
|                                          gboolean          unredirected) | ||||
| { | ||||
|   MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor); | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|  | ||||
|   if (priv->unredirected == unredirected) | ||||
|     return; | ||||
|  | ||||
|   priv->unredirected = unredirected; | ||||
|   sync_unredirected (self); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_surface_actor_x11_is_unredirected (MetaSurfaceActor *actor) | ||||
| { | ||||
|   MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor); | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|  | ||||
|   return priv->unredirected; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_x11_dispose (GObject *object) | ||||
| { | ||||
|   MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (object); | ||||
|  | ||||
|   detach_pixmap (self); | ||||
|   free_damage (self); | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_surface_actor_x11_parent_class)->dispose (object); | ||||
| } | ||||
|  | ||||
| static MetaWindow * | ||||
| meta_surface_actor_x11_get_window (MetaSurfaceActor *actor) | ||||
| { | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (META_SURFACE_ACTOR_X11 (actor)); | ||||
|  | ||||
|   return priv->window; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_x11_class_init (MetaSurfaceActorX11Class *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|   MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass); | ||||
|  | ||||
|   object_class->dispose = meta_surface_actor_x11_dispose; | ||||
|  | ||||
|   surface_actor_class->process_damage = meta_surface_actor_x11_process_damage; | ||||
|   surface_actor_class->pre_paint = meta_surface_actor_x11_pre_paint; | ||||
|   surface_actor_class->is_argb32 = meta_surface_actor_x11_is_argb32; | ||||
|   surface_actor_class->is_visible = meta_surface_actor_x11_is_visible; | ||||
|  | ||||
|   surface_actor_class->should_unredirect = meta_surface_actor_x11_should_unredirect; | ||||
|   surface_actor_class->set_unredirected = meta_surface_actor_x11_set_unredirected; | ||||
|   surface_actor_class->is_unredirected = meta_surface_actor_x11_is_unredirected; | ||||
|  | ||||
|   surface_actor_class->get_window = meta_surface_actor_x11_get_window; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_x11_init (MetaSurfaceActorX11 *self) | ||||
| { | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|  | ||||
|   priv->last_width = -1; | ||||
|   priv->last_height = -1; | ||||
| } | ||||
|  | ||||
| static void | ||||
| create_damage (MetaSurfaceActorX11 *self) | ||||
| { | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|   Display *xdisplay = meta_display_get_xdisplay (priv->display); | ||||
|   Window xwindow = meta_window_get_toplevel_xwindow (priv->window); | ||||
|  | ||||
|   priv->damage = XDamageCreate (xdisplay, xwindow, XDamageReportBoundingBox); | ||||
| } | ||||
|  | ||||
| static void | ||||
| window_decorated_notify (MetaWindow *window, | ||||
|                          GParamSpec *pspec, | ||||
|                          gpointer    user_data) | ||||
| { | ||||
|   MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (user_data); | ||||
|  | ||||
|   free_damage (self); | ||||
|   create_damage (self); | ||||
| } | ||||
|  | ||||
| MetaSurfaceActor * | ||||
| meta_surface_actor_x11_new (MetaWindow *window) | ||||
| { | ||||
|   MetaSurfaceActorX11 *self = g_object_new (META_TYPE_SURFACE_ACTOR_X11, NULL); | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|   MetaDisplay *display = meta_window_get_display (window); | ||||
|  | ||||
|   g_assert (!meta_is_wayland_compositor ()); | ||||
|  | ||||
|   priv->window = window; | ||||
|   priv->display = display; | ||||
|  | ||||
|   create_damage (self); | ||||
|   g_signal_connect_object (priv->window, "notify::decorated", | ||||
|                            G_CALLBACK (window_decorated_notify), self, 0); | ||||
|  | ||||
|   update_is_argb32 (self); | ||||
|  | ||||
|   priv->unredirected = FALSE; | ||||
|   sync_unredirected (self); | ||||
|  | ||||
|   clutter_actor_set_reactive (CLUTTER_ACTOR (self), TRUE); | ||||
|   return META_SURFACE_ACTOR (self); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self, | ||||
|                                  int width, int height) | ||||
| { | ||||
|   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); | ||||
|  | ||||
|   if (priv->last_width == width && | ||||
|       priv->last_height == height) | ||||
|     return; | ||||
|  | ||||
|   priv->size_changed = TRUE; | ||||
|   priv->last_width = width; | ||||
|   priv->last_height = height; | ||||
| } | ||||
							
								
								
									
										69
									
								
								src/compositor/meta-surface-actor-x11.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								src/compositor/meta-surface-actor-x11.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2013 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Owen Taylor <otaylor@redhat.com> | ||||
|  *     Jasper St. Pierre <jstpierre@mecheye.net> | ||||
|  */ | ||||
|  | ||||
| #ifndef __META_SURFACE_ACTOR_X11_H__ | ||||
| #define __META_SURFACE_ACTOR_X11_H__ | ||||
|  | ||||
| #include <glib-object.h> | ||||
|  | ||||
| #include "meta-surface-actor.h" | ||||
|  | ||||
| #include <X11/extensions/Xdamage.h> | ||||
|  | ||||
| #include <meta/display.h> | ||||
| #include <meta/window.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define META_TYPE_SURFACE_ACTOR_X11            (meta_surface_actor_x11_get_type ()) | ||||
| #define META_SURFACE_ACTOR_X11(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11)) | ||||
| #define META_SURFACE_ACTOR_X11_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11Class)) | ||||
| #define META_IS_SURFACE_ACTOR_X11(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SURFACE_ACTOR_X11)) | ||||
| #define META_IS_SURFACE_ACTOR_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_SURFACE_ACTOR_X11)) | ||||
| #define META_SURFACE_ACTOR_X11_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11Class)) | ||||
|  | ||||
| typedef struct _MetaSurfaceActorX11      MetaSurfaceActorX11; | ||||
| typedef struct _MetaSurfaceActorX11Class MetaSurfaceActorX11Class; | ||||
|  | ||||
| struct _MetaSurfaceActorX11 | ||||
| { | ||||
|   MetaSurfaceActor parent; | ||||
| }; | ||||
|  | ||||
| struct _MetaSurfaceActorX11Class | ||||
| { | ||||
|   MetaSurfaceActorClass parent_class; | ||||
| }; | ||||
|  | ||||
| GType meta_surface_actor_x11_get_type (void); | ||||
|  | ||||
| MetaSurfaceActor * meta_surface_actor_x11_new (MetaWindow *window); | ||||
|  | ||||
| void meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self, | ||||
|                                       int width, int height); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __META_SURFACE_ACTOR_X11_H__ */ | ||||
| @@ -10,27 +10,38 @@ | ||||
|  */ | ||||
|  | ||||
| #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_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) | ||||
| @@ -39,9 +50,84 @@ meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor      *self, | ||||
|   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)); | ||||
| } | ||||
|  | ||||
| @@ -92,51 +178,14 @@ meta_surface_actor_get_texture (MetaSurfaceActor *self) | ||||
|   return self->priv->texture; | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_area (MetaSurfaceActor *self, | ||||
| 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); | ||||
|     } | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_surface_actor_damage_all (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)); | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_surface_actor_damage_area (MetaSurfaceActor *self, | ||||
|                                 int               x, | ||||
|                                 int               y, | ||||
|                                 int               width, | ||||
|                                 int               height) | ||||
| { | ||||
|   MetaSurfaceActorPrivate *priv = self->priv; | ||||
|  | ||||
|   update_area (self, x, y, width, height); | ||||
|   return meta_shaped_texture_update_area (priv->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 | ||||
| @@ -146,33 +195,19 @@ meta_surface_actor_is_obscured (MetaSurfaceActor *self) | ||||
|   return meta_shaped_texture_is_obscured (priv->texture); | ||||
| } | ||||
|  | ||||
| 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); | ||||
| } | ||||
|  | ||||
| void | ||||
| 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 | ||||
| @@ -183,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,33 +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); | ||||
|  | ||||
| gboolean meta_surface_actor_damage_all  (MetaSurfaceActor *self); | ||||
| gboolean meta_surface_actor_damage_area (MetaSurfaceActor *self, | ||||
|                                          int               x, | ||||
|                                          int               y, | ||||
|                                          int               width, | ||||
|                                          int               height); | ||||
| MetaWindow        *meta_surface_actor_get_window  (MetaSurfaceActor *self); | ||||
|  | ||||
| gboolean meta_surface_actor_is_obscured (MetaSurfaceActor *self); | ||||
| gboolean meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor      *self, | ||||
|                                                    cairo_rectangle_int_t *unobscured_bounds); | ||||
|  | ||||
| void meta_surface_actor_set_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" | ||||
| @@ -63,5 +60,6 @@ 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
											
										
									
								
							| @@ -164,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); | ||||
|   | ||||
| @@ -39,6 +39,7 @@ | ||||
| #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; | ||||
| @@ -749,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); | ||||
|         } | ||||
|     } | ||||
|   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); | ||||
| 	  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; | ||||
|  | ||||
|   | ||||
| @@ -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,7 +37,7 @@ | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
|  | ||||
| #include "meta-wayland-surface.h" | ||||
| #include "wayland/meta-wayland-surface.h" | ||||
|  | ||||
| static void meta_window_present_delete_dialog (MetaWindow *window, | ||||
|                                                guint32     timestamp); | ||||
| @@ -261,8 +261,7 @@ meta_window_present_delete_dialog (MetaWindow *window, guint32 timestamp) | ||||
|         { | ||||
|           MetaWindow *w = tmp->data; | ||||
|  | ||||
|           if (w->xtransient_for == window->xwindow && | ||||
|               w->res_class && | ||||
|           if (w->transient_for == window && w->res_class && | ||||
|               g_ascii_strcasecmp (w->res_class, "mutter-dialog") == 0) | ||||
|             { | ||||
|               meta_window_activate (w, timestamp); | ||||
|   | ||||
| @@ -84,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; | ||||
| @@ -125,7 +117,6 @@ struct _MetaDisplay | ||||
|    * like the no_focus_window or the stage X window. */ | ||||
|   Window focus_xwindow; | ||||
|   gulong focus_serial; | ||||
|   MetaFocusType focus_type; | ||||
|  | ||||
|   /* last timestamp passed to XSetInputFocus */ | ||||
|   guint32 last_focus_time; | ||||
| @@ -224,7 +215,6 @@ struct _MetaDisplay | ||||
|   gboolean    grab_threshold_movement_reached; /* raise_on_click == FALSE.    */ | ||||
|   MetaResizePopup *grab_resize_popup; | ||||
|   GTimeVal    grab_last_moveresize_time; | ||||
|   guint32     grab_motion_notify_time; | ||||
|   GList*      grab_old_window_stacking; | ||||
|   MetaEdgeResistanceData *grab_edge_resistance_data; | ||||
|   unsigned int grab_last_user_action_was_snap; | ||||
| @@ -242,8 +232,8 @@ struct _MetaDisplay | ||||
|   int	      grab_resize_timeout_id; | ||||
|  | ||||
|   /* Keybindings stuff */ | ||||
|   MetaKeyBinding *key_bindings; | ||||
|   int             n_key_bindings; | ||||
|   GHashTable     *key_bindings; | ||||
|   GHashTable     *key_bindings_index; | ||||
|   int             min_keycode; | ||||
|   int             max_keycode; | ||||
|   KeySym *keymap; | ||||
| @@ -495,7 +485,6 @@ gboolean meta_display_process_barrier_event (MetaDisplay *display, | ||||
|  | ||||
| void meta_display_set_input_focus_xwindow (MetaDisplay *display, | ||||
|                                            MetaScreen  *screen, | ||||
|                                            MetaFocusType  type, | ||||
|                                            Window       window, | ||||
|                                            guint32      timestamp); | ||||
|  | ||||
|   | ||||
| @@ -36,15 +36,11 @@ | ||||
| #include <meta/main.h> | ||||
| #include "screen-private.h" | ||||
| #include "window-private.h" | ||||
| #include "window-x11.h" | ||||
| #include "window-props.h" | ||||
| #include "group-props.h" | ||||
| #include "frame.h" | ||||
| #include <meta/errors.h> | ||||
| #include "keybindings-private.h" | ||||
| #include <meta/prefs.h> | ||||
| #include "resizepopup.h" | ||||
| #include "xprops.h" | ||||
| #include "workspace-private.h" | ||||
| #include "bell.h" | ||||
| #include <meta/compositor.h> | ||||
| @@ -72,15 +68,13 @@ | ||||
| #include <string.h> | ||||
| #include <unistd.h> | ||||
|  | ||||
| #include "meta-xwayland-private.h" | ||||
| #include "x11/window-x11.h" | ||||
| #include "x11/window-props.h" | ||||
| #include "x11/group-props.h" | ||||
| #include "x11/xprops.h" | ||||
|  | ||||
| #define GRAB_OP_IS_WINDOW_SWITCH(g)                     \ | ||||
|         (g == META_GRAB_OP_KEYBOARD_TABBING_NORMAL  ||  \ | ||||
|          g == META_GRAB_OP_KEYBOARD_TABBING_DOCK    ||  \ | ||||
|          g == META_GRAB_OP_KEYBOARD_TABBING_GROUP   ||  \ | ||||
|          g == META_GRAB_OP_KEYBOARD_ESCAPING_NORMAL ||  \ | ||||
|          g == META_GRAB_OP_KEYBOARD_ESCAPING_DOCK   ||  \ | ||||
|          g == META_GRAB_OP_KEYBOARD_ESCAPING_GROUP) | ||||
| #include "wayland/meta-xwayland-private.h" | ||||
| #include "meta-surface-actor-wayland.h" | ||||
|  | ||||
| /* | ||||
|  * SECTION:pings | ||||
| @@ -183,8 +177,6 @@ static void    prefs_changed_callback    (MetaPreference pref, | ||||
| static void    sanity_check_timestamps   (MetaDisplay *display, | ||||
|                                           guint32      known_good_timestamp); | ||||
|  | ||||
| MetaGroup*     get_focussed_group (MetaDisplay *display); | ||||
|  | ||||
| static void | ||||
| meta_display_get_property(GObject         *object, | ||||
|                           guint            prop_id, | ||||
| @@ -1302,10 +1294,6 @@ meta_get_display (void) | ||||
|   return the_display; | ||||
| } | ||||
|  | ||||
| #ifdef WITH_VERBOSE_MODE | ||||
| static gboolean dump_events = TRUE; | ||||
| #endif | ||||
|  | ||||
| static gboolean | ||||
| grab_op_is_mouse_only (MetaGrabOp op) | ||||
| { | ||||
| @@ -1374,13 +1362,6 @@ grab_op_is_keyboard (MetaGrabOp op) | ||||
|     case META_GRAB_OP_KEYBOARD_RESIZING_NE: | ||||
|     case META_GRAB_OP_KEYBOARD_RESIZING_SW: | ||||
|     case META_GRAB_OP_KEYBOARD_RESIZING_NW: | ||||
|     case META_GRAB_OP_KEYBOARD_TABBING_NORMAL: | ||||
|     case META_GRAB_OP_KEYBOARD_TABBING_DOCK: | ||||
|     case META_GRAB_OP_KEYBOARD_TABBING_GROUP: | ||||
|     case META_GRAB_OP_KEYBOARD_ESCAPING_NORMAL: | ||||
|     case META_GRAB_OP_KEYBOARD_ESCAPING_DOCK: | ||||
|     case META_GRAB_OP_KEYBOARD_ESCAPING_GROUP: | ||||
|     case META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING: | ||||
|     case META_GRAB_OP_COMPOSITOR: | ||||
|       return TRUE; | ||||
|  | ||||
| @@ -1432,6 +1413,20 @@ meta_grab_op_is_moving (MetaGrabOp op) | ||||
|     } | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| grab_op_should_block_mouse_events (MetaGrabOp op) | ||||
| { | ||||
|   switch (op) | ||||
|     { | ||||
|     case META_GRAB_OP_WAYLAND_CLIENT: | ||||
|     case META_GRAB_OP_COMPOSITOR: | ||||
|       return TRUE; | ||||
|  | ||||
|     default: | ||||
|       return FALSE; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_display_xserver_time_is_before: | ||||
|  * @display: a #MetaDisplay | ||||
| @@ -1681,9 +1676,19 @@ get_window_for_event (MetaDisplay        *display, | ||||
|   if (display->grab_op != META_GRAB_OP_NONE) | ||||
|     return display->grab_window; | ||||
|  | ||||
|   /* Always use the key focused window for key events. */ | ||||
|   switch (event->type) | ||||
|     { | ||||
|     case CLUTTER_KEY_PRESS: | ||||
|     case CLUTTER_KEY_RELEASE: | ||||
|       return display->focus_window; | ||||
|     default: | ||||
|       break; | ||||
|     } | ||||
|  | ||||
|   source = clutter_event_get_source (event); | ||||
|   if (META_IS_WINDOW_ACTOR (source)) | ||||
|     return meta_window_actor_get_meta_window (META_WINDOW_ACTOR (source)); | ||||
|   if (META_IS_SURFACE_ACTOR (source)) | ||||
|     return meta_surface_actor_get_window (META_SURFACE_ACTOR (source)); | ||||
|  | ||||
|   return NULL; | ||||
| } | ||||
| @@ -1742,7 +1747,6 @@ get_input_event (MetaDisplay *display, | ||||
|  | ||||
| static void | ||||
| update_focus_window (MetaDisplay *display, | ||||
|                      MetaFocusType  type, | ||||
|                      MetaWindow  *window, | ||||
|                      Window       xwindow, | ||||
|                      gulong       serial, | ||||
| @@ -1754,7 +1758,6 @@ update_focus_window (MetaDisplay   *display, | ||||
|   display->focused_by_us = focused_by_us; | ||||
|  | ||||
|   if (display->focus_xwindow == xwindow && | ||||
|       display->focus_type == type && | ||||
|       display->focus_window == window) | ||||
|     return; | ||||
|  | ||||
| @@ -1777,25 +1780,14 @@ update_focus_window (MetaDisplay   *display, | ||||
|       meta_window_set_focused_internal (previous, FALSE); | ||||
|     } | ||||
|  | ||||
|   display->focus_type = type; | ||||
|   display->focus_window = window; | ||||
|   display->focus_xwindow = xwindow; | ||||
|  | ||||
|   if (display->focus_window) | ||||
|     { | ||||
|       ClutterActor *window_actor; | ||||
|  | ||||
|       meta_topic (META_DEBUG_FOCUS, "* Focus --> %s with serial %lu\n", | ||||
|                   display->focus_window->desc, serial); | ||||
|       meta_window_set_focused_internal (display->focus_window, TRUE); | ||||
|  | ||||
|       /* XXX -- this is sort of a layer violation, but because we | ||||
|        * rely on the compositor for event delivery anyway, I don't | ||||
|        * think it's too bad... */ | ||||
|  | ||||
|       window_actor = CLUTTER_ACTOR (display->focus_window->compositor_private); | ||||
|       if (window_actor) | ||||
|         clutter_actor_grab_key_focus (window_actor); | ||||
|     } | ||||
|   else | ||||
|     meta_topic (META_DEBUG_FOCUS, "* Focus --> NULL with serial %lu\n", serial); | ||||
| @@ -1804,8 +1796,7 @@ update_focus_window (MetaDisplay   *display, | ||||
|     { | ||||
|       compositor = meta_wayland_compositor_get_default (); | ||||
|  | ||||
|       if (display->focus_type == META_FOCUS_NO_FOCUS_WINDOW || | ||||
|           display->focus_type == META_FOCUS_STAGE) | ||||
|       if (meta_display_xwindow_is_a_no_focus_window (display, xwindow)) | ||||
|         meta_wayland_compositor_set_input_focus (compositor, NULL); | ||||
|       else if (window && window->surface) | ||||
|         meta_wayland_compositor_set_input_focus (compositor, window); | ||||
| @@ -1849,7 +1840,6 @@ timestamp_too_old (MetaDisplay *display, | ||||
| static void | ||||
| request_xserver_input_focus_change (MetaDisplay *display, | ||||
|                                     MetaScreen  *screen, | ||||
|                                     MetaFocusType  type, | ||||
|                                     MetaWindow  *meta_window, | ||||
|                                     Window       xwindow, | ||||
|                                     guint32      timestamp) | ||||
| @@ -1885,7 +1875,6 @@ request_xserver_input_focus_change (MetaDisplay   *display, | ||||
|   meta_display_ungrab (display); | ||||
|  | ||||
|   update_focus_window (display, | ||||
|                        type, | ||||
|                        meta_window, | ||||
|                        xwindow, | ||||
|                        serial, | ||||
| @@ -1907,12 +1896,9 @@ handle_window_focus_event (MetaDisplay  *display, | ||||
|                            unsigned long serial) | ||||
| { | ||||
|   MetaWindow *focus_window; | ||||
|   MetaFocusType type; | ||||
| #ifdef WITH_VERBOSE_MODE | ||||
|   const char *window_type; | ||||
|  | ||||
|   type = META_FOCUS_NONE; | ||||
|  | ||||
|   /* Note the event can be on either the window or the frame, | ||||
|    * we focus the frame for shaded windows | ||||
|    */ | ||||
| @@ -1924,26 +1910,14 @@ handle_window_focus_event (MetaDisplay  *display, | ||||
|         window_type = "frame window"; | ||||
|       else | ||||
|         window_type = "unknown client window"; | ||||
|  | ||||
|       if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND) | ||||
|         type = META_FOCUS_WAYLAND_CLIENT; | ||||
|       else | ||||
|         type = META_FOCUS_X_CLIENT; | ||||
|     } | ||||
|   else if (meta_display_xwindow_is_a_no_focus_window (display, event->event)) | ||||
|     { | ||||
|     window_type = "no_focus_window"; | ||||
|       type = META_FOCUS_NO_FOCUS_WINDOW; | ||||
|     } | ||||
|   else if (meta_display_screen_for_root (display, event->event)) | ||||
|     window_type = "root window"; | ||||
|   else | ||||
|     window_type = "unknown window"; | ||||
|  | ||||
|   /* Don't change type if we don't know the new window */ | ||||
|   if (type == META_FOCUS_NONE) | ||||
|     type = display->focus_type; | ||||
|  | ||||
|   meta_topic (META_DEBUG_FOCUS, | ||||
|               "Focus %s event received on %s 0x%lx (%s) " | ||||
|               "mode %s detail %s serial %lu\n", | ||||
| @@ -2028,7 +2002,6 @@ handle_window_focus_event (MetaDisplay  *display, | ||||
|        display->server_focus_serial == display->focus_serial)) | ||||
|     { | ||||
|       update_focus_window (display, | ||||
|                            type, | ||||
|                            focus_window, | ||||
|                            focus_window ? focus_window->xwindow : None, | ||||
|                            display->server_focus_serial, | ||||
| @@ -2057,9 +2030,6 @@ meta_display_handle_event (MetaDisplay        *display, | ||||
|   gboolean bypass_clutter = FALSE, bypass_wayland = FALSE; | ||||
|   MetaWaylandCompositor *compositor = NULL; | ||||
|  | ||||
|   /* XXX -- we need to fill this in properly at some point... */ | ||||
|   gboolean frame_was_receiver = FALSE; | ||||
|  | ||||
|   if (meta_is_wayland_compositor ()) | ||||
|     { | ||||
|       compositor = meta_wayland_compositor_get_default (); | ||||
| @@ -2093,7 +2063,7 @@ meta_display_handle_event (MetaDisplay        *display, | ||||
|   switch (event->type) | ||||
|     { | ||||
|     case CLUTTER_BUTTON_PRESS: | ||||
|       if (display->grab_op == META_GRAB_OP_COMPOSITOR) | ||||
|       if (grab_op_should_block_mouse_events (display->grab_op)) | ||||
|         break; | ||||
|  | ||||
|       display->overlay_key_only_pressed = FALSE; | ||||
| @@ -2111,48 +2081,45 @@ meta_display_handle_event (MetaDisplay        *display, | ||||
|                       (display->grab_window ? | ||||
|                        display->grab_window->desc : | ||||
|                        "none")); | ||||
|           if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op)) | ||||
|             { | ||||
|               meta_topic (META_DEBUG_WINDOW_OPS, | ||||
|                           "Syncing to old stack positions.\n"); | ||||
|  | ||||
|               /* XXX: I'm not sure if this is the right thing to do. | ||||
|                  The pre-Wayland code was only calling | ||||
|                  meta_stack_set_positions if the modified window was a | ||||
|                  root window */ | ||||
|               if (event->any.source == CLUTTER_ACTOR (event->any.stage) && window && window->screen) | ||||
|                 meta_stack_set_positions (window->screen->stack, | ||||
|                                           display->grab_old_window_stacking); | ||||
|             } | ||||
|           meta_display_end_grab_op (display, event->any.time); | ||||
|           bypass_clutter = TRUE; | ||||
|           bypass_wayland = TRUE; | ||||
|         } | ||||
|       else if (window && display->grab_op == META_GRAB_OP_NONE) | ||||
|         { | ||||
|           gboolean begin_move = FALSE; | ||||
|           ClutterModifierType grab_mask; | ||||
|           gboolean unmodified; | ||||
|           gboolean fully_modified; | ||||
|  | ||||
|           grab_mask = display->window_grab_modifiers; | ||||
|           if (g_getenv ("MUTTER_DEBUG_BUTTON_GRABS")) | ||||
|             grab_mask |= CLUTTER_CONTROL_MASK; | ||||
|  | ||||
|           /* Two possible sources of an unmodified event; one is a | ||||
|            * client that's letting button presses pass through to the | ||||
|            * frame, the other is our focus_window_grab on unmodified | ||||
|            * button 1.  So for all such events we focus the window. | ||||
|           /* We have three passive button grabs: | ||||
|            * - on any button, without modifiers => focuses and maybe raises the window | ||||
|            * - on resize button, with modifiers => start an interactive resizing | ||||
|            *   (normally <Super>middle) | ||||
|            * - on move button, with modifiers => start an interactive move | ||||
|            *   (normally <Super>left) | ||||
|            * - on menu button, with modifiers => show the window menu | ||||
|            *   (normally <Super>right) | ||||
|            * | ||||
|            * We may get here because we actually have a button | ||||
|            * grab on the window, or because we're a wayland | ||||
|            * compositor and thus we see all the events, so we | ||||
|            * need to check if the event is interesting. | ||||
|            * We want an event that is not modified, for a window | ||||
|            * that has (or would have, the wayland case) the | ||||
|            * button grab active. | ||||
|            * | ||||
|            * We may have other events on the window, for example | ||||
|            * a click on a frame button, but that's not for us to | ||||
|            * care about. Just let the event through. | ||||
|            */ | ||||
|           unmodified = (event->button.modifier_state & grab_mask) == 0; | ||||
|           fully_modified = grab_mask && (event->button.modifier_state & grab_mask) == grab_mask; | ||||
|  | ||||
|           if (unmodified || | ||||
|               event->button.button == 1) | ||||
|             { | ||||
|               /* don't focus if frame received, will be lowered in | ||||
|                * frames.c or special-cased if the click was on a | ||||
|                * minimize/close button. | ||||
|                */ | ||||
|               if (!frame_was_receiver) | ||||
|           if (unmodified && window && window->have_focus_click_grab) | ||||
|             { | ||||
|               if (meta_prefs_get_raise_on_click ()) | ||||
|                 meta_window_raise (window); | ||||
| @@ -2175,15 +2142,15 @@ meta_display_handle_event (MetaDisplay        *display, | ||||
|                  * window mappings after the user clicks on a panel. | ||||
|                  */ | ||||
|                 display->allow_terminal_deactivation = TRUE; | ||||
|                 } | ||||
|  | ||||
|               /* you can move on alt-click but not on | ||||
|                * the click-to-focus | ||||
|                */ | ||||
|               if (!unmodified) | ||||
|                 begin_move = TRUE; | ||||
|               meta_verbose ("Allowing events time %u\n", | ||||
|                             (unsigned int)event->button.time); | ||||
|  | ||||
|               XIAllowEvents (display->xdisplay, clutter_input_device_get_device_id (event->button.device), | ||||
|                              XIReplayDevice, event->button.time); | ||||
|               bypass_clutter = TRUE; | ||||
|             } | ||||
|           else if (!unmodified && ((int) event->button.button == meta_prefs_get_mouse_button_resize ())) | ||||
|           else if (fully_modified && (int) event->button.button == meta_prefs_get_mouse_button_resize ()) | ||||
|             { | ||||
|               if (window->has_resize_func) | ||||
|                 { | ||||
| @@ -2231,8 +2198,10 @@ meta_display_handle_event (MetaDisplay        *display, | ||||
|                                                 event->button.x, | ||||
|                                                 event->button.y); | ||||
|                 } | ||||
|               bypass_clutter = TRUE; | ||||
|               bypass_wayland = TRUE; | ||||
|             } | ||||
|           else if ((int) event->button.button == meta_prefs_get_mouse_button_menu ()) | ||||
|           else if (fully_modified && (int) event->button.button == meta_prefs_get_mouse_button_menu ()) | ||||
|             { | ||||
|               if (meta_prefs_get_raise_on_click ()) | ||||
|                 meta_window_raise (window); | ||||
| @@ -2244,8 +2213,9 @@ meta_display_handle_event (MetaDisplay        *display, | ||||
|               bypass_clutter = TRUE; | ||||
|               bypass_wayland = TRUE; | ||||
|             } | ||||
|  | ||||
|           if (begin_move && window->has_move_func) | ||||
|           else if (fully_modified && (int) event->button.button == 1) | ||||
|             { | ||||
|               if (window->has_move_func) | ||||
|                 { | ||||
|                   meta_display_begin_grab_op (display, | ||||
|                                               window->screen, | ||||
| @@ -2258,13 +2228,14 @@ meta_display_handle_event (MetaDisplay        *display, | ||||
|                                               event->any.time, | ||||
|                                               event->button.x, | ||||
|                                               event->button.y); | ||||
|                 } | ||||
|               bypass_clutter = TRUE; | ||||
|               bypass_wayland = TRUE; | ||||
|             } | ||||
|         } | ||||
|       break; | ||||
|     case CLUTTER_BUTTON_RELEASE: | ||||
|       if (display->grab_op == META_GRAB_OP_COMPOSITOR) | ||||
|       if (grab_op_should_block_mouse_events (display->grab_op)) | ||||
|         break; | ||||
|  | ||||
|       display->overlay_key_only_pressed = FALSE; | ||||
| @@ -2278,7 +2249,7 @@ meta_display_handle_event (MetaDisplay        *display, | ||||
|         } | ||||
|       break; | ||||
|     case CLUTTER_MOTION: | ||||
|       if (display->grab_op == META_GRAB_OP_COMPOSITOR) | ||||
|       if (grab_op_should_block_mouse_events (display->grab_op)) | ||||
|         break; | ||||
|  | ||||
|       if (display->grab_window == window && | ||||
| @@ -2312,6 +2283,10 @@ meta_display_handle_event (MetaDisplay        *display, | ||||
|   if (display->grab_op == META_GRAB_OP_COMPOSITOR) | ||||
|     bypass_wayland = TRUE; | ||||
|  | ||||
|   /* If a Wayland client has a grab, don't pass that through to Clutter */ | ||||
|   if (display->grab_op == META_GRAB_OP_WAYLAND_CLIENT) | ||||
|     bypass_clutter = TRUE; | ||||
|  | ||||
|   if (compositor && !bypass_wayland) | ||||
|     { | ||||
|       if (meta_wayland_compositor_handle_event (compositor, event)) | ||||
| @@ -2326,11 +2301,10 @@ handle_input_xevent (MetaDisplay *display, | ||||
|                      XIEvent     *input_event, | ||||
|                      gulong       serial) | ||||
| { | ||||
|   XIDeviceEvent *device_event = (XIDeviceEvent *) input_event; | ||||
|   XIEnterEvent *enter_event = (XIEnterEvent *) input_event; | ||||
|   Window modified; | ||||
|   MetaWindow *window; | ||||
|   gboolean frame_was_receiver; | ||||
|   MetaScreen *screen; | ||||
|  | ||||
|   if (input_event == NULL) | ||||
|     return FALSE; | ||||
| @@ -2338,242 +2312,8 @@ handle_input_xevent (MetaDisplay *display, | ||||
|   modified = xievent_get_modified_window (display, input_event); | ||||
|   window = modified != None ? meta_display_lookup_x_window (display, modified) : NULL; | ||||
|  | ||||
|   frame_was_receiver = FALSE; | ||||
|   if (window && | ||||
|       window->frame && | ||||
|       modified == window->frame->xwindow) | ||||
|     { | ||||
|       /* Note that if the frame and the client both have an | ||||
|        * XGrabButton (as is normal with our setup), the event | ||||
|        * goes to the frame. | ||||
|        */ | ||||
|       frame_was_receiver = TRUE; | ||||
|       meta_topic (META_DEBUG_EVENTS, "Frame was receiver of event for %s\n", | ||||
|                   window->desc); | ||||
|     } | ||||
|  | ||||
|   if (window && !window->override_redirect && | ||||
|       (input_event->evtype == XI_KeyPress || input_event->evtype == XI_ButtonPress)) | ||||
|     { | ||||
|       if (CurrentTime == display->current_time) | ||||
|         { | ||||
|           /* We can't use missing (i.e. invalid) timestamps to set user time, | ||||
|            * nor do we want to use them to sanity check other timestamps. | ||||
|            * See bug 313490 for more details. | ||||
|            */ | ||||
|           meta_warning ("Event has no timestamp! You may be using a broken " | ||||
|                         "program such as xse.  Please ask the authors of that " | ||||
|                         "program to fix it.\n"); | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           meta_window_set_user_time (window, display->current_time); | ||||
|           sanity_check_timestamps (display, display->current_time); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   switch (input_event->evtype) | ||||
|     { | ||||
|     case XI_ButtonPress: | ||||
|       if (display->grab_op == META_GRAB_OP_COMPOSITOR) | ||||
|         break; | ||||
|  | ||||
|       display->overlay_key_only_pressed = FALSE; | ||||
|  | ||||
|       if (device_event->detail == 4 || device_event->detail == 5) | ||||
|         /* Scrollwheel event, do nothing and deliver event to compositor below */ | ||||
|         break; | ||||
|  | ||||
|       if ((window && | ||||
|            meta_grab_op_is_mouse (display->grab_op) && | ||||
|            (device_event->mods.effective & display->window_grab_modifiers) && | ||||
|            display->grab_button != device_event->detail && | ||||
|            display->grab_window == window) || | ||||
|           grab_op_is_keyboard (display->grab_op)) | ||||
|         { | ||||
|           meta_topic (META_DEBUG_WINDOW_OPS, | ||||
|                       "Ending grab op %u on window %s due to button press\n", | ||||
|                       display->grab_op, | ||||
|                       (display->grab_window ? | ||||
|                        display->grab_window->desc : | ||||
|                        "none")); | ||||
|           if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op)) | ||||
|             { | ||||
|               MetaScreen *screen; | ||||
|               meta_topic (META_DEBUG_WINDOW_OPS, | ||||
|                           "Syncing to old stack positions.\n"); | ||||
|               screen = | ||||
|                 meta_display_screen_for_root (display, device_event->event); | ||||
|  | ||||
|               if (screen!=NULL) | ||||
|                 meta_stack_set_positions (screen->stack, | ||||
|                                           display->grab_old_window_stacking); | ||||
|             } | ||||
|           meta_display_end_grab_op (display, | ||||
|                                     device_event->time); | ||||
|         } | ||||
|       else if (window && display->grab_op == META_GRAB_OP_NONE) | ||||
|         { | ||||
|           gboolean begin_move = FALSE; | ||||
|           unsigned int grab_mask; | ||||
|           gboolean unmodified; | ||||
|  | ||||
|           grab_mask = display->window_grab_modifiers; | ||||
|           if (g_getenv ("MUTTER_DEBUG_BUTTON_GRABS")) | ||||
|             grab_mask |= ControlMask; | ||||
|  | ||||
|           /* Two possible sources of an unmodified event; one is a | ||||
|            * client that's letting button presses pass through to the | ||||
|            * frame, the other is our focus_window_grab on unmodified | ||||
|            * button 1.  So for all such events we focus the window. | ||||
|            */ | ||||
|           unmodified = (device_event->mods.effective & grab_mask) == 0; | ||||
|  | ||||
|           if (unmodified || | ||||
|               device_event->detail == 1) | ||||
|             { | ||||
|               /* don't focus if frame received, will be lowered in | ||||
|                * frames.c or special-cased if the click was on a | ||||
|                * minimize/close button. | ||||
|                */ | ||||
|               if (!frame_was_receiver) | ||||
|                 { | ||||
|                   if (meta_prefs_get_raise_on_click ()) | ||||
|                     meta_window_raise (window); | ||||
|                   else | ||||
|                     meta_topic (META_DEBUG_FOCUS, | ||||
|                                 "Not raising window on click due to don't-raise-on-click option\n"); | ||||
|  | ||||
|                   /* Don't focus panels--they must explicitly request focus. | ||||
|                    * See bug 160470 | ||||
|                    */ | ||||
|                   if (window->type != META_WINDOW_DOCK) | ||||
|                     { | ||||
|                       meta_topic (META_DEBUG_FOCUS, | ||||
|                                   "Focusing %s due to unmodified button %u press (display.c)\n", | ||||
|                                   window->desc, device_event->detail); | ||||
|                       meta_window_focus (window, device_event->time); | ||||
|                     } | ||||
|                   else | ||||
|                     /* However, do allow terminals to lose focus due to new | ||||
|                      * window mappings after the user clicks on a panel. | ||||
|                      */ | ||||
|                     display->allow_terminal_deactivation = TRUE; | ||||
|                 } | ||||
|  | ||||
|               /* you can move on alt-click but not on | ||||
|                * the click-to-focus | ||||
|                */ | ||||
|               if (!unmodified) | ||||
|                 begin_move = TRUE; | ||||
|             } | ||||
|           else if (!unmodified && device_event->detail == meta_prefs_get_mouse_button_resize()) | ||||
|             { | ||||
|               if (window->has_resize_func) | ||||
|                 { | ||||
|                   gboolean north, south; | ||||
|                   gboolean west, east; | ||||
|                   MetaRectangle frame_rect; | ||||
|                   MetaGrabOp op; | ||||
|  | ||||
|                   meta_window_get_frame_rect (window, &frame_rect); | ||||
|  | ||||
|                   west = device_event->root_x <  (frame_rect.x + 1 * frame_rect.width  / 3); | ||||
|                   east = device_event->root_x >  (frame_rect.x + 2 * frame_rect.width  / 3); | ||||
|                   north = device_event->root_y < (frame_rect.y + 1 * frame_rect.height / 3); | ||||
|                   south = device_event->root_y > (frame_rect.y + 2 * frame_rect.height / 3); | ||||
|  | ||||
|                   if (north && west) | ||||
|                     op = META_GRAB_OP_RESIZING_NW; | ||||
|                   else if (north && east) | ||||
|                     op = META_GRAB_OP_RESIZING_NE; | ||||
|                   else if (south && west) | ||||
|                     op = META_GRAB_OP_RESIZING_SW; | ||||
|                   else if (south && east) | ||||
|                     op = META_GRAB_OP_RESIZING_SE; | ||||
|                   else if (north) | ||||
|                     op = META_GRAB_OP_RESIZING_N; | ||||
|                   else if (west) | ||||
|                     op = META_GRAB_OP_RESIZING_W; | ||||
|                   else if (east) | ||||
|                     op = META_GRAB_OP_RESIZING_E; | ||||
|                   else if (south) | ||||
|                     op = META_GRAB_OP_RESIZING_S; | ||||
|                   else /* Middle region is no-op to avoid user triggering wrong action */ | ||||
|                     op = META_GRAB_OP_NONE; | ||||
|  | ||||
|                   if (op != META_GRAB_OP_NONE) | ||||
|                     meta_display_begin_grab_op (display, | ||||
|                                                 window->screen, | ||||
|                                                 window, | ||||
|                                                 op, | ||||
|                                                 TRUE, | ||||
|                                                 FALSE, | ||||
|                                                 device_event->detail, | ||||
|                                                 0, | ||||
|                                                 device_event->time, | ||||
|                                                 device_event->root_x, | ||||
|                                                 device_event->root_y); | ||||
|                 } | ||||
|             } | ||||
|           else if (device_event->detail == meta_prefs_get_mouse_button_menu()) | ||||
|             { | ||||
|               if (meta_prefs_get_raise_on_click ()) | ||||
|                 meta_window_raise (window); | ||||
|               meta_window_show_menu (window, | ||||
|                                      device_event->root_x, | ||||
|                                      device_event->root_y, | ||||
|                                      device_event->detail, | ||||
|                                      device_event->time); | ||||
|             } | ||||
|  | ||||
|           if (!frame_was_receiver && unmodified) | ||||
|             { | ||||
|               /* This is from our synchronous grab since | ||||
|                * it has no modifiers and was on the client window | ||||
|                */ | ||||
|  | ||||
|               meta_verbose ("Allowing events time %u\n", | ||||
|                             (unsigned int)device_event->time); | ||||
|  | ||||
|               XIAllowEvents (display->xdisplay, device_event->deviceid, | ||||
|                              XIReplayDevice, device_event->time); | ||||
|             } | ||||
|  | ||||
|           if (begin_move && window->has_move_func) | ||||
|             { | ||||
|               meta_display_begin_grab_op (display, | ||||
|                                           window->screen, | ||||
|                                           window, | ||||
|                                           META_GRAB_OP_MOVING, | ||||
|                                           TRUE, | ||||
|                                           FALSE, | ||||
|                                           device_event->detail, | ||||
|                                           0, | ||||
|                                           device_event->time, | ||||
|                                           device_event->root_x, | ||||
|                                           device_event->root_y); | ||||
|             } | ||||
|         } | ||||
|       break; | ||||
|     case XI_ButtonRelease: | ||||
|       if (display->grab_op == META_GRAB_OP_COMPOSITOR) | ||||
|         break; | ||||
|  | ||||
|       display->overlay_key_only_pressed = FALSE; | ||||
|  | ||||
|       if (display->grab_window == window && | ||||
|           meta_grab_op_is_mouse (display->grab_op)) | ||||
|         meta_window_handle_mouse_grab_op_xevent (window, device_event); | ||||
|       break; | ||||
|     case XI_Motion: | ||||
|       if (display->grab_op == META_GRAB_OP_COMPOSITOR) | ||||
|         break; | ||||
|  | ||||
|       if (display->grab_window == window && | ||||
|           meta_grab_op_is_mouse (display->grab_op)) | ||||
|         meta_window_handle_mouse_grab_op_xevent (window, device_event); | ||||
|       break; | ||||
|     case XI_Enter: | ||||
|       if (display->grab_op == META_GRAB_OP_COMPOSITOR) | ||||
|         break; | ||||
| @@ -2629,12 +2369,11 @@ handle_input_xevent (MetaDisplay *display, | ||||
|       if (!window) | ||||
|         { | ||||
|           /* Check if the window is a root window. */ | ||||
|           MetaScreen *screen = | ||||
|             meta_display_screen_for_root(display, | ||||
|                                          enter_event->event); | ||||
|           if (screen == NULL) | ||||
|           if (enter_event->root != enter_event->event) | ||||
|             break; | ||||
|  | ||||
|           screen = meta_display_screen_for_root (display, enter_event->root); | ||||
|  | ||||
|           if (enter_event->evtype == XI_FocusIn && | ||||
|               enter_event->mode == XINotifyDetailNone) | ||||
|             { | ||||
| @@ -2660,7 +2399,9 @@ handle_input_xevent (MetaDisplay *display, | ||||
|             } | ||||
|  | ||||
|         } | ||||
|       break; | ||||
|  | ||||
|       /* Don't send FocusIn / FocusOut to Clutter */ | ||||
|       return TRUE; | ||||
|     } | ||||
|  | ||||
|   return FALSE; | ||||
| @@ -2879,7 +2620,7 @@ handle_other_xevent (MetaDisplay *display, | ||||
|       /* NB: override redirect windows wont cause a map request so we | ||||
|        * watch out for map notifies against any root windows too if a | ||||
|        * compositor is enabled: */ | ||||
|       if (display->compositor && window == NULL | ||||
|       if (window == NULL | ||||
|           && meta_display_screen_for_root (display, event->xmap.event)) | ||||
|         { | ||||
|           window = meta_window_x11_new (display, event->xmap.window, | ||||
| @@ -2934,7 +2675,7 @@ handle_other_xevent (MetaDisplay *display, | ||||
|         } | ||||
|  | ||||
|       if (window && window->override_redirect) | ||||
|         meta_window_configure_notify (window, &event->xconfigure); | ||||
|         meta_window_x11_configure_notify (window, &event->xconfigure); | ||||
|  | ||||
|       break; | ||||
|     case ConfigureRequest: | ||||
| @@ -3246,8 +2987,7 @@ meta_display_handle_xevent (MetaDisplay *display, | ||||
|   MetaMonitorManager *monitor; | ||||
|   MetaScreen *screen; | ||||
|  | ||||
| #ifdef WITH_VERBOSE_MODE | ||||
|   if (dump_events) | ||||
| #if 0 | ||||
|   meta_spew_event (display, event); | ||||
| #endif | ||||
|  | ||||
| @@ -3277,7 +3017,6 @@ meta_display_handle_xevent (MetaDisplay *display, | ||||
|       meta_topic (META_DEBUG_FOCUS, "Earlier attempt to focus %s failed\n", | ||||
|                   display->focus_window->desc); | ||||
|       update_focus_window (display, | ||||
|                            META_FOCUS_NONE, | ||||
|                            meta_display_lookup_x_window (display, display->server_focus_window), | ||||
|                            display->server_focus_window, | ||||
|                            display->server_focus_serial, | ||||
| @@ -3345,7 +3084,7 @@ meta_display_handle_xevent (MetaDisplay *display, | ||||
|     } | ||||
|  | ||||
|  out: | ||||
|   if (display->compositor && !bypass_compositor) | ||||
|   if (!bypass_compositor) | ||||
|     { | ||||
|       MetaWindow *window = modified != None ? meta_display_lookup_x_window (display, modified) : NULL; | ||||
|  | ||||
| @@ -3525,8 +3264,7 @@ event_get_time (MetaDisplay *display, | ||||
|     } | ||||
| } | ||||
|  | ||||
| #ifdef WITH_VERBOSE_MODE | ||||
| const char* | ||||
| G_GNUC_UNUSED const char* | ||||
| meta_event_detail_to_string (int d) | ||||
| { | ||||
|   const char *detail = "???"; | ||||
| @@ -3562,10 +3300,8 @@ meta_event_detail_to_string (int d) | ||||
|  | ||||
|   return detail; | ||||
| } | ||||
| #endif /* WITH_VERBOSE_MODE */ | ||||
|  | ||||
| #ifdef WITH_VERBOSE_MODE | ||||
| const char* | ||||
| G_GNUC_UNUSED const char* | ||||
| meta_event_mode_to_string (int m) | ||||
| { | ||||
|   const char *mode = "???"; | ||||
| @@ -3587,10 +3323,8 @@ meta_event_mode_to_string (int m) | ||||
|  | ||||
|   return mode; | ||||
| } | ||||
| #endif /* WITH_VERBOSE_MODE */ | ||||
|  | ||||
| #ifdef WITH_VERBOSE_MODE | ||||
| static const char* | ||||
| G_GNUC_UNUSED static const char* | ||||
| stack_mode_to_string (int mode) | ||||
| { | ||||
|   switch (mode) | ||||
| @@ -3609,11 +3343,9 @@ stack_mode_to_string (int mode) | ||||
|  | ||||
|   return "Unknown"; | ||||
| } | ||||
| #endif /* WITH_VERBOSE_MODE */ | ||||
|  | ||||
| #ifdef HAVE_XSYNC | ||||
| #ifdef WITH_VERBOSE_MODE | ||||
| static gint64 | ||||
| G_GNUC_UNUSED static gint64 | ||||
| sync_value_to_64 (const XSyncValue *value) | ||||
| { | ||||
|   gint64 v; | ||||
| @@ -3623,10 +3355,8 @@ sync_value_to_64 (const XSyncValue *value) | ||||
|    | ||||
|   return v; | ||||
| } | ||||
| #endif /* WITH_VERBOSE_MODE */ | ||||
|  | ||||
| #ifdef WITH_VERBOSE_MODE | ||||
| static const char* | ||||
| G_GNUC_UNUSED static const char* | ||||
| alarm_state_to_string (XSyncAlarmState state) | ||||
| { | ||||
|   switch (state) | ||||
| @@ -3641,12 +3371,9 @@ alarm_state_to_string (XSyncAlarmState state) | ||||
|       return "(unknown)"; | ||||
|     } | ||||
| } | ||||
| #endif /* WITH_VERBOSE_MODE */ | ||||
|  | ||||
| #endif /* HAVE_XSYNC */ | ||||
|  | ||||
| #ifdef WITH_VERBOSE_MODE | ||||
| static void | ||||
| G_GNUC_UNUSED static void | ||||
| meta_spew_xi2_event (MetaDisplay *display, | ||||
|                      XIEvent     *input_event, | ||||
|                      const char **name_p, | ||||
| @@ -3655,26 +3382,10 @@ meta_spew_xi2_event (MetaDisplay *display, | ||||
|   const char *name = NULL; | ||||
|   char *extra = NULL; | ||||
|  | ||||
|   XIDeviceEvent *device_event = (XIDeviceEvent *) input_event; | ||||
|   XIEnterEvent *enter_event = (XIEnterEvent *) input_event; | ||||
|  | ||||
|   switch (input_event->evtype) | ||||
|     { | ||||
|     case XI_Motion: | ||||
|       name = "XI_Motion"; | ||||
|       break; | ||||
|     case XI_ButtonPress: | ||||
|       name = "XI_ButtonPress"; | ||||
|       break; | ||||
|     case XI_ButtonRelease: | ||||
|       name = "XI_ButtonRelease"; | ||||
|       break; | ||||
|     case XI_KeyPress: | ||||
|       name = "XI_KeyPress"; | ||||
|       break; | ||||
|     case XI_KeyRelease: | ||||
|       name = "XI_KeyRelease"; | ||||
|       break; | ||||
|     case XI_FocusIn: | ||||
|       name = "XI_FocusIn"; | ||||
|       break; | ||||
| @@ -3699,34 +3410,6 @@ meta_spew_xi2_event (MetaDisplay *display, | ||||
|  | ||||
|   switch (input_event->evtype) | ||||
|     { | ||||
|     case XI_Motion: | ||||
|       extra = g_strdup_printf ("win: 0x%lx x: %g y: %g", | ||||
|                                device_event->event, | ||||
|                                device_event->root_x, | ||||
|                                device_event->root_y); | ||||
|       break; | ||||
|     case XI_ButtonPress: | ||||
|     case XI_ButtonRelease: | ||||
|       extra = g_strdup_printf ("button %u x %g y %g root 0x%lx", | ||||
|                                device_event->detail, | ||||
|                                device_event->root_x, | ||||
|                                device_event->root_y, | ||||
|                                device_event->root); | ||||
|       break; | ||||
|     case XI_KeyPress: | ||||
|     case XI_KeyRelease: | ||||
|       { | ||||
|         KeySym keysym; | ||||
|         const char *str; | ||||
|    | ||||
|         keysym = XKeycodeToKeysym (display->xdisplay, device_event->detail, 0); | ||||
|  | ||||
|         str = XKeysymToString (keysym); | ||||
|  | ||||
|         extra = g_strdup_printf ("Key '%s' state 0x%x", | ||||
|                                  str ? str : "none", device_event->mods.effective); | ||||
|       } | ||||
|       break; | ||||
|     case XI_FocusIn: | ||||
|     case XI_FocusOut: | ||||
|       extra = g_strdup_printf ("detail: %s mode: %s\n", | ||||
| @@ -3750,7 +3433,7 @@ meta_spew_xi2_event (MetaDisplay *display, | ||||
|   *extra_p = extra; | ||||
| } | ||||
|  | ||||
| static void | ||||
| G_GNUC_UNUSED static void | ||||
| meta_spew_core_event (MetaDisplay *display, | ||||
|                       XEvent      *event, | ||||
|                       const char **name_p, | ||||
| @@ -3974,7 +3657,7 @@ meta_spew_core_event (MetaDisplay *display, | ||||
|   *extra_p = extra; | ||||
| } | ||||
|  | ||||
| static void | ||||
| G_GNUC_UNUSED static void | ||||
| meta_spew_event (MetaDisplay *display, | ||||
|                  XEvent      *event) | ||||
| { | ||||
| @@ -3984,9 +3667,6 @@ meta_spew_event (MetaDisplay *display, | ||||
|   MetaScreen *screen; | ||||
|   XIEvent *input_event; | ||||
|    | ||||
|   if (!meta_is_verbose()) | ||||
|     return; | ||||
|    | ||||
|   /* filter overnumerous events */ | ||||
|   if (event->type == Expose || event->type == MotionNotify || | ||||
|       event->type == NoExpose) | ||||
| @@ -4015,8 +3695,7 @@ meta_spew_event (MetaDisplay *display, | ||||
|   else | ||||
|     winname = g_strdup_printf ("0x%lx", event->xany.window); | ||||
|  | ||||
|   meta_topic (META_DEBUG_EVENTS, | ||||
|               "%s on %s%s %s %sserial %lu\n", name, winname, | ||||
|   g_print ("%s on %s%s %s %sserial %lu\n", name, winname, | ||||
|            extra ? ":" : "", extra ? extra : "", | ||||
|            event->xany.send_event ? "SEND " : "", | ||||
|            event->xany.serial); | ||||
| @@ -4026,7 +3705,6 @@ meta_spew_event (MetaDisplay *display, | ||||
|   if (extra) | ||||
|     g_free (extra); | ||||
| } | ||||
| #endif /* WITH_VERBOSE_MODE */ | ||||
|  | ||||
| MetaWindow* | ||||
| meta_display_lookup_x_window (MetaDisplay *display, | ||||
| @@ -4354,7 +4032,6 @@ meta_display_begin_grab_op (MetaDisplay *display, | ||||
|   display->grab_latest_motion_y = root_y; | ||||
|   display->grab_last_moveresize_time.tv_sec = 0; | ||||
|   display->grab_last_moveresize_time.tv_usec = 0; | ||||
|   display->grab_motion_notify_time = 0; | ||||
|   display->grab_old_window_stacking = NULL; | ||||
| #ifdef HAVE_XSYNC | ||||
|   display->grab_last_user_action_was_snap = FALSE; | ||||
| @@ -4391,16 +4068,6 @@ meta_display_begin_grab_op (MetaDisplay *display, | ||||
|   g_assert (display->grab_window != NULL || display->grab_screen != NULL); | ||||
|   g_assert (display->grab_op != META_GRAB_OP_NONE); | ||||
|  | ||||
|   /* Save the old stacking */ | ||||
|   if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op)) | ||||
|     { | ||||
|       meta_topic (META_DEBUG_WINDOW_OPS, | ||||
|                   "Saving old stack positions; old pointer was %p.\n", | ||||
|                   display->grab_old_window_stacking); | ||||
|       display->grab_old_window_stacking =  | ||||
|         meta_stack_get_positions (screen->stack); | ||||
|     } | ||||
|  | ||||
|   if (display->grab_window) | ||||
|     { | ||||
|       meta_window_refresh_resize_popup (display->grab_window); | ||||
| @@ -4443,20 +4110,6 @@ meta_display_end_grab_op (MetaDisplay *display, | ||||
|         meta_window_raise (display->grab_window); | ||||
|     } | ||||
|    | ||||
|   if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op) || | ||||
|       display->grab_op == META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING) | ||||
|     { | ||||
|       if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op)) | ||||
|         meta_screen_tab_popup_destroy (display->grab_screen); | ||||
|       else | ||||
|         meta_screen_workspace_popup_destroy (display->grab_screen); | ||||
|  | ||||
|       /* If the ungrab here causes an EnterNotify, ignore it for | ||||
|        * sloppy focus | ||||
|        */ | ||||
|       display->ungrab_should_not_cause_focus_window = display->grab_xwindow; | ||||
|     } | ||||
|    | ||||
|   /* If this was a move or resize clear out the edge cache */ | ||||
|   if (meta_grab_op_is_resizing (display->grab_op) ||  | ||||
|       meta_grab_op_is_moving (display->grab_op)) | ||||
| @@ -4980,7 +4633,7 @@ meta_display_ping_window (MetaWindow        *window, | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   if (!window->net_wm_ping) | ||||
|   if (!window->can_ping) | ||||
|     { | ||||
|       if (ping_reply_func) | ||||
|         (* ping_reply_func) (window, timestamp, user_data); | ||||
| @@ -5122,8 +4775,8 @@ meta_display_pong_for_serial (MetaDisplay    *display, | ||||
|     } | ||||
| } | ||||
|  | ||||
| MetaGroup* | ||||
| get_focussed_group (MetaDisplay *display) | ||||
| static MetaGroup * | ||||
| get_focused_group (MetaDisplay *display) | ||||
| { | ||||
|   if (display->focus_window) | ||||
|     return display->focus_window->group; | ||||
| @@ -5133,7 +4786,7 @@ get_focussed_group (MetaDisplay *display) | ||||
|  | ||||
| #define IN_TAB_CHAIN(w,t) (((t) == META_TAB_LIST_NORMAL && META_WINDOW_IN_NORMAL_TAB_CHAIN (w)) \ | ||||
|     || ((t) == META_TAB_LIST_DOCKS && META_WINDOW_IN_DOCK_TAB_CHAIN (w)) \ | ||||
|     || ((t) == META_TAB_LIST_GROUP && META_WINDOW_IN_GROUP_TAB_CHAIN (w, get_focussed_group(w->display))) \ | ||||
|     || ((t) == META_TAB_LIST_GROUP && META_WINDOW_IN_GROUP_TAB_CHAIN (w, get_focused_group (w->display))) \ | ||||
|     || ((t) == META_TAB_LIST_NORMAL_ALL && META_WINDOW_IN_NORMAL_TAB_CHAIN_TYPE (w))) | ||||
|  | ||||
| static MetaWindow* | ||||
| @@ -5946,8 +5599,6 @@ meta_display_set_input_focus_window (MetaDisplay *display, | ||||
| { | ||||
|   request_xserver_input_focus_change (display, | ||||
|                                       window->screen, | ||||
|                                       window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND ? | ||||
|                                       META_FOCUS_WAYLAND_CLIENT : META_FOCUS_X_CLIENT, | ||||
|                                       window, | ||||
|                                       focus_frame ? window->frame->xwindow : window->xwindow, | ||||
|                                       timestamp); | ||||
| @@ -5972,13 +5623,11 @@ meta_display_request_take_focus (MetaDisplay *display, | ||||
| void | ||||
| meta_display_set_input_focus_xwindow (MetaDisplay *display, | ||||
|                                       MetaScreen  *screen, | ||||
|                                       MetaFocusType  type, | ||||
|                                       Window       window, | ||||
|                                       guint32      timestamp) | ||||
| { | ||||
|   request_xserver_input_focus_change (display, | ||||
|                                       screen, | ||||
|                                       type, | ||||
|                                       NULL, | ||||
|                                       window, | ||||
|                                       timestamp); | ||||
| @@ -5991,7 +5640,6 @@ meta_display_focus_the_no_focus_window (MetaDisplay *display, | ||||
| { | ||||
|   request_xserver_input_focus_change (display, | ||||
|                                       screen, | ||||
|                                       META_FOCUS_NO_FOCUS_WINDOW, | ||||
|                                       NULL, | ||||
|                                       screen->no_focus_window, | ||||
|                                       timestamp); | ||||
|   | ||||
| @@ -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} | ||||
| }; | ||||
|  | ||||
| @@ -343,6 +351,7 @@ meta_select_display (char *display_arg) | ||||
|   else | ||||
|     display_name = g_getenv ("MUTTER_DISPLAY"); | ||||
|  | ||||
|   if (display_name) | ||||
|     g_setenv ("DISPLAY", display_name, TRUE); | ||||
| } | ||||
|  | ||||
| @@ -400,8 +409,7 @@ meta_init (void) | ||||
|   if (g_getenv ("MUTTER_DEBUG")) | ||||
|     meta_set_debugging (TRUE); | ||||
|  | ||||
|   /* We consider running from mutter-launch equivalent to running from bare metal. */ | ||||
|   if (getenv ("WESTON_LAUNCHER_SOCK")) | ||||
|   if (opt_display_server) | ||||
|     clutter_set_windowing_backend (CLUTTER_WINDOWING_EGL); | ||||
|  | ||||
|   meta_set_is_wayland_compositor (opt_wayland); | ||||
| @@ -496,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,6 +571,9 @@ 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 defined(CLUTTER_WINDOWING_EGL) | ||||
|   if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL)) | ||||
| @@ -1074,9 +1079,10 @@ 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); | ||||
|   if (mods) | ||||
|     gdk_device_get_state (gdevice, | ||||
|                           gdk_screen_get_root_window (gscreen), | ||||
|                           NULL, (GdkModifierType*)mods); | ||||
| @@ -1095,8 +1101,11 @@ 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); | ||||
|   if (x) | ||||
|     *x = point.x; | ||||
|   if (y) | ||||
|     *y = point.y; | ||||
|   if (mods) | ||||
|     *mods = clutter_input_device_get_modifier_state (cdevice); | ||||
| } | ||||
|  | ||||
| @@ -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); | ||||
| } | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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" | ||||
|  | ||||
|   | ||||
| @@ -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)) | ||||
|     { | ||||
| @@ -700,17 +700,10 @@ meta_window_place (MetaWindow        *window, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   if ((window->type == META_WINDOW_DIALOG || | ||||
|        window->type == META_WINDOW_MODAL_DIALOG) && | ||||
|       window->xtransient_for != None) | ||||
|   if (window->type == META_WINDOW_DIALOG || | ||||
|       window->type == META_WINDOW_MODAL_DIALOG) | ||||
|     { | ||||
|       /* Center horizontally, at top of parent vertically */ | ||||
|  | ||||
|       MetaWindow *parent; | ||||
|            | ||||
|       parent = | ||||
|         meta_display_lookup_x_window (window->display, | ||||
|                                       window->xtransient_for); | ||||
|       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; | ||||
|  | ||||
| @@ -151,25 +149,9 @@ void          meta_screen_foreach_window      (MetaScreen                 *scree | ||||
|  | ||||
| void          meta_screen_update_cursor       (MetaScreen                 *screen); | ||||
|  | ||||
| void          meta_screen_tab_popup_create       (MetaScreen              *screen, | ||||
|                                                   MetaTabList              list_type, | ||||
|                                                   MetaTabShowType          show_type, | ||||
|                                                   MetaWindow              *initial_window); | ||||
| void          meta_screen_tab_popup_forward      (MetaScreen              *screen); | ||||
| void          meta_screen_tab_popup_backward     (MetaScreen              *screen); | ||||
| MetaWindow*   meta_screen_tab_popup_get_selected (MetaScreen              *screen); | ||||
| void          meta_screen_tab_popup_destroy      (MetaScreen              *screen); | ||||
|  | ||||
| void          meta_screen_workspace_popup_create       (MetaScreen    *screen, | ||||
|                                                         MetaWorkspace *initial_selection); | ||||
| void          meta_screen_workspace_popup_select       (MetaScreen    *screen, | ||||
|                                                         MetaWorkspace *workspace); | ||||
| MetaWorkspace*meta_screen_workspace_popup_get_selected (MetaScreen    *screen); | ||||
| void          meta_screen_workspace_popup_destroy      (MetaScreen    *screen); | ||||
|  | ||||
| void          meta_screen_tile_preview_update          (MetaScreen    *screen, | ||||
| void          meta_screen_update_tile_preview          (MetaScreen    *screen, | ||||
|                                                         gboolean       delay); | ||||
| void          meta_screen_tile_preview_hide            (MetaScreen    *screen); | ||||
| void          meta_screen_hide_tile_preview            (MetaScreen    *screen); | ||||
|  | ||||
| MetaWindow*   meta_screen_get_mouse_window     (MetaScreen                 *screen, | ||||
|                                                 MetaWindow                 *not_this_one); | ||||
|   | ||||
| @@ -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, | ||||
| @@ -760,10 +762,6 @@ meta_screen_new (MetaDisplay *display, | ||||
|   screen->ui = meta_ui_new (screen->display->xdisplay, | ||||
|                             screen->xscreen); | ||||
|  | ||||
|   screen->tab_popup = NULL; | ||||
|   screen->ws_popup = NULL; | ||||
|   screen->tile_preview = NULL; | ||||
|  | ||||
|   screen->tile_preview_timeout_id = 0; | ||||
|  | ||||
|   screen->stack = meta_stack_new (screen); | ||||
| @@ -811,11 +809,8 @@ meta_screen_free (MetaScreen *screen, | ||||
|    | ||||
|   meta_display_grab (display); | ||||
|  | ||||
|   if (screen->display->compositor) | ||||
|     { | ||||
|   meta_compositor_unmanage_screen (screen->display->compositor, | ||||
|                                    screen); | ||||
|     } | ||||
|    | ||||
|   meta_display_unmanage_windows_for_screen (display, screen, timestamp); | ||||
|    | ||||
| @@ -868,9 +863,6 @@ meta_screen_free (MetaScreen *screen, | ||||
|   if (screen->tile_preview_timeout_id) | ||||
|     g_source_remove (screen->tile_preview_timeout_id); | ||||
|  | ||||
|   if (screen->tile_preview) | ||||
|     meta_tile_preview_free (screen->tile_preview); | ||||
|    | ||||
|   g_free (screen->screen_name); | ||||
|  | ||||
|   g_object_unref (screen); | ||||
| @@ -1432,255 +1424,8 @@ meta_screen_update_cursor (MetaScreen *screen) | ||||
|                                        screen->current_cursor); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_screen_tab_popup_create (MetaScreen      *screen, | ||||
|                               MetaTabList      list_type, | ||||
|                               MetaTabShowType  show_type, | ||||
|                               MetaWindow      *initial_selection) | ||||
| { | ||||
|   MetaTabEntry *entries; | ||||
|   GList *tab_list; | ||||
|   GList *tmp; | ||||
|   int len; | ||||
|   int i; | ||||
|  | ||||
|   if (screen->tab_popup) | ||||
|     return; | ||||
|  | ||||
|   tab_list = meta_display_get_tab_list (screen->display, | ||||
|                                         list_type, | ||||
|                                         screen, | ||||
|                                         screen->active_workspace); | ||||
|  | ||||
|   len = g_list_length (tab_list); | ||||
|  | ||||
|   entries = g_new (MetaTabEntry, len + 1); | ||||
|   entries[len].key = NULL; | ||||
|   entries[len].title = NULL; | ||||
|   entries[len].icon = NULL; | ||||
|  | ||||
|   i = 0; | ||||
|   tmp = tab_list; | ||||
|   while (i < len) | ||||
|     { | ||||
|       MetaWindow *window; | ||||
|       MetaRectangle r; | ||||
|  | ||||
|       window = tmp->data; | ||||
|  | ||||
|       entries[i].key = (MetaTabEntryKey) window; | ||||
|       entries[i].title = window->title; | ||||
|       entries[i].icon = g_object_ref (window->icon); | ||||
|       entries[i].blank = FALSE; | ||||
|       entries[i].hidden = !meta_window_showing_on_its_workspace (window); | ||||
|       entries[i].demands_attention = window->wm_state_demands_attention; | ||||
|  | ||||
|       if (show_type == META_TAB_SHOW_INSTANTLY || | ||||
|           !entries[i].hidden                   || | ||||
|           !meta_window_get_icon_geometry (window, &r)) | ||||
|         meta_window_get_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; | ||||
| @@ -1688,22 +1433,6 @@ meta_screen_tile_preview_update_timeout (gpointer data) | ||||
|  | ||||
|   screen->tile_preview_timeout_id = 0; | ||||
|  | ||||
|   if (!screen->tile_preview) | ||||
|     { | ||||
|       Window xwindow; | ||||
|       gulong create_serial; | ||||
|       MetaStackWindow stack_window; | ||||
|  | ||||
|       screen->tile_preview = meta_tile_preview_new (screen->number); | ||||
|       xwindow = meta_tile_preview_get_xwindow (screen->tile_preview, | ||||
|                                                &create_serial); | ||||
|       stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11; | ||||
|       stack_window.x11.xwindow = xwindow; | ||||
|       meta_stack_tracker_record_add (screen->stack_tracker, | ||||
|                                      &stack_window, | ||||
|                                      create_serial); | ||||
|     } | ||||
|  | ||||
|   if (window) | ||||
|     { | ||||
|       switch (window->tile_mode) | ||||
| @@ -1728,12 +1457,16 @@ meta_screen_tile_preview_update_timeout (gpointer data) | ||||
|   if (needs_preview) | ||||
|     { | ||||
|       MetaRectangle tile_rect; | ||||
|       int monitor; | ||||
|  | ||||
|       monitor = meta_window_get_current_tile_monitor_number (window); | ||||
|       meta_window_get_current_tile_area (window, &tile_rect); | ||||
|       meta_tile_preview_show (screen->tile_preview, &tile_rect); | ||||
|       meta_compositor_show_tile_preview (screen->display->compositor, | ||||
|                                          screen, window, &tile_rect, monitor); | ||||
|     } | ||||
|   else | ||||
|     meta_tile_preview_hide (screen->tile_preview); | ||||
|     meta_compositor_hide_tile_preview (screen->display->compositor, | ||||
|                                        screen); | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
| @@ -1741,7 +1474,7 @@ meta_screen_tile_preview_update_timeout (gpointer data) | ||||
| #define TILE_PREVIEW_TIMEOUT_MS 200 | ||||
|  | ||||
| void | ||||
| meta_screen_tile_preview_update (MetaScreen *screen, | ||||
| meta_screen_update_tile_preview (MetaScreen *screen, | ||||
|                                  gboolean    delay) | ||||
| { | ||||
|   if (delay) | ||||
| @@ -1751,7 +1484,7 @@ meta_screen_tile_preview_update (MetaScreen *screen, | ||||
|  | ||||
|       screen->tile_preview_timeout_id = | ||||
|         g_timeout_add (TILE_PREVIEW_TIMEOUT_MS, | ||||
|                        meta_screen_tile_preview_update_timeout, | ||||
|                        meta_screen_update_tile_preview_timeout, | ||||
|                        screen); | ||||
|     } | ||||
|   else | ||||
| @@ -1759,18 +1492,18 @@ meta_screen_tile_preview_update (MetaScreen *screen, | ||||
|       if (screen->tile_preview_timeout_id > 0) | ||||
|         g_source_remove (screen->tile_preview_timeout_id); | ||||
|  | ||||
|       meta_screen_tile_preview_update_timeout ((gpointer)screen); | ||||
|       meta_screen_update_tile_preview_timeout ((gpointer)screen); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_screen_tile_preview_hide (MetaScreen *screen) | ||||
| meta_screen_hide_tile_preview (MetaScreen *screen) | ||||
| { | ||||
|   if (screen->tile_preview_timeout_id > 0) | ||||
|     g_source_remove (screen->tile_preview_timeout_id); | ||||
|  | ||||
|   if (screen->tile_preview) | ||||
|     meta_tile_preview_hide (screen->tile_preview); | ||||
|   meta_compositor_hide_tile_preview (screen->display->compositor, | ||||
|                                      screen); | ||||
| } | ||||
|  | ||||
| MetaWindow* | ||||
| @@ -1778,38 +1511,19 @@ meta_screen_get_mouse_window (MetaScreen  *screen, | ||||
|                               MetaWindow  *not_this_one) | ||||
| { | ||||
|   MetaWindow *window; | ||||
|   Window root_return, child_return; | ||||
|   double root_x_return, root_y_return; | ||||
|   double win_x_return, win_y_return; | ||||
|   XIButtonState buttons; | ||||
|   XIModifierState mods; | ||||
|   XIGroupState group; | ||||
|   int x, y; | ||||
|  | ||||
|   if (not_this_one) | ||||
|     meta_topic (META_DEBUG_FOCUS, | ||||
|                 "Focusing mouse window excluding %s\n", not_this_one->desc); | ||||
|  | ||||
|   meta_error_trap_push (screen->display); | ||||
|   XIQueryPointer (screen->display->xdisplay, | ||||
|                   META_VIRTUAL_CORE_POINTER_ID, | ||||
|                   screen->xroot, | ||||
|                   &root_return, | ||||
|                   &child_return, | ||||
|                   &root_x_return, | ||||
|                   &root_y_return, | ||||
|                   &win_x_return, | ||||
|                   &win_y_return, | ||||
|                   &buttons, | ||||
|                   &mods, | ||||
|                   &group); | ||||
|   meta_error_trap_pop (screen->display); | ||||
|   free (buttons.mask); | ||||
|   meta_cursor_tracker_get_pointer (screen->cursor_tracker, | ||||
|                                    &x, &y, NULL); | ||||
|  | ||||
|   window = meta_stack_get_default_focus_window_at_point (screen->stack, | ||||
|                                                          screen->active_workspace, | ||||
|                                                          not_this_one, | ||||
|                                                          root_x_return, | ||||
|                                                          root_y_return); | ||||
|                                                          x, y); | ||||
|  | ||||
|   return window; | ||||
| } | ||||
| @@ -2091,28 +1805,11 @@ meta_screen_get_current_monitor (MetaScreen *screen) | ||||
|    | ||||
|   if (screen->display->monitor_cache_invalidated) | ||||
|     { | ||||
|       Window root_return, child_return; | ||||
|       double win_x_return, win_y_return; | ||||
|       double root_x_return, root_y_return; | ||||
|       XIButtonState buttons; | ||||
|       XIModifierState mods; | ||||
|       XIGroupState group; | ||||
|       int x, y; | ||||
|  | ||||
|       XIQueryPointer (screen->display->xdisplay, | ||||
|                       META_VIRTUAL_CORE_POINTER_ID, | ||||
|                       screen->xroot, | ||||
|                       &root_return, | ||||
|                       &child_return, | ||||
|                       &root_x_return, | ||||
|                       &root_y_return, | ||||
|                       &win_x_return, | ||||
|                       &win_y_return, | ||||
|                       &buttons, | ||||
|                       &mods, | ||||
|                       &group); | ||||
|       free (buttons.mask); | ||||
|  | ||||
|       meta_screen_get_current_monitor_for_pos (screen, root_x_return, root_y_return); | ||||
|       meta_cursor_tracker_get_pointer (screen->cursor_tracker, | ||||
|                                        &x, &y, NULL); | ||||
|       meta_screen_get_current_monitor_for_pos (screen, x, y); | ||||
|     } | ||||
|  | ||||
|   return screen->last_monitor_index; | ||||
| @@ -2823,7 +2520,6 @@ 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); | ||||
|   | ||||
| @@ -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,7 +1245,6 @@ 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); | ||||
|   | ||||
| @@ -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,7 +1707,7 @@ 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; | ||||
| @@ -1718,41 +1720,44 @@ 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) | ||||
|         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 (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 (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))) | ||||
|               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))) | ||||
|               not_this_one_group == meta_window_get_group (window)) | ||||
|             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))) | ||||
|       if (topmost_overall == NULL && window->type != META_WINDOW_DOCK) | ||||
|         topmost_overall = window; | ||||
|  | ||||
|       /* We could try to bail out early here for efficiency in | ||||
| @@ -1760,9 +1765,6 @@ get_default_focus_window (MetaStack     *stack, | ||||
|        */ | ||||
|     } | ||||
|  | ||||
|       link = link->next; | ||||
|     } | ||||
|  | ||||
|   if (transient_parent) | ||||
|     return transient_parent; | ||||
|   else if (topmost_in_group) | ||||
|   | ||||
| @@ -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; | ||||
|  | ||||
| @@ -89,7 +92,6 @@ struct _MetaWindow | ||||
|   char *desc; /* used in debug spew */ | ||||
|   char *title; | ||||
|  | ||||
|   char *icon_name; | ||||
|   GdkPixbuf *icon; | ||||
|   GdkPixbuf *mini_icon; | ||||
|   MetaIconCache icon_cache; | ||||
| @@ -97,7 +99,6 @@ struct _MetaWindow | ||||
|   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 | ||||
| @@ -159,8 +160,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; | ||||
| @@ -238,7 +239,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; | ||||
|    | ||||
| @@ -263,13 +264,6 @@ struct _MetaWindow | ||||
|   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; | ||||
|   guint skip_pager : 1; | ||||
| @@ -323,15 +317,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; | ||||
|  | ||||
| @@ -431,8 +416,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; | ||||
| @@ -471,10 +454,9 @@ 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 (*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 | ||||
| @@ -567,9 +549,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 */ | ||||
| @@ -634,12 +613,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); | ||||
| @@ -652,6 +625,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); | ||||
|  | ||||
| @@ -683,9 +657,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); | ||||
|  | ||||
| @@ -742,9 +715,19 @@ void meta_window_set_surface_mapped (MetaWindow *window, | ||||
|  | ||||
| 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); | ||||
|  | ||||
| #endif | ||||
|   | ||||
										
											
												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, | ||||
| @@ -121,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 */ | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -75,9 +75,6 @@ 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); | ||||
| @@ -203,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); | ||||
| @@ -211,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); | ||||
|  | ||||
| @@ -252,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, | ||||
|   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,8 +58,8 @@ 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 | ||||
|     wl_data_source_send_send (offer->source->resource, mime_type, fd); | ||||
|  | ||||
|   close (fd); | ||||
| } | ||||
|  | ||||
| @@ -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) | ||||
| @@ -146,23 +138,11 @@ meta_wayland_keyboard_take_keymap (MetaWaylandKeyboard *keyboard, | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   if (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) | ||||
| @@ -225,28 +205,26 @@ err_keymap_str: | ||||
|   return; | ||||
| } | ||||
|  | ||||
| static void | ||||
| release_focus (MetaWaylandKeyboard *keyboard) | ||||
| { | ||||
|   wl_list_remove (&keyboard->focus_surface_listener.link); | ||||
|   wl_list_remove (&keyboard->focus_resource_listener.link); | ||||
|  | ||||
|   keyboard->focus_resource = NULL; | ||||
|   keyboard->focus_surface = NULL; | ||||
| } | ||||
|  | ||||
| static void | ||||
| keyboard_handle_focus_surface_destroy (struct wl_listener *listener, void *data) | ||||
| { | ||||
|   MetaWaylandKeyboard *keyboard = wl_container_of (listener, keyboard, focus_surface_listener); | ||||
|   release_focus (keyboard); | ||||
|  | ||||
|   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); | ||||
|   release_focus (keyboard); | ||||
|  | ||||
|   keyboard->focus_resource = NULL; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| @@ -291,28 +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, | ||||
|   if (keyboard->focus_resource) | ||||
|     { | ||||
|       wl_keyboard_send_modifiers (keyboard->focus_resource, serial, mods_depressed, | ||||
|                                   mods_latched, mods_locked, group); | ||||
|  | ||||
|   if (pointer && pointer->focus_surface && pointer->focus_surface != keyboard->focus_surface) | ||||
|     { | ||||
|       pr = find_resource_for_surface (&keyboard->resource_list, pointer->focus_surface); | ||||
|       if (pr) | ||||
|         { | ||||
|           wl_keyboard_send_modifiers (pr, serial, | ||||
| 				      mods_depressed, | ||||
|                                       mods_latched, | ||||
|                                       mods_locked, | ||||
|                                       group); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -322,31 +283,6 @@ 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) | ||||
| @@ -382,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); | ||||
| @@ -391,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) | ||||
| @@ -442,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)); | ||||
| @@ -466,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 | ||||
| @@ -485,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) | ||||
| @@ -527,73 +432,54 @@ void | ||||
| meta_wayland_keyboard_set_focus (MetaWaylandKeyboard *keyboard, | ||||
|                                  MetaWaylandSurface *surface) | ||||
| { | ||||
|   struct wl_resource *resource; | ||||
|   uint32_t serial; | ||||
|  | ||||
|   if (keyboard->focus_surface == surface && keyboard->focus_resource != NULL) | ||||
|     return; | ||||
|  | ||||
|   resource = keyboard->focus_resource; | ||||
|   if (resource) | ||||
|   if (keyboard->focus_surface != NULL) | ||||
|     { | ||||
|       if (keyboard->focus_resource) | ||||
|         { | ||||
|           if (keyboard->focus_surface->resource) | ||||
|             { | ||||
|           struct wl_client *client = wl_resource_get_client (resource); | ||||
|               struct wl_client *client = wl_resource_get_client (keyboard->focus_resource); | ||||
|               struct wl_display *display = wl_client_get_display (client); | ||||
|           serial = wl_display_next_serial (display); | ||||
|           wl_keyboard_send_leave (resource, serial, keyboard->focus_surface->resource); | ||||
|  | ||||
|           meta_wayland_surface_focused_unset (keyboard->focus_surface); | ||||
|               uint32_t serial = wl_display_next_serial (display); | ||||
|               wl_keyboard_send_leave (keyboard->focus_resource, serial, keyboard->focus_surface->resource); | ||||
|             } | ||||
|  | ||||
|           wl_list_remove (&keyboard->focus_resource_listener.link); | ||||
|       wl_list_remove (&keyboard->focus_surface_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); | ||||
|  | ||||
|       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 (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); | ||||
| 	} | ||||
|  | ||||
|       meta_wayland_surface_focused_set (surface); | ||||
|  | ||||
|       keyboard->focus_resource = resource; | ||||
|       keyboard->focus_surface = surface; | ||||
|  | ||||
|       wl_resource_add_destroy_listener (keyboard->focus_resource, &keyboard->focus_resource_listener); | ||||
|       wl_resource_add_destroy_listener (keyboard->focus_surface->resource, &keyboard->focus_surface_listener); | ||||
|  | ||||
|       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); | ||||
|  | ||||
|           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_resource_add_destroy_listener (keyboard->focus_resource, &keyboard->focus_resource_listener); | ||||
|           keyboard->focus_serial = serial; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -622,85 +508,6 @@ meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard) | ||||
|   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_surface) | ||||
|     { | ||||
|       /* 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_surface) | ||||
|     { | ||||
|       /* 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,27 +69,12 @@ 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; | ||||
| @@ -107,8 +93,6 @@ struct _MetaWaylandKeyboard | ||||
|  | ||||
|   struct wl_array keys; | ||||
|  | ||||
|   MetaWaylandXkbState modifier_state; | ||||
|  | ||||
|   struct wl_display *display; | ||||
|  | ||||
|   struct xkb_context *xkb_context; | ||||
| @@ -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,48 +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) | ||||
| { | ||||
|   MetaWaylandSeat *seat = wl_container_of (pointer, seat, pointer); | ||||
|  | ||||
|   return seat; | ||||
| } | ||||
|  | ||||
| static void | ||||
| release_focus (MetaWaylandPointer *pointer) | ||||
| { | ||||
|   wl_list_remove (&pointer->focus_surface_listener.link); | ||||
|   wl_list_remove (&pointer->focus_resource_listener.link); | ||||
|  | ||||
|   pointer->focus_resource = NULL; | ||||
|   pointer->focus_surface = NULL; | ||||
| } | ||||
|  | ||||
| static void | ||||
| pointer_handle_focus_surface_destroy (struct wl_listener *listener, void *data) | ||||
| { | ||||
|   MetaWaylandPointer *pointer = wl_container_of (listener, pointer, focus_surface_listener); | ||||
|   release_focus (pointer); | ||||
|  | ||||
|   pointer->focus_surface = NULL; | ||||
|  | ||||
|   if (pointer->focus_resource) | ||||
|     { | ||||
|       wl_list_remove (&pointer->focus_resource_listener.link); | ||||
|       pointer->focus_resource = NULL; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| pointer_handle_focus_resource_destroy (struct wl_listener *listener, void *data) | ||||
| { | ||||
|   MetaWaylandPointer *pointer = wl_container_of (listener, pointer, focus_resource_listener); | ||||
|   release_focus (pointer); | ||||
|  | ||||
|   pointer->focus_resource = NULL; | ||||
| } | ||||
|  | ||||
| static void | ||||
| default_grab_focus (MetaWaylandPointerGrab *grab, | ||||
|                     MetaWaylandSurface     *surface, | ||||
| 		    const ClutterEvent     *event) | ||||
|                     MetaWaylandSurface     *surface) | ||||
| { | ||||
|   MetaWaylandPointer *pointer = grab->pointer; | ||||
|  | ||||
| @@ -310,7 +298,7 @@ meta_wayland_pointer_init (MetaWaylandPointer *pointer) | ||||
| void | ||||
| meta_wayland_pointer_release (MetaWaylandPointer *pointer) | ||||
| { | ||||
|   release_focus (pointer); | ||||
|   /* Do nothing. */ | ||||
| } | ||||
|  | ||||
| static struct wl_resource * | ||||
| @@ -331,71 +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 == surface && pointer->focus_resource != NULL) | ||||
|     return; | ||||
|  | ||||
|   resource = pointer->focus_resource; | ||||
|   if (resource) | ||||
|   if (pointer->focus_surface) | ||||
|     { | ||||
|       if (pointer->focus_resource) | ||||
|         { | ||||
|           if (pointer->focus_surface->resource) | ||||
|             { | ||||
|           struct wl_client *client = wl_resource_get_client (resource); | ||||
|               struct wl_client *client = wl_resource_get_client (pointer->focus_resource); | ||||
|               struct wl_display *display = wl_client_get_display (client); | ||||
|           serial = wl_display_next_serial (display); | ||||
|           wl_pointer_send_leave (resource, serial, pointer->focus_surface->resource); | ||||
|               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_surface_listener.link); | ||||
|           wl_list_remove (&pointer->focus_resource_listener.link); | ||||
|  | ||||
|       pointer->focus_surface = NULL; | ||||
|           pointer->focus_resource = NULL; | ||||
|         } | ||||
|  | ||||
|   resource = find_resource_for_surface (&pointer->resource_list, surface); | ||||
|   if (resource) | ||||
|       wl_list_remove (&pointer->focus_surface_listener.link); | ||||
|       pointer->focus_surface = NULL; | ||||
|     } | ||||
|  | ||||
|   if (surface != NULL) | ||||
|     { | ||||
|       struct wl_client *client = wl_resource_get_client (resource); | ||||
|       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); | ||||
|       wl_fixed_t sx, sy; | ||||
|           uint32_t serial = wl_display_next_serial (display); | ||||
|  | ||||
|       serial = wl_display_next_serial (display); | ||||
|  | ||||
|       if (kbd) | ||||
|         { | ||||
|           kr = find_resource_for_surface (&kbd->resource_list, surface); | ||||
|           if (kr) | ||||
|             { | ||||
|               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); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|       meta_wayland_pointer_get_relative_coordinates (pointer, surface, &sx, &sy); | ||||
|       meta_window_handle_enter (surface->window, | ||||
|           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_pointer_send_enter (resource, serial, surface->resource, sx, sy); | ||||
|  | ||||
|       pointer->focus_resource = resource; | ||||
|       pointer->focus_surface = surface; | ||||
|           { | ||||
|             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); | ||||
|       wl_resource_add_destroy_listener (pointer->focus_surface->resource, &pointer->focus_surface_listener); | ||||
|  | ||||
|           pointer->focus_serial = serial; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -409,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 | ||||
| @@ -419,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 { | ||||
| @@ -494,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); | ||||
| } | ||||
| @@ -551,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); | ||||
| } | ||||
| @@ -603,6 +521,8 @@ meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer, | ||||
|  | ||||
|   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; | ||||
| @@ -610,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; | ||||
| @@ -618,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; | ||||
|   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; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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, | ||||
| @@ -85,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); | ||||
|   | ||||
| @@ -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" | ||||
| @@ -91,30 +90,8 @@ struct _MetaWaylandCompositor | ||||
|   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); | ||||
|  | ||||
| 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) | ||||
|  | ||||
| @@ -275,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 | ||||
| @@ -335,7 +347,7 @@ count_buttons (const ClutterEvent *event) | ||||
|   return count; | ||||
| } | ||||
|  | ||||
| void | ||||
| static void | ||||
| meta_wayland_seat_update_pointer (MetaWaylandSeat    *seat, | ||||
|                                   const ClutterEvent *event) | ||||
| { | ||||
| @@ -358,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) | ||||
| @@ -420,21 +453,15 @@ 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)); | ||||
|  | ||||
|       surface = window->surface; | ||||
|     } | ||||
|   if (META_IS_SURFACE_ACTOR_WAYLAND (actor)) | ||||
|     surface = meta_surface_actor_wayland_get_surface (META_SURFACE_ACTOR_WAYLAND (actor)); | ||||
|  | ||||
|   pointer->current = surface; | ||||
|   if (surface != pointer->focus_surface) | ||||
|     { | ||||
|       const MetaWaylandPointerGrabInterface *interface = | ||||
|         pointer->grab->interface; | ||||
|       interface->focus (pointer->grab, | ||||
|                         surface, for_event); | ||||
|       interface->focus (pointer->grab, surface); | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
| @@ -77,7 +71,7 @@ MetaWaylandSeat * | ||||
| meta_wayland_seat_new (struct wl_display *display); | ||||
|  | ||||
| void | ||||
| meta_wayland_seat_update_pointer (MetaWaylandSeat *seat, | ||||
| meta_wayland_seat_update (MetaWaylandSeat    *seat, | ||||
|                           const ClutterEvent *event); | ||||
|  | ||||
| gboolean | ||||
|   | ||||
| @@ -44,11 +44,11 @@ | ||||
| #include "meta-wayland-private.h" | ||||
| #include "meta-xwayland-private.h" | ||||
| #include "meta-wayland-stage.h" | ||||
| #include "meta-surface-actor.h" | ||||
| #include "meta-wayland-seat.h" | ||||
| #include "meta-wayland-keyboard.h" | ||||
| #include "meta-wayland-pointer.h" | ||||
| #include "meta-wayland-data-device.h" | ||||
|  | ||||
| #include "meta-cursor-tracker-private.h" | ||||
| #include "display-private.h" | ||||
| #include "window-private.h" | ||||
| @@ -58,6 +58,9 @@ | ||||
| #include "meta-idle-monitor-private.h" | ||||
| #include "monitor-private.h" | ||||
|  | ||||
| #include "meta-surface-actor.h" | ||||
| #include "meta-surface-actor-wayland.h" | ||||
|  | ||||
| typedef enum | ||||
| { | ||||
|   META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE, | ||||
| @@ -79,7 +82,6 @@ surface_handle_buffer_destroy (struct wl_listener *listener, void *data) | ||||
|   wl_resource_post_error (surface->resource, WL_DISPLAY_ERROR_INVALID_OBJECT, | ||||
|                           "Destroyed buffer while it was attached to the surface"); | ||||
|   surface->buffer = NULL; | ||||
|   wl_list_remove (&surface->buffer_destroy_listener.link); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -114,7 +116,7 @@ surface_process_damage (MetaWaylandSurface *surface, | ||||
|     { | ||||
|       cairo_rectangle_int_t rect; | ||||
|       cairo_region_get_rectangle (region, i, &rect); | ||||
|       meta_surface_actor_damage_area (surface->surface_actor, | ||||
|       meta_surface_actor_process_damage (surface->surface_actor, | ||||
|                                          rect.x, rect.y, rect.width, rect.height); | ||||
|     } | ||||
| } | ||||
| @@ -259,9 +261,6 @@ ensure_buffer_texture (MetaWaylandBuffer *buffer) | ||||
|   CoglError *catch_error = NULL; | ||||
|   CoglTexture *texture; | ||||
|  | ||||
|   if (!buffer) | ||||
|     return; | ||||
|  | ||||
|   texture = COGL_TEXTURE (cogl_wayland_texture_2d_new_from_buffer (ctx, | ||||
|                                                                    buffer->resource, | ||||
|                                                                    &catch_error)); | ||||
| @@ -273,8 +272,6 @@ ensure_buffer_texture (MetaWaylandBuffer *buffer) | ||||
|     } | ||||
|  | ||||
|   buffer->texture = texture; | ||||
|   buffer->width = cogl_texture_get_width (texture); | ||||
|   buffer->height = cogl_texture_get_height (texture); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -294,10 +291,10 @@ actor_surface_commit (MetaWaylandSurface             *surface, | ||||
|   MetaSurfaceActor *surface_actor = surface->surface_actor; | ||||
|   MetaWaylandBuffer *buffer = pending->buffer; | ||||
|  | ||||
|   if (buffer_changed) | ||||
|   if (buffer_changed && buffer) | ||||
|     { | ||||
|       ensure_buffer_texture (buffer); | ||||
|       meta_surface_actor_attach_wayland_buffer (surface_actor, buffer); | ||||
|       meta_surface_actor_wayland_set_buffer (META_SURFACE_ACTOR_WAYLAND (surface->surface_actor), buffer); | ||||
|     } | ||||
|  | ||||
|   surface_process_damage (surface, pending->damage); | ||||
| @@ -324,11 +321,11 @@ toplevel_surface_commit (MetaWaylandSurface             *surface, | ||||
|       /* We resize X based surfaces according to X events */ | ||||
|       if (buffer != NULL && window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND) | ||||
|         { | ||||
|           int new_width; | ||||
|           int new_height; | ||||
|           int new_width, new_height; | ||||
|  | ||||
|           new_width = cogl_texture_get_width (buffer->texture); | ||||
|           new_height = cogl_texture_get_height (buffer->texture); | ||||
|  | ||||
|           new_width = surface->buffer->width; | ||||
|           new_height = surface->buffer->height; | ||||
|           if (new_width != window->rect.width || | ||||
|               new_height != window->rect.height || | ||||
|               pending->dx != 0 || | ||||
| @@ -339,22 +336,6 @@ toplevel_surface_commit (MetaWaylandSurface             *surface, | ||||
|  | ||||
|   if (pending->frame_extents_changed) | ||||
|     meta_window_set_custom_frame_extents (surface->window, &pending->frame_extents); | ||||
|  | ||||
|   if (pending->maximized.changed) | ||||
|     { | ||||
|       if (pending->maximized.value) | ||||
|         meta_window_maximize (surface->window, META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL); | ||||
|       else | ||||
|         meta_window_unmaximize (surface->window, META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL); | ||||
|     } | ||||
|  | ||||
|   if (pending->fullscreen.changed) | ||||
|     { | ||||
|       if (pending->fullscreen.value) | ||||
|         meta_window_make_fullscreen (surface->window); | ||||
|       else | ||||
|         meta_window_unmake_fullscreen (surface->window); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -380,8 +361,6 @@ double_buffered_state_init (MetaWaylandDoubleBufferedState *state) | ||||
|   wl_list_init (&state->frame_callback_list); | ||||
|  | ||||
|   state->frame_extents_changed = FALSE; | ||||
|   state->maximized.changed = FALSE; | ||||
|   state->fullscreen.changed = FALSE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -573,34 +552,30 @@ const struct wl_surface_interface meta_wayland_surface_interface = { | ||||
|   meta_wayland_surface_set_buffer_scale | ||||
| }; | ||||
|  | ||||
| static void | ||||
| unparent_actor (MetaWaylandSurface *surface) | ||||
| void | ||||
| meta_wayland_surface_make_toplevel (MetaWaylandSurface *surface) | ||||
| { | ||||
|   ClutterActor *parent_actor; | ||||
|  | ||||
|   parent_actor = clutter_actor_get_parent (CLUTTER_ACTOR (surface->surface_actor)); | ||||
|   clutter_actor_remove_child (parent_actor, CLUTTER_ACTOR (surface->surface_actor)); | ||||
|   clutter_actor_set_reactive (CLUTTER_ACTOR (surface->surface_actor), TRUE); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_wayland_surface_window_unmanaged (MetaWaylandSurface *surface) | ||||
| { | ||||
|   /* The window is being unmanaged. Unparent our surface actor | ||||
|    * before the window actor is destroyed, as we need to hold | ||||
|    * onto it... */ | ||||
|   unparent_actor (surface); | ||||
|  | ||||
|   clutter_actor_set_reactive (CLUTTER_ACTOR (surface->surface_actor), FALSE); | ||||
|   surface->window = NULL; | ||||
| } | ||||
|  | ||||
| static void | ||||
| destroy_window (MetaWaylandSurface *surface) | ||||
| { | ||||
|   if (surface->window) | ||||
|     { | ||||
|       MetaDisplay *display = meta_get_display (); | ||||
|       guint32 timestamp = meta_display_get_current_time_roundtrip (display); | ||||
|  | ||||
|   g_assert (surface->window != NULL); | ||||
|       meta_window_unmanage (surface->window, timestamp); | ||||
|     } | ||||
|  | ||||
|   g_assert (surface->window == NULL); | ||||
| } | ||||
|  | ||||
| @@ -610,18 +585,17 @@ wl_surface_destructor (struct wl_resource *resource) | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (resource); | ||||
|   MetaWaylandCompositor *compositor = surface->compositor; | ||||
|  | ||||
|   /* At the time when the wl_surface is destroyed, we should | ||||
|    * no longer have a window, unless we're an XWayland window | ||||
|    * in which case we received the wl_surface.destroy before | ||||
|    * the UnmapNotify/DestroyNotify. */ | ||||
|   g_assert (surface->window == NULL || surface->window->client_type == META_WINDOW_CLIENT_TYPE_X11); | ||||
|   /* If we still have a window at the time of destruction, that means that | ||||
|    * the client is disconnecting, as the resources are destroyed in a random | ||||
|    * order. Simply destroy the window in this case. */ | ||||
|   if (surface->window) | ||||
|     destroy_window (surface); | ||||
|  | ||||
|   compositor->surfaces = g_list_remove (compositor->surfaces, surface); | ||||
|  | ||||
|   surface_set_buffer (surface, NULL); | ||||
|   double_buffered_state_destroy (&surface->pending); | ||||
|  | ||||
|   clutter_actor_destroy (CLUTTER_ACTOR (surface->surface_actor)); | ||||
|   g_object_unref (surface->surface_actor); | ||||
|  | ||||
|   if (surface->resource) | ||||
| @@ -645,28 +619,18 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor, | ||||
|   wl_resource_set_implementation (surface->resource, &meta_wayland_surface_interface, surface, wl_surface_destructor); | ||||
|  | ||||
|   surface->buffer_destroy_listener.notify = surface_handle_buffer_destroy; | ||||
|   surface->surface_actor = g_object_ref_sink (meta_surface_actor_new ()); | ||||
|   surface->surface_actor = g_object_ref_sink (meta_surface_actor_wayland_new (surface)); | ||||
|  | ||||
|   double_buffered_state_init (&surface->pending); | ||||
|  | ||||
|   return surface; | ||||
| } | ||||
|  | ||||
| static void | ||||
| destroy_surface_extension (MetaWaylandSurfaceExtension *extension) | ||||
| { | ||||
|   wl_list_remove (&extension->surface_destroy_listener.link); | ||||
|   extension->resource = NULL; | ||||
| } | ||||
|  | ||||
| static void | ||||
| extension_handle_surface_destroy (struct wl_listener *listener, | ||||
| 				  void *data) | ||||
| { | ||||
|   MetaWaylandSurfaceExtension *extension = wl_container_of (listener, extension, surface_destroy_listener); | ||||
|   wl_resource_destroy (extension->resource); | ||||
| } | ||||
|  | ||||
| static int | ||||
| get_resource_version (struct wl_resource *master_resource, | ||||
|                       int                 max_version) | ||||
| @@ -676,23 +640,22 @@ get_resource_version (struct wl_resource *master_resource, | ||||
|  | ||||
| static gboolean | ||||
| create_surface_extension (MetaWaylandSurfaceExtension *extension, | ||||
|                           struct wl_client            *client, | ||||
|                           struct wl_resource          *master_resource, | ||||
|                           struct wl_resource          *surface_resource, | ||||
|                           guint32                      id, | ||||
|                           int                          max_version, | ||||
|                           const struct wl_interface   *interface, | ||||
|                           const void                  *implementation, | ||||
|                           wl_resource_destroy_func_t   destructor) | ||||
|                           wl_resource_destroy_func_t   destructor, | ||||
|                           MetaWaylandSurface          *surface, | ||||
|                           struct wl_resource          *master_resource, | ||||
|                           guint32                      id) | ||||
| { | ||||
|   struct wl_client *client; | ||||
|  | ||||
|   if (extension->resource != NULL) | ||||
|     return FALSE; | ||||
|  | ||||
|   client = wl_resource_get_client (surface->resource); | ||||
|   extension->resource = wl_resource_create (client, interface, get_resource_version (master_resource, max_version), id); | ||||
|   wl_resource_set_implementation (extension->resource, implementation, extension, destructor); | ||||
|  | ||||
|   extension->surface_destroy_listener.notify = extension_handle_surface_destroy; | ||||
|   wl_resource_add_destroy_listener (surface_resource, &extension->surface_destroy_listener); | ||||
|   wl_resource_set_implementation (extension->resource, implementation, surface, destructor); | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
| @@ -719,11 +682,10 @@ xdg_shell_pong (struct wl_client *client, | ||||
| static void | ||||
| xdg_surface_destructor (struct wl_resource *resource) | ||||
| { | ||||
|   MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource); | ||||
|   MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface); | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (resource); | ||||
|  | ||||
|   destroy_window (surface); | ||||
|   destroy_surface_extension (xdg_surface); | ||||
|   destroy_surface_extension (&surface->xdg_surface); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -738,8 +700,7 @@ xdg_surface_set_transient_for (struct wl_client *client, | ||||
|                                struct wl_resource *resource, | ||||
|                                struct wl_resource *parent_resource) | ||||
| { | ||||
|   MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource); | ||||
|   MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface); | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (resource); | ||||
|   MetaWindow *transient_for = NULL; | ||||
|  | ||||
|   if (parent_resource) | ||||
| @@ -759,8 +720,7 @@ xdg_surface_set_margin (struct wl_client *client, | ||||
|                         int32_t top_margin, | ||||
|                         int32_t bottom_margin) | ||||
| { | ||||
|   MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource); | ||||
|   MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface); | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (resource); | ||||
|  | ||||
|   surface->pending.frame_extents_changed = TRUE; | ||||
|   surface->pending.frame_extents.left = left_margin; | ||||
| @@ -774,8 +734,7 @@ xdg_surface_set_title (struct wl_client *client, | ||||
|                        struct wl_resource *resource, | ||||
|                        const char *title) | ||||
| { | ||||
|   MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource); | ||||
|   MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface); | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (resource); | ||||
|  | ||||
|   meta_window_set_title (surface->window, title); | ||||
| } | ||||
| @@ -785,8 +744,7 @@ xdg_surface_set_app_id (struct wl_client *client, | ||||
|                         struct wl_resource *resource, | ||||
|                         const char *app_id) | ||||
| { | ||||
|   MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource); | ||||
|   MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface); | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (resource); | ||||
|  | ||||
|   meta_window_set_wm_class (surface->window, app_id, app_id); | ||||
| } | ||||
| @@ -821,8 +779,7 @@ xdg_surface_move (struct wl_client *client, | ||||
|                   guint32 serial) | ||||
| { | ||||
|   MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); | ||||
|   MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource); | ||||
|   MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface); | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (resource); | ||||
|  | ||||
|   if (seat->pointer.button_count == 0 || | ||||
|       seat->pointer.grab_serial != serial || | ||||
| @@ -833,7 +790,7 @@ xdg_surface_move (struct wl_client *client, | ||||
| } | ||||
|  | ||||
| static MetaGrabOp | ||||
| grab_op_for_edge (int edge) | ||||
| grab_op_for_xdg_surface_resize_edge (int edge) | ||||
| { | ||||
|   switch (edge) | ||||
|     { | ||||
| @@ -867,15 +824,14 @@ xdg_surface_resize (struct wl_client *client, | ||||
|                     guint32 edges) | ||||
| { | ||||
|   MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); | ||||
|   MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource); | ||||
|   MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface); | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (resource); | ||||
|  | ||||
|   if (seat->pointer.button_count == 0 || | ||||
|       seat->pointer.grab_serial != serial || | ||||
|       seat->pointer.focus_surface != surface) | ||||
|     return; | ||||
|  | ||||
|   begin_grab_op_on_surface (surface, seat, grab_op_for_edge (edges)); | ||||
|   begin_grab_op_on_surface (surface, seat, grab_op_for_xdg_surface_resize_edge (edges)); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -887,55 +843,51 @@ xdg_surface_set_output (struct wl_client *client, | ||||
| } | ||||
|  | ||||
| static void | ||||
| xdg_surface_set_fullscreen (struct wl_client *client, | ||||
|                             struct wl_resource *resource) | ||||
| xdg_surface_request_change_state (struct wl_client *client, | ||||
|                                   struct wl_resource *resource, | ||||
|                                   uint32_t state_type, | ||||
|                                   uint32_t value, | ||||
|                                   uint32_t serial) | ||||
| { | ||||
|   MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource); | ||||
|   MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface); | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (resource); | ||||
|  | ||||
|   surface->pending.fullscreen.changed = TRUE; | ||||
|   surface->pending.fullscreen.value = TRUE; | ||||
|   surface->state_changed_serial = serial; | ||||
|  | ||||
|   switch (state_type) | ||||
|     { | ||||
|     case XDG_SURFACE_STATE_MAXIMIZED: | ||||
|       if (value) | ||||
|         meta_window_maximize (surface->window, META_MAXIMIZE_BOTH); | ||||
|       else | ||||
|         meta_window_unmaximize (surface->window, META_MAXIMIZE_BOTH); | ||||
|       break; | ||||
|     case XDG_SURFACE_STATE_FULLSCREEN: | ||||
|       if (value) | ||||
|         meta_window_make_fullscreen (surface->window); | ||||
|       else | ||||
|         meta_window_unmake_fullscreen (surface->window); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| xdg_surface_unset_fullscreen (struct wl_client *client, | ||||
|                               struct wl_resource *resource) | ||||
| xdg_surface_ack_change_state (struct wl_client *client, | ||||
|                               struct wl_resource *resource, | ||||
|                               uint32_t state_type, | ||||
|                               uint32_t value, | ||||
|                               uint32_t serial) | ||||
| { | ||||
|   MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource); | ||||
|   MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface); | ||||
|  | ||||
|   surface->pending.fullscreen.changed = TRUE; | ||||
|   surface->pending.fullscreen.value = FALSE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| xdg_surface_set_maximized (struct wl_client *client, | ||||
|                            struct wl_resource *resource) | ||||
| { | ||||
|   MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource); | ||||
|   MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface); | ||||
|  | ||||
|   surface->pending.maximized.changed = TRUE; | ||||
|   surface->pending.maximized.value = TRUE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| xdg_surface_unset_maximized (struct wl_client *client, | ||||
|                              struct wl_resource *resource) | ||||
| { | ||||
|   MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource); | ||||
|   MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface); | ||||
|  | ||||
|   surface->pending.maximized.changed = TRUE; | ||||
|   surface->pending.maximized.value = FALSE; | ||||
|   /* Do nothing for now. In the future, we'd imagine that | ||||
|    * we'd ignore attaches when we have a state pending that | ||||
|    * we haven't had the client ACK'd, to prevent a race | ||||
|    * condition when we have an in-flight attach when the | ||||
|    * client gets the new state. */ | ||||
| } | ||||
|  | ||||
| static void | ||||
| xdg_surface_set_minimized (struct wl_client *client, | ||||
|                            struct wl_resource *resource) | ||||
| { | ||||
|   MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource); | ||||
|   MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface); | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (resource); | ||||
|  | ||||
|   meta_window_minimize (surface->window); | ||||
| } | ||||
| @@ -949,10 +901,8 @@ static const struct xdg_surface_interface meta_wayland_xdg_surface_interface = { | ||||
|   xdg_surface_move, | ||||
|   xdg_surface_resize, | ||||
|   xdg_surface_set_output, | ||||
|   xdg_surface_set_fullscreen, | ||||
|   xdg_surface_unset_fullscreen, | ||||
|   xdg_surface_set_maximized, | ||||
|   xdg_surface_unset_maximized, | ||||
|   xdg_surface_request_change_state, | ||||
|   xdg_surface_ack_change_state, | ||||
|   xdg_surface_set_minimized, | ||||
| }; | ||||
|  | ||||
| @@ -964,11 +914,12 @@ xdg_shell_get_xdg_surface (struct wl_client *client, | ||||
| { | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); | ||||
|  | ||||
|   if (!create_surface_extension (&surface->xdg_surface, client, surface_resource, resource, id, | ||||
|   if (!create_surface_extension (&surface->xdg_surface, | ||||
|                                  META_XDG_SURFACE_VERSION, | ||||
|                                  &xdg_surface_interface, | ||||
|                                  &meta_wayland_xdg_surface_interface, | ||||
|                                  xdg_surface_destructor)) | ||||
|                                  xdg_surface_destructor, | ||||
|                                  surface, resource, id)) | ||||
|     { | ||||
|       wl_resource_post_error (surface_resource, | ||||
|                               WL_DISPLAY_ERROR_INVALID_OBJECT, | ||||
| @@ -976,17 +927,17 @@ xdg_shell_get_xdg_surface (struct wl_client *client, | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   meta_wayland_surface_make_toplevel (surface); | ||||
|   surface->window = meta_window_wayland_new (meta_get_display (), surface); | ||||
| } | ||||
|  | ||||
| static void | ||||
| xdg_popup_destructor (struct wl_resource *resource) | ||||
| { | ||||
|   MetaWaylandSurfaceExtension *xdg_popup = wl_resource_get_user_data (resource); | ||||
|   MetaWaylandSurface *surface = wl_container_of (xdg_popup, surface, xdg_popup); | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (resource); | ||||
|  | ||||
|   destroy_window (surface); | ||||
|   destroy_surface_extension (xdg_popup); | ||||
|   destroy_surface_extension (&surface->xdg_popup); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -1015,18 +966,16 @@ xdg_shell_get_xdg_popup (struct wl_client *client, | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); | ||||
|   MetaWaylandSurface *parent_surf = wl_resource_get_user_data (parent_resource); | ||||
|   MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); | ||||
|   MetaRectangle parent_rect; | ||||
|  | ||||
|   if (parent_surf == NULL || parent_surf->window == NULL) | ||||
|     return; | ||||
|  | ||||
|   meta_window_get_rect (parent_surf->window, &parent_rect); | ||||
|  | ||||
|   if (!create_surface_extension (&surface->xdg_popup, client, surface_resource, resource, id, | ||||
|   if (!create_surface_extension (&surface->xdg_popup, | ||||
|                                  META_XDG_POPUP_VERSION, | ||||
|                                  &xdg_popup_interface, | ||||
|                                  &meta_wayland_xdg_popup_interface, | ||||
|                                  xdg_popup_destructor)) | ||||
|                                  xdg_popup_destructor, | ||||
|                                  surface, resource, id)) | ||||
|     { | ||||
|       wl_resource_post_error (surface_resource, | ||||
|                               WL_DISPLAY_ERROR_INVALID_OBJECT, | ||||
| @@ -1034,15 +983,15 @@ xdg_shell_get_xdg_popup (struct wl_client *client, | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   meta_wayland_surface_make_toplevel (surface); | ||||
|   surface->window = meta_window_wayland_new (meta_get_display (), surface); | ||||
|   surface->window->rect.x = parent_rect.x + x; | ||||
|   surface->window->rect.y = parent_rect.y + y; | ||||
|   surface->window->rect.x = parent_surf->window->rect.x + x; | ||||
|   surface->window->rect.y = parent_surf->window->rect.y + y; | ||||
|   surface->window->showing_for_first_time = FALSE; | ||||
|   surface->window->placed = TRUE; | ||||
|   meta_window_set_transient_for (surface->window, parent_surf->window); | ||||
|  | ||||
|   surface->window->type = META_WINDOW_DROPDOWN_MENU; | ||||
|   meta_window_type_changed (surface->window); | ||||
|   meta_window_set_type (surface->window, META_WINDOW_DROPDOWN_MENU); | ||||
|  | ||||
|   meta_wayland_pointer_start_popup_grab (&seat->pointer, surface); | ||||
| } | ||||
| @@ -1108,13 +1057,264 @@ bind_xdg_shell (struct wl_client *client, | ||||
|   wl_client_add_destroy_listener (client, &xdg_shell->client_destroy_listener); | ||||
| } | ||||
|  | ||||
| static void | ||||
| wl_shell_surface_destructor (struct wl_resource *resource) | ||||
| { | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (resource); | ||||
|  | ||||
|   destroy_surface_extension (&surface->wl_shell_surface); | ||||
| } | ||||
|  | ||||
| static void | ||||
| wl_shell_surface_pong (struct wl_client *client, | ||||
|                        struct wl_resource *resource, | ||||
|                        uint32_t serial) | ||||
| { | ||||
|   MetaDisplay *display = meta_get_display (); | ||||
|  | ||||
|   meta_display_pong_for_serial (display, serial); | ||||
| } | ||||
|  | ||||
| static void | ||||
| wl_shell_surface_move (struct wl_client *client, | ||||
|                        struct wl_resource *resource, | ||||
|                        struct wl_resource *seat_resource, | ||||
|                        uint32_t serial) | ||||
| { | ||||
|   MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (resource); | ||||
|  | ||||
|   if (seat->pointer.button_count == 0 || | ||||
|       seat->pointer.grab_serial != serial || | ||||
|       seat->pointer.focus_surface != surface) | ||||
|     return; | ||||
|  | ||||
|   begin_grab_op_on_surface (surface, seat, META_GRAB_OP_MOVING); | ||||
| } | ||||
|  | ||||
| static MetaGrabOp | ||||
| grab_op_for_wl_shell_surface_resize_edge (int edge) | ||||
| { | ||||
|   switch (edge) | ||||
|     { | ||||
|     case WL_SHELL_SURFACE_RESIZE_TOP_LEFT: | ||||
|       return META_GRAB_OP_RESIZING_NW; | ||||
|     case WL_SHELL_SURFACE_RESIZE_TOP: | ||||
|       return META_GRAB_OP_RESIZING_N; | ||||
|     case WL_SHELL_SURFACE_RESIZE_TOP_RIGHT: | ||||
|       return META_GRAB_OP_RESIZING_NE; | ||||
|     case WL_SHELL_SURFACE_RESIZE_RIGHT: | ||||
|       return META_GRAB_OP_RESIZING_E; | ||||
|     case WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT: | ||||
|       return META_GRAB_OP_RESIZING_SE; | ||||
|     case WL_SHELL_SURFACE_RESIZE_BOTTOM: | ||||
|       return META_GRAB_OP_RESIZING_S; | ||||
|     case WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT: | ||||
|       return META_GRAB_OP_RESIZING_SW; | ||||
|     case WL_SHELL_SURFACE_RESIZE_LEFT: | ||||
|       return META_GRAB_OP_RESIZING_W; | ||||
|     default: | ||||
|       g_warning ("invalid edge: %d", edge); | ||||
|       return META_GRAB_OP_NONE; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| wl_shell_surface_resize (struct wl_client *client, | ||||
|                          struct wl_resource *resource, | ||||
|                          struct wl_resource *seat_resource, | ||||
|                          uint32_t serial, | ||||
|                          uint32_t edges) | ||||
| { | ||||
|   MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (resource); | ||||
|  | ||||
|   if (seat->pointer.button_count == 0 || | ||||
|       seat->pointer.grab_serial != serial || | ||||
|       seat->pointer.focus_surface != surface) | ||||
|     return; | ||||
|  | ||||
|   begin_grab_op_on_surface (surface, seat, grab_op_for_wl_shell_surface_resize_edge (edges)); | ||||
| } | ||||
|  | ||||
| typedef enum { | ||||
|   SURFACE_STATE_TOPLEVEL, | ||||
|   SURFACE_STATE_FULLSCREEN, | ||||
|   SURFACE_STATE_MAXIMIZED, | ||||
| } SurfaceState; | ||||
|  | ||||
| static void | ||||
| wl_shell_surface_set_state (MetaWaylandSurface *surface, | ||||
|                             SurfaceState        state) | ||||
| { | ||||
|   if (state == SURFACE_STATE_FULLSCREEN) | ||||
|     meta_window_make_fullscreen (surface->window); | ||||
|   else | ||||
|     meta_window_unmake_fullscreen (surface->window); | ||||
|  | ||||
|   if (state == SURFACE_STATE_MAXIMIZED) | ||||
|     meta_window_maximize (surface->window, META_MAXIMIZE_BOTH); | ||||
|   else | ||||
|     meta_window_unmaximize (surface->window, META_MAXIMIZE_BOTH); | ||||
| } | ||||
|  | ||||
| static void | ||||
| wl_shell_surface_set_toplevel (struct wl_client *client, | ||||
|                                struct wl_resource *resource) | ||||
| { | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (resource); | ||||
|  | ||||
|   wl_shell_surface_set_state (surface, SURFACE_STATE_TOPLEVEL); | ||||
| } | ||||
|  | ||||
| static void | ||||
| wl_shell_surface_set_transient (struct wl_client *client, | ||||
|                                 struct wl_resource *resource, | ||||
|                                 struct wl_resource *parent_resource, | ||||
|                                 int32_t x, | ||||
|                                 int32_t y, | ||||
|                                 uint32_t flags) | ||||
| { | ||||
|   MetaWaylandSurface *parent_surf = wl_resource_get_user_data (parent_resource); | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (resource); | ||||
|  | ||||
|   wl_shell_surface_set_state (surface, SURFACE_STATE_TOPLEVEL); | ||||
|  | ||||
|   meta_window_set_transient_for (surface->window, parent_surf->window); | ||||
|   meta_window_move (surface->window, FALSE, | ||||
|                     parent_surf->window->rect.x + x, | ||||
|                     parent_surf->window->rect.y + y); | ||||
|   surface->window->placed = TRUE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| wl_shell_surface_set_fullscreen (struct wl_client *client, | ||||
|                                  struct wl_resource *resource, | ||||
|                                  uint32_t method, | ||||
|                                  uint32_t framerate, | ||||
|                                  struct wl_resource *output) | ||||
| { | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (resource); | ||||
|  | ||||
|   wl_shell_surface_set_state (surface, SURFACE_STATE_FULLSCREEN); | ||||
| } | ||||
|  | ||||
| static void | ||||
| wl_shell_surface_set_popup (struct wl_client *client, | ||||
|                             struct wl_resource *resource, | ||||
|                             struct wl_resource *seat_resource, | ||||
|                             uint32_t serial, | ||||
|                             struct wl_resource *parent_resource, | ||||
|                             int32_t x, | ||||
|                             int32_t y, | ||||
|                             uint32_t flags) | ||||
| { | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (resource); | ||||
|   MetaWaylandSurface *parent_surf = wl_resource_get_user_data (parent_resource); | ||||
|   MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); | ||||
|  | ||||
|   wl_shell_surface_set_state (surface, SURFACE_STATE_TOPLEVEL); | ||||
|  | ||||
|   meta_window_set_transient_for (surface->window, parent_surf->window); | ||||
|   meta_window_move (surface->window, FALSE, | ||||
|                     parent_surf->window->rect.x + x, | ||||
|                     parent_surf->window->rect.y + y); | ||||
|   surface->window->placed = TRUE; | ||||
|  | ||||
|   meta_wayland_pointer_start_popup_grab (&seat->pointer, surface); | ||||
| } | ||||
|  | ||||
| static void | ||||
| wl_shell_surface_set_maximized (struct wl_client *client, | ||||
|                                 struct wl_resource *resource, | ||||
|                                 struct wl_resource *output) | ||||
| { | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (resource); | ||||
|  | ||||
|   wl_shell_surface_set_state (surface, SURFACE_STATE_MAXIMIZED); | ||||
| } | ||||
|  | ||||
| static void | ||||
| wl_shell_surface_set_title (struct wl_client *client, | ||||
|                             struct wl_resource *resource, | ||||
|                             const char *title) | ||||
| { | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (resource); | ||||
|  | ||||
|   meta_window_set_title (surface->window, title); | ||||
| } | ||||
|  | ||||
| static void | ||||
| wl_shell_surface_set_class (struct wl_client *client, | ||||
|                             struct wl_resource *resource, | ||||
|                             const char *class_) | ||||
| { | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (resource); | ||||
|  | ||||
|   meta_window_set_wm_class (surface->window, class_, class_); | ||||
| } | ||||
|  | ||||
| static const struct wl_shell_surface_interface meta_wayland_wl_shell_surface_interface = { | ||||
|   wl_shell_surface_pong, | ||||
|   wl_shell_surface_move, | ||||
|   wl_shell_surface_resize, | ||||
|   wl_shell_surface_set_toplevel, | ||||
|   wl_shell_surface_set_transient, | ||||
|   wl_shell_surface_set_fullscreen, | ||||
|   wl_shell_surface_set_popup, | ||||
|   wl_shell_surface_set_maximized, | ||||
|   wl_shell_surface_set_title, | ||||
|   wl_shell_surface_set_class, | ||||
| }; | ||||
|  | ||||
| static void | ||||
| wl_shell_get_shell_surface (struct wl_client *client, | ||||
|                             struct wl_resource *resource, | ||||
|                             uint32_t id, | ||||
|                             struct wl_resource *surface_resource) | ||||
| { | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); | ||||
|  | ||||
|   if (!create_surface_extension (&surface->wl_shell_surface, | ||||
|                                  META_WL_SHELL_SURFACE_VERSION, | ||||
|                                  &wl_shell_surface_interface, | ||||
|                                  &meta_wayland_wl_shell_surface_interface, | ||||
|                                  wl_shell_surface_destructor, | ||||
|                                  surface, resource, id)) | ||||
|     { | ||||
|       wl_resource_post_error (surface_resource, | ||||
|                               WL_DISPLAY_ERROR_INVALID_OBJECT, | ||||
|                               "wl_shell::get_shell_surface already requested"); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   meta_wayland_surface_make_toplevel (surface); | ||||
|   surface->window = meta_window_wayland_new (meta_get_display (), surface); | ||||
| } | ||||
|  | ||||
| static const struct wl_shell_interface meta_wayland_wl_shell_interface = { | ||||
|   wl_shell_get_shell_surface, | ||||
| }; | ||||
|  | ||||
| static void | ||||
| bind_wl_shell (struct wl_client *client, | ||||
|                void             *data, | ||||
|                uint32_t          version, | ||||
|                uint32_t          id) | ||||
| { | ||||
|   struct wl_resource *resource; | ||||
|  | ||||
|   resource = wl_resource_create (client, &wl_shell_interface, | ||||
|                                  MIN (META_WL_SHELL_VERSION, version), id); | ||||
|   wl_resource_set_implementation (resource, &meta_wayland_wl_shell_interface, data, NULL); | ||||
| } | ||||
|  | ||||
| static void | ||||
| gtk_surface_destructor (struct wl_resource *resource) | ||||
| { | ||||
|   MetaWaylandSurfaceExtension *gtk_surface = wl_resource_get_user_data (resource); | ||||
|   MetaWaylandSurface *surface = wl_container_of (gtk_surface, surface, gtk_surface); | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (resource); | ||||
|  | ||||
|   destroy_surface_extension (gtk_surface); | ||||
|   destroy_surface_extension (&surface->gtk_surface); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -1127,8 +1327,7 @@ set_dbus_properties (struct wl_client   *client, | ||||
| 		     const char         *application_object_path, | ||||
| 		     const char         *unique_bus_name) | ||||
| { | ||||
|   MetaWaylandSurfaceExtension *gtk_surface = wl_resource_get_user_data (resource); | ||||
|   MetaWaylandSurface *surface = wl_container_of (gtk_surface, surface, gtk_surface); | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (resource); | ||||
|  | ||||
|   /* Broken client, let it die instead of us */ | ||||
|   if (!surface->window) | ||||
| @@ -1158,11 +1357,12 @@ get_gtk_surface (struct wl_client *client, | ||||
| { | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); | ||||
|  | ||||
|   if (!create_surface_extension (&surface->gtk_surface, client, surface_resource, resource, id, | ||||
|   if (!create_surface_extension (&surface->gtk_surface, | ||||
|                                  META_GTK_SURFACE_VERSION, | ||||
|                                  >k_surface_interface, | ||||
|                                  &meta_wayland_gtk_surface_interface, | ||||
|                                  gtk_surface_destructor)) | ||||
|                                  gtk_surface_destructor, | ||||
|                                  surface, resource, id)) | ||||
|     { | ||||
|       wl_resource_post_error (surface_resource, | ||||
|                               WL_DISPLAY_ERROR_INVALID_OBJECT, | ||||
| @@ -1244,15 +1444,20 @@ subsurface_parent_surface_committed (MetaWaylandSurface *surface) | ||||
|  | ||||
|   if (surface->sub.synchronous) | ||||
|     commit_double_buffered_state (surface, pending_surface_state); | ||||
| } | ||||
|  | ||||
|   double_buffered_state_reset (pending_surface_state); | ||||
| static void | ||||
| unparent_actor (MetaWaylandSurface *surface) | ||||
| { | ||||
|   ClutterActor *parent_actor; | ||||
|   parent_actor = clutter_actor_get_parent (CLUTTER_ACTOR (surface->surface_actor)); | ||||
|   clutter_actor_remove_child (parent_actor, CLUTTER_ACTOR (surface->surface_actor)); | ||||
| } | ||||
|  | ||||
| static void | ||||
| wl_subsurface_destructor (struct wl_resource *resource) | ||||
| { | ||||
|   MetaWaylandSurfaceExtension *subsurface = wl_resource_get_user_data (resource); | ||||
|   MetaWaylandSurface *surface = wl_container_of (subsurface, surface, subsurface); | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (resource); | ||||
|  | ||||
|   if (surface->sub.parent) | ||||
|     { | ||||
| @@ -1264,7 +1469,7 @@ wl_subsurface_destructor (struct wl_resource *resource) | ||||
|     } | ||||
|  | ||||
|   double_buffered_state_destroy (&surface->sub.pending_surface_state); | ||||
|   destroy_surface_extension (subsurface); | ||||
|   destroy_surface_extension (&surface->subsurface); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -1280,8 +1485,7 @@ wl_subsurface_set_position (struct wl_client *client, | ||||
|                             int32_t x, | ||||
|                             int32_t y) | ||||
| { | ||||
|   MetaWaylandSurfaceExtension *subsurface = wl_resource_get_user_data (resource); | ||||
|   MetaWaylandSurface *surface = wl_container_of (subsurface, surface, subsurface); | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (resource); | ||||
|  | ||||
|   surface->sub.pending_x = x; | ||||
|   surface->sub.pending_y = y; | ||||
| @@ -1331,8 +1535,7 @@ wl_subsurface_place_above (struct wl_client *client, | ||||
|                            struct wl_resource *resource, | ||||
|                            struct wl_resource *sibling_resource) | ||||
| { | ||||
|   MetaWaylandSurfaceExtension *subsurface = wl_resource_get_user_data (resource); | ||||
|   MetaWaylandSurface *surface = wl_container_of (subsurface, surface, subsurface); | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (resource); | ||||
|   MetaWaylandSurface *sibling = wl_resource_get_user_data (sibling_resource); | ||||
|  | ||||
|   if (!is_valid_sibling (surface, sibling)) | ||||
| @@ -1354,8 +1557,7 @@ wl_subsurface_place_below (struct wl_client *client, | ||||
|                            struct wl_resource *resource, | ||||
|                            struct wl_resource *sibling_resource) | ||||
| { | ||||
|   MetaWaylandSurfaceExtension *subsurface = wl_resource_get_user_data (resource); | ||||
|   MetaWaylandSurface *surface = wl_container_of (subsurface, surface, subsurface); | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (resource); | ||||
|   MetaWaylandSurface *sibling = wl_resource_get_user_data (sibling_resource); | ||||
|  | ||||
|   if (!is_valid_sibling (surface, sibling)) | ||||
| @@ -1376,10 +1578,7 @@ static void | ||||
| wl_subsurface_set_sync (struct wl_client *client, | ||||
|                         struct wl_resource *resource) | ||||
| { | ||||
|   MetaWaylandSurfaceExtension *subsurface = | ||||
|     wl_resource_get_user_data (resource); | ||||
|   MetaWaylandSurface *surface = | ||||
|     wl_container_of (subsurface, surface, subsurface); | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (resource); | ||||
|  | ||||
|   surface->sub.synchronous = TRUE; | ||||
| } | ||||
| @@ -1388,10 +1587,7 @@ static void | ||||
| wl_subsurface_set_desync (struct wl_client *client, | ||||
|                           struct wl_resource *resource) | ||||
| { | ||||
|   MetaWaylandSurfaceExtension *subsurface = | ||||
|     wl_resource_get_user_data (resource); | ||||
|   MetaWaylandSurface *surface = | ||||
|     wl_container_of (subsurface, surface, subsurface); | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (resource); | ||||
|  | ||||
|   if (surface->sub.synchronous) | ||||
|     subsurface_parent_surface_committed (surface); | ||||
| @@ -1437,11 +1633,12 @@ wl_subcompositor_get_subsurface (struct wl_client *client, | ||||
|   MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); | ||||
|   MetaWaylandSurface *parent = wl_resource_get_user_data (parent_resource); | ||||
|  | ||||
|   if (!create_surface_extension (&surface->subsurface, client, surface_resource, resource, id, | ||||
|   if (!create_surface_extension (&surface->subsurface, | ||||
|                                  META_GTK_SURFACE_VERSION, | ||||
|                                  &wl_subsurface_interface, | ||||
|                                  &meta_wayland_subsurface_interface, | ||||
|                                  wl_subsurface_destructor)) | ||||
|                                  wl_subsurface_destructor, | ||||
|                                  surface, resource, id)) | ||||
|     { | ||||
|       wl_resource_post_error (surface_resource, | ||||
|                               WL_DISPLAY_ERROR_INVALID_OBJECT, | ||||
| @@ -1487,6 +1684,11 @@ meta_wayland_init_shell (MetaWaylandCompositor *compositor) | ||||
| 			compositor, bind_xdg_shell) == NULL) | ||||
|     g_error ("Failed to register a global xdg-shell object"); | ||||
|  | ||||
|   if (wl_global_create (compositor->wayland_display, | ||||
| 			&wl_shell_interface, 1, | ||||
| 			compositor, bind_wl_shell) == NULL) | ||||
|     g_error ("Failed to register a global wl-shell object"); | ||||
|  | ||||
|   if (wl_global_create (compositor->wayland_display, | ||||
| 			>k_shell_interface, | ||||
| 			META_GTK_SHELL_VERSION, | ||||
| @@ -1508,26 +1710,80 @@ meta_wayland_surface_configure_notify (MetaWaylandSurface *surface, | ||||
|   if (surface->xdg_surface.resource) | ||||
|     xdg_surface_send_configure (surface->xdg_surface.resource, | ||||
|                                 new_width, new_height); | ||||
|   else if (surface->wl_shell_surface.resource) | ||||
|     wl_shell_surface_send_configure (surface->wl_shell_surface.resource, | ||||
|                                      0, new_width, new_height); | ||||
| } | ||||
|  | ||||
| static void | ||||
| send_change_state (MetaWaylandSurface *surface, | ||||
|                    uint32_t state_type, | ||||
|                    uint32_t value) | ||||
| { | ||||
|   if (surface->xdg_surface.resource) | ||||
|     { | ||||
|       uint32_t serial; | ||||
|  | ||||
|       if (surface->state_changed_serial != 0) | ||||
|         { | ||||
|           serial = surface->state_changed_serial; | ||||
|           surface->state_changed_serial = 0; | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           struct wl_client *client = wl_resource_get_client (surface->xdg_surface.resource); | ||||
|           struct wl_display *display = wl_client_get_display (client); | ||||
|           serial = wl_display_next_serial (display); | ||||
|         } | ||||
|  | ||||
|       xdg_surface_send_change_state (surface->xdg_surface.resource, state_type, value, serial); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_wayland_surface_focused_set (MetaWaylandSurface *surface) | ||||
| meta_wayland_surface_send_maximized (MetaWaylandSurface *surface) | ||||
| { | ||||
|   if (surface->xdg_surface.resource) | ||||
|     xdg_surface_send_focused_set (surface->xdg_surface.resource); | ||||
|   send_change_state (surface, XDG_SURFACE_STATE_MAXIMIZED, TRUE); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_wayland_surface_focused_unset (MetaWaylandSurface *surface) | ||||
| meta_wayland_surface_send_unmaximized (MetaWaylandSurface *surface) | ||||
| { | ||||
|   send_change_state (surface, XDG_SURFACE_STATE_MAXIMIZED, FALSE); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_wayland_surface_send_fullscreened (MetaWaylandSurface *surface) | ||||
| { | ||||
|   send_change_state (surface, XDG_SURFACE_STATE_FULLSCREEN, TRUE); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_wayland_surface_send_unfullscreened (MetaWaylandSurface *surface) | ||||
| { | ||||
|   send_change_state (surface, XDG_SURFACE_STATE_FULLSCREEN, FALSE); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_wayland_surface_activated (MetaWaylandSurface *surface) | ||||
| { | ||||
|   if (surface->xdg_surface.resource) | ||||
|     xdg_surface_send_focused_unset (surface->xdg_surface.resource); | ||||
|     xdg_surface_send_activated (surface->xdg_surface.resource); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_wayland_surface_deactivated (MetaWaylandSurface *surface) | ||||
| { | ||||
|   if (surface->xdg_surface.resource) | ||||
|     xdg_surface_send_deactivated (surface->xdg_surface.resource); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_wayland_surface_ping (MetaWaylandSurface *surface, | ||||
|                            guint32             serial) | ||||
| { | ||||
|   if (surface->xdg_surface.resource) | ||||
|     { | ||||
|       struct wl_client *client = wl_resource_get_client (surface->resource); | ||||
|       struct wl_resource *xdg_shell = get_xdg_shell_for_client (client); | ||||
|  | ||||
| @@ -1538,6 +1794,11 @@ meta_wayland_surface_ping (MetaWaylandSurface *surface, | ||||
|         } | ||||
|  | ||||
|       xdg_shell_send_ping (xdg_shell, serial); | ||||
|     } | ||||
|   else if (surface->wl_shell_surface.resource) | ||||
|     { | ||||
|       wl_shell_surface_send_ping (surface->wl_shell_surface.resource, serial); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -1546,3 +1807,16 @@ meta_wayland_surface_delete (MetaWaylandSurface *surface) | ||||
|   if (surface->xdg_surface.resource) | ||||
|     xdg_surface_send_delete (surface->xdg_surface.resource); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_wayland_surface_popup_done (MetaWaylandSurface *surface) | ||||
| { | ||||
|   struct wl_client *client = wl_resource_get_client (surface->resource); | ||||
|   struct wl_display *display = wl_client_get_display (client); | ||||
|   uint32_t serial = wl_display_next_serial (display); | ||||
|  | ||||
|   if (surface->xdg_popup.resource) | ||||
|     xdg_popup_send_popup_done (surface->xdg_popup.resource, serial); | ||||
|   else if (surface->wl_shell_surface.resource) | ||||
|     wl_shell_surface_send_popup_done (surface->wl_shell_surface.resource); | ||||
| } | ||||
|   | ||||
| @@ -38,16 +38,9 @@ struct _MetaWaylandBuffer | ||||
|   struct wl_listener destroy_listener; | ||||
|  | ||||
|   CoglTexture *texture; | ||||
|   int32_t width, height; | ||||
|   uint32_t ref_count; | ||||
| }; | ||||
|  | ||||
| typedef struct | ||||
| { | ||||
|   guint changed : 1; | ||||
|   guint value : 1; | ||||
| } MetaWaylandStateFlag; | ||||
|  | ||||
| typedef struct | ||||
| { | ||||
|   /* wl_surface.attach */ | ||||
| @@ -68,15 +61,11 @@ typedef struct | ||||
|  | ||||
|   gboolean frame_extents_changed; | ||||
|   GtkBorder frame_extents; | ||||
|  | ||||
|   MetaWaylandStateFlag fullscreen; | ||||
|   MetaWaylandStateFlag maximized; | ||||
| } MetaWaylandDoubleBufferedState; | ||||
|  | ||||
| typedef struct | ||||
| { | ||||
|   struct wl_resource *resource; | ||||
|   struct wl_listener surface_destroy_listener; | ||||
| } MetaWaylandSurfaceExtension; | ||||
|  | ||||
| struct _MetaWaylandSurface | ||||
| @@ -87,6 +76,7 @@ struct _MetaWaylandSurface | ||||
|   MetaWindow *window; | ||||
|   MetaWaylandSurfaceExtension xdg_surface; | ||||
|   MetaWaylandSurfaceExtension xdg_popup; | ||||
|   MetaWaylandSurfaceExtension wl_shell_surface; | ||||
|   MetaWaylandSurfaceExtension gtk_surface; | ||||
|   MetaWaylandSurfaceExtension subsurface; | ||||
|  | ||||
| @@ -108,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; | ||||
| }; | ||||
| @@ -119,17 +111,25 @@ MetaWaylandSurface *meta_wayland_surface_create (MetaWaylandCompositor *composit | ||||
| 						 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); | ||||
| 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,6 +37,7 @@ | ||||
| /* 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 | ||||
| @@ -52,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 */ | ||||
|   | ||||
| @@ -508,6 +508,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 +545,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) | ||||
| @@ -643,6 +652,8 @@ meta_wayland_init (void) | ||||
|  | ||||
|   clutter_wayland_set_compositor_display (compositor->wayland_display); | ||||
|  | ||||
|   /* 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 (); | ||||
| @@ -651,17 +662,6 @@ meta_wayland_init (void) | ||||
|   if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS) | ||||
|     g_error ("Failed to initialize Clutter"); | ||||
|  | ||||
| #if defined(CLUTTER_WINDOWING_EGL) | ||||
|   if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL)) | ||||
|     { | ||||
|       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)); | ||||
|       int drm_fd = cogl_kms_renderer_get_kms_fd (cogl_renderer); | ||||
|       meta_launcher_set_drm_fd (compositor->launcher, drm_fd, NULL); | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|   meta_monitor_manager_initialize (); | ||||
|   monitors = meta_monitor_manager_get (); | ||||
|   g_signal_connect (monitors, "monitors-changed", | ||||
| @@ -728,7 +728,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; | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										53
									
								
								src/wayland/meta-wayland.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/wayland/meta-wayland.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | ||||
| /* | ||||
|  * Copyright (C) 2014 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Jasper St. Pierre <jstpierre@mecheye.net> | ||||
|  */ | ||||
|  | ||||
| #ifndef META_WAYLAND_H | ||||
| #define META_WAYLAND_H | ||||
|  | ||||
| #include "meta-wayland-types.h" | ||||
|  | ||||
| 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); | ||||
|  | ||||
| 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); | ||||
| gboolean                meta_wayland_compositor_activate_session (MetaWaylandCompositor  *compositor, | ||||
|                                                                   GError                **error); | ||||
|  | ||||
| #endif | ||||
|  | ||||
| @@ -23,6 +23,7 @@ | ||||
| #include <gio/gunixfdmessage.h> | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
| #include <clutter/egl/clutter-egl.h> | ||||
| #include <clutter/evdev/clutter-evdev.h> | ||||
|  | ||||
| #include <glib.h> | ||||
| @@ -41,6 +42,8 @@ | ||||
| #include <xf86drm.h> | ||||
| #include <xf86drmMode.h> | ||||
|  | ||||
| #include "meta-wayland-private.h" | ||||
| #include "meta-cursor-tracker-private.h" | ||||
| #include "meta-weston-launch.h" | ||||
|  | ||||
| struct _MetaLauncher | ||||
| @@ -154,33 +157,8 @@ send_message_to_wl (MetaLauncher           *self, | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_launcher_set_drm_fd (MetaLauncher  *self, | ||||
| 			  int            drm_fd, | ||||
| 			  GError       **error) | ||||
| { | ||||
|   struct weston_launcher_message message; | ||||
|   GSocketControlMessage *cmsg; | ||||
|   gboolean ok; | ||||
|  | ||||
|   message.opcode = WESTON_LAUNCHER_DRM_SET_FD; | ||||
|  | ||||
|   cmsg = g_unix_fd_message_new (); | ||||
|   if (g_unix_fd_message_append_fd (G_UNIX_FD_MESSAGE (cmsg), | ||||
| 				   drm_fd, error) == FALSE) | ||||
|     { | ||||
|       g_object_unref (cmsg); | ||||
|       return FALSE; | ||||
|     } | ||||
|  | ||||
|   ok = send_message_to_wl (self, &message, sizeof message, cmsg, NULL, error); | ||||
|  | ||||
|   g_object_unref (cmsg); | ||||
|   return ok; | ||||
| } | ||||
|  | ||||
| int | ||||
| meta_launcher_open_input_device (MetaLauncher  *self, | ||||
| static int | ||||
| meta_launcher_open_device (MetaLauncher  *self, | ||||
|                            const char    *name, | ||||
|                            int            flags, | ||||
|                            GError       **error) | ||||
| @@ -232,6 +210,17 @@ meta_launcher_enter (MetaLauncher *launcher) | ||||
|   cogl_kms_display_queue_modes_reset (cogl_display); | ||||
|  | ||||
|   clutter_evdev_reclaim_devices (); | ||||
|  | ||||
|   { | ||||
|     MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); | ||||
|  | ||||
|     /* When we mode-switch back, we need to immediately queue a redraw | ||||
|      * in case nothing else queued one for us, and force the cursor to | ||||
|      * update. */ | ||||
|  | ||||
|     clutter_actor_queue_redraw (compositor->stage); | ||||
|     meta_cursor_tracker_force_update (compositor->seat->cursor_tracker); | ||||
|   } | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -248,7 +237,14 @@ on_evdev_device_open (const char  *path, | ||||
| { | ||||
|   MetaLauncher *launcher = user_data; | ||||
|  | ||||
|   return meta_launcher_open_input_device (launcher, path, flags, error); | ||||
|   return meta_launcher_open_device (launcher, path, flags, error); | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_evdev_device_close (int          fd, | ||||
|                        gpointer     user_data) | ||||
| { | ||||
|   close (fd); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -354,8 +350,6 @@ meta_launcher_new (void) | ||||
|  | ||||
|   self->weston_launch = g_socket_new_from_fd (launch_fd, NULL); | ||||
|  | ||||
|   clutter_evdev_set_open_callback (on_evdev_device_open, self); | ||||
|  | ||||
|   self->nested_context = g_main_context_new (); | ||||
|   self->nested_loop = g_main_loop_new (self->nested_context, FALSE); | ||||
|  | ||||
| @@ -369,6 +363,22 @@ meta_launcher_new (void) | ||||
|   g_source_attach (self->inner_source, self->nested_context); | ||||
|   g_source_unref (self->inner_source); | ||||
|  | ||||
|   clutter_evdev_set_device_callbacks (on_evdev_device_open, | ||||
|                                       on_evdev_device_close, | ||||
|                                       self); | ||||
|  | ||||
| #if defined(CLUTTER_WINDOWING_EGL) | ||||
|   if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL)) | ||||
|     { | ||||
|       GError *error = NULL; | ||||
|       int fd = meta_launcher_open_device (self, "/dev/dri/card0", O_RDWR, &error); | ||||
|       if (error) | ||||
|         g_error ("Failed to open /dev/dri/card0: %s", error->message); | ||||
|  | ||||
|       clutter_egl_set_kms_fd (fd); | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|   return self; | ||||
| } | ||||
|  | ||||
| @@ -388,7 +398,7 @@ meta_launcher_free (MetaLauncher *launcher) | ||||
|  | ||||
| gboolean | ||||
| meta_launcher_activate_vt (MetaLauncher  *launcher, | ||||
| 			   int            vt, | ||||
| 			   signed char    vt, | ||||
| 			   GError       **error) | ||||
| { | ||||
|   struct weston_launcher_activate_vt message; | ||||
|   | ||||
| @@ -29,18 +29,6 @@ MetaLauncher     *meta_launcher_new                     (void); | ||||
| void              meta_launcher_free                    (MetaLauncher  *self); | ||||
|  | ||||
| gboolean          meta_launcher_activate_vt             (MetaLauncher  *self, | ||||
| 							 int            number, | ||||
| 							 signed char    vt, | ||||
| 							 GError       **error); | ||||
|  | ||||
| gboolean          meta_launcher_set_drm_fd              (MetaLauncher  *self, | ||||
| 							 int            drm_fd, | ||||
| 							 GError       **error); | ||||
| gboolean          meta_launcher_set_master              (MetaLauncher  *self, | ||||
| 							 gboolean       master, | ||||
| 							 GError       **error); | ||||
| int               meta_launcher_open_input_device       (MetaLauncher  *self, | ||||
| 							 const char    *name, | ||||
| 							 int            flags, | ||||
| 							 GError       **error); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -47,10 +47,19 @@ xserver_set_window_id (struct wl_client *client, | ||||
|   if (!window) | ||||
|     return; | ||||
|  | ||||
|   /* If the window has an existing surface, like if we're | ||||
|    * undecorating or decorating the window, then we need | ||||
|    * to detach the window from its old surface. | ||||
|    */ | ||||
|   if (window->surface) | ||||
|     window->surface->window = NULL; | ||||
|  | ||||
|   meta_wayland_surface_make_toplevel (surface); | ||||
|  | ||||
|   surface->window = window; | ||||
|   window->surface = surface; | ||||
|  | ||||
|   meta_window_set_surface_mapped (window, TRUE); | ||||
|   meta_compositor_window_surface_changed (display->compositor, window); | ||||
| } | ||||
|  | ||||
| static const struct xserver_interface xserver_implementation = { | ||||
|   | ||||
| @@ -40,19 +40,22 @@ | ||||
| 
 | ||||
|     <enum name="version"> | ||||
|       <description summary="latest protocol version"> | ||||
| 	Use this enum to check the protocol version, and it will be updated | ||||
| 	automatically. | ||||
| 	The 'current' member of this enum gives the version of the | ||||
| 	protocol.  Implementations can compare this to the version | ||||
| 	they implement using static_assert to ensure the protocol and | ||||
| 	implementation versions match. | ||||
|       </description> | ||||
|       <entry name="current" value="2" summary="Always the latest version"/> | ||||
|       <entry name="current" value="3" summary="Always the latest version"/> | ||||
|     </enum> | ||||
| 
 | ||||
| 
 | ||||
|     <request name="use_unstable_version"> | ||||
|       <description summary="enable use of this unstable version"> | ||||
| 	Use this request in order to enable use of this interface. | ||||
| 
 | ||||
| 	Understand and agree that one is using an unstable interface, | ||||
| 	that will likely change in the future, breaking the API. | ||||
| 	Negotiate the unstable version of the interface.  This | ||||
| 	mechanism is in place to ensure client and server agree on the | ||||
| 	unstable versions of the protocol that they speak or exit | ||||
| 	cleanly if they don't agree.  This request will go away once | ||||
| 	the xdg-shell protocol is stable. | ||||
|       </description> | ||||
|       <arg name="version" type="int"/> | ||||
|     </request> | ||||
| @@ -249,12 +252,6 @@ | ||||
| 	ignore it if it doesn't resize, pick a smaller size (to | ||||
| 	satisfy aspect ratio or resize in steps of NxM pixels). | ||||
| 
 | ||||
| 	The edges parameter provides a hint about how the surface | ||||
| 	was resized. The client may use this information to decide | ||||
| 	how to adjust its content to the new size (e.g. a scrolling | ||||
| 	area might adjust its content position to leave the viewable | ||||
| 	content unmoved). Valid edge values are from resize_edge enum. | ||||
| 
 | ||||
| 	The client is free to dismiss all but the last configure | ||||
| 	event it received. | ||||
| 
 | ||||
| @@ -281,128 +278,109 @@ | ||||
|       <arg name="output" type="object" interface="wl_output" allow-null="true"/> | ||||
|     </request> | ||||
| 
 | ||||
|     <event name="request_set_fullscreen"> | ||||
|       <description summary="server requests that the client set fullscreen"> | ||||
| 	Event sent from the compositor to the client requesting that the client | ||||
| 	goes to a fullscreen state. It's the client job to call set_fullscreen | ||||
| 	and really trigger the fullscreen state. | ||||
|     <enum name="state"> | ||||
|       <description summary="types of state on the surface"> | ||||
|         The different state values used on the surface. This is designed for | ||||
|         state values like maximized, fullscreen. It is paired with the | ||||
|         request_change_state event to ensure that both the client and the | ||||
|         compositor setting the state can be synchronized. | ||||
| 
 | ||||
|         States set in this way are double-buffered. They will get applied on | ||||
|         the next commit. | ||||
| 
 | ||||
|         Desktop environments may extend this enum by taking up a range of | ||||
|         values and documenting the range they chose in this description. | ||||
|         They are not required to document the values for the range that they | ||||
|         chose. Ideally, any good extensions from a desktop environment should | ||||
|         make its way into standardization into this enum. | ||||
| 
 | ||||
|         The current reserved ranges are: | ||||
| 
 | ||||
|         0x0000 - 0x0FFF: xdg-shell core values, documented below. | ||||
|         0x1000 - 0x1FFF: GNOME | ||||
|       </description> | ||||
|     </event> | ||||
|       <entry name="maximized" value="1" summary="the surface is maximized"> | ||||
|         A non-zero value indicates the surface is maximized. Otherwise, | ||||
|         the surface is unmaximized. | ||||
|       </entry> | ||||
|       <entry name="fullscreen" value="2" summary="the surface is fullscreen"> | ||||
|         A non-zero value indicates the surface is fullscreen. Otherwise, | ||||
|         the surface is not fullscreen. | ||||
|       </entry> | ||||
|     </enum> | ||||
| 
 | ||||
|     <event name="request_unset_fullscreen"> | ||||
|       <description summary="server requests that the client unset fullscreen"> | ||||
| 	Event sent from the compositor to the client requesting that the client | ||||
| 	leaves the fullscreen state. It's the client job to call | ||||
| 	unset_fullscreen and really leave the fullscreen state. | ||||
|       </description> | ||||
|     </event> | ||||
| 
 | ||||
|     <request name="set_fullscreen"> | ||||
|       <description summary="set the surface state as fullscreen"> | ||||
| 	Set the surface as fullscreen. | ||||
| 
 | ||||
| 	After this request, the compositor should send a configure event | ||||
| 	informing the output size. | ||||
| 
 | ||||
| 	This request informs the compositor that the next attached buffer | ||||
| 	committed will be in a fullscreen state. The buffer size should be the | ||||
| 	same size as the size informed in the configure event, if the client | ||||
| 	doesn't want to leave any empty area. | ||||
| 
 | ||||
| 	In other words: the next attached buffer after set_maximized is the new | ||||
| 	maximized buffer. And the surface will be positioned at the maximized | ||||
| 	position on commit. | ||||
| 
 | ||||
| 	A simple way to synchronize and wait for the correct configure event is | ||||
| 	to use a wl_display.sync request right after the set_fullscreen | ||||
| 	request. When the sync callback returns, the last configure event | ||||
| 	received just before it will be the correct one, and should contain the | ||||
| 	right size for the surface to maximize. | ||||
| 
 | ||||
| 	Setting one state won't unset another state. Use | ||||
| 	xdg_surface.unset_fullscreen for unsetting it. | ||||
|     <request name="request_change_state"> | ||||
|       <description summary="client requests to change a surface's state"> | ||||
|         This asks the compositor to change the state. If the compositor wants | ||||
|         to change the state, it will send a change_state event with the same | ||||
|         state_type, value, and serial, and the event flow continues as if it | ||||
|         it was initiated by the compositor. | ||||
| 
 | ||||
|         If the compositor does not want to change the state, it will send a | ||||
|         change_state to the client with the old value of the state. | ||||
|       </description> | ||||
|       <arg name="state_type" type="uint" summary="the state to set"/> | ||||
|       <arg name="value" type="uint" summary="the value to change the state to"/> | ||||
|       <arg name="serial" type="uint" summary="an event serial"> | ||||
|         This serial is so the client can know which change_state event corresponds | ||||
|         to which request_change_state request it sent out. | ||||
|       </arg> | ||||
|     </request> | ||||
| 
 | ||||
|     <request name="unset_fullscreen"> | ||||
|       <description summary="unset the surface state as fullscreen"> | ||||
| 	Unset the surface fullscreen state. | ||||
| 
 | ||||
| 	Same negotiation as set_fullscreen must be used. | ||||
|     <event name="change_state"> | ||||
|       <description summary="compositor wants to change a surface's state"> | ||||
|         This event tells the client to change a surface's state. The client | ||||
|         should respond with an ack_change_state request to the compositor to | ||||
|         guarantee that the compositor knows that the client has seen it. | ||||
|       </description> | ||||
|     </request> | ||||
| 
 | ||||
|     <event name="request_set_maximized"> | ||||
|       <description summary="server requests that the client set maximized"> | ||||
| 	Event sent from the compositor to the client requesting that the client | ||||
| 	goes to a maximized state. It's the client job to call set_maximized | ||||
| 	and really trigger the maximized state. | ||||
|       </description> | ||||
|       <arg name="state_type" type="uint" summary="the state to set"/> | ||||
|       <arg name="value" type="uint" summary="the value to change the state to"/> | ||||
|       <arg name="serial" type="uint" summary="a serial for the compositor's own tracking"/> | ||||
|     </event> | ||||
| 
 | ||||
|     <event name="request_unset_maximized"> | ||||
|       <description summary="server requests that the client unset maximized"> | ||||
| 	Event sent from the compositor to the client requesting that the client | ||||
| 	leaves the maximized state. It's the client job to call unset_maximized | ||||
| 	and really leave the maximized state. | ||||
|       </description> | ||||
|     </event> | ||||
| 
 | ||||
|     <request name="set_maximized"> | ||||
|       <description summary="set the surface state as maximized"> | ||||
| 	Set the surface as maximized. | ||||
| 
 | ||||
| 	After this request, the compositor will send a configure event | ||||
| 	informing the output size minus panel and other MW decorations. | ||||
| 
 | ||||
| 	This request informs the compositor that the next attached buffer | ||||
| 	committed will be in a maximized state. The buffer size should be the | ||||
| 	same size as the size informed in the configure event, if the client | ||||
| 	doesn't want to leave any empty area. | ||||
| 
 | ||||
| 	In other words: the next attached buffer after set_maximized is the new | ||||
| 	maximized buffer. And the surface will be positioned at the maximized | ||||
| 	position on commit. | ||||
| 
 | ||||
| 	A simple way to synchronize and wait for the correct configure event is | ||||
| 	to use a wl_display.sync request right after the set_maximized request. | ||||
| 	When the sync callback returns, the last configure event received just | ||||
| 	before it will be the correct one, and should contain the right size | ||||
| 	for the surface to maximize. | ||||
| 
 | ||||
| 	Setting one state won't unset another state. Use | ||||
| 	xdg_surface.unset_maximized for unsetting it. | ||||
|       </description> | ||||
|     </request> | ||||
| 
 | ||||
|     <request name="unset_maximized"> | ||||
|       <description summary="unset the surface state as maximized"> | ||||
| 	Unset the surface maximized state. | ||||
| 
 | ||||
| 	Same negotiation as set_maximized must be used. | ||||
|     <request name="ack_change_state"> | ||||
|       <description summary="ack a change_state event"> | ||||
|         When a change_state event is received, a client should then ack it | ||||
|         using the ack_change_state request to ensure that the compositor | ||||
|         knows the client has seen the event. | ||||
| 
 | ||||
|         By this point, the state is confirmed, and the next attach should | ||||
|         contain the buffer drawn for the new state value. | ||||
| 
 | ||||
|         The values here need to be the same as the values in the cooresponding | ||||
|         change_state event. | ||||
|       </description> | ||||
|       <arg name="state_type" type="uint" summary="the state to set"/> | ||||
|       <arg name="value" type="uint" summary="the value to change the state to"/> | ||||
|       <arg name="serial" type="uint" summary="a serial to pass to change_state"/> | ||||
|     </request> | ||||
| 
 | ||||
|     <request name="set_minimized"> | ||||
|       <description summary="set the surface state as minimized"> | ||||
| 	Set the surface minimized state. | ||||
| 
 | ||||
| 	Setting one state won't unset another state. | ||||
|       <description summary="minimize the surface"> | ||||
|         Minimize the surface. | ||||
|       </description> | ||||
|     </request> | ||||
| 
 | ||||
|     <event name="focused_set"> | ||||
|       <description summary="surface was focused"> | ||||
| 	The focused_set event is sent when this surface has been | ||||
| 	activated. Window decorations should be updated accordingly. | ||||
|     <event name="activated"> | ||||
|       <description summary="surface was activated"> | ||||
| 	The activated_set event is sent when this surface has been | ||||
| 	activated, which means that the surface has user attention. | ||||
|         Window decorations should be updated accordingly. You should | ||||
|         not use this event for anything but the style of decorations | ||||
|         you display, use wl_keyboard.enter and wl_keyboard.leave for | ||||
|         determining keyboard focus. | ||||
|       </description> | ||||
|     </event> | ||||
| 
 | ||||
|     <event name="focused_unset"> | ||||
|       <description summary="surface was unfocused"> | ||||
| 	The focused_unset event is sent when this surface has been | ||||
| 	deactivated, because another surface has been activated. Window | ||||
| 	decorations should be updated accordingly. | ||||
|     <event name="deactivated"> | ||||
|       <description summary="surface was deactivated"> | ||||
| 	The deactivate event is sent when this surface has been | ||||
|         deactivated, which means that the surface lost user attention. | ||||
|         Window decorations should be updated accordingly. You should | ||||
|         not use this event for anything but the style of decorations | ||||
|         you display, use wl_keyboard.enter and wl_keyboard.leave for | ||||
|         determining keyboard focus. | ||||
|       </description> | ||||
|     </event> | ||||
| 
 | ||||
| @@ -80,6 +80,7 @@ struct weston_launch { | ||||
| 	struct termios terminal_attributes; | ||||
| 	int kb_mode; | ||||
| 	enum vt_state vt_state; | ||||
| 	unsigned vt; | ||||
|  | ||||
|         int drm_fd; | ||||
| }; | ||||
| @@ -164,69 +165,6 @@ setenv_fd(const char *env, int fd) | ||||
| 	setenv(env, buf, 1); | ||||
| } | ||||
|  | ||||
| static int | ||||
| handle_setdrmfd(struct weston_launch *wl, struct msghdr *msg, ssize_t len) | ||||
| { | ||||
|         struct weston_launcher_reply reply; | ||||
| 	struct cmsghdr *cmsg; | ||||
| 	union cmsg_data *data; | ||||
| 	struct stat s; | ||||
|  | ||||
| 	reply.header.opcode = WESTON_LAUNCHER_DRM_SET_FD; | ||||
| 	reply.ret = -1; | ||||
|  | ||||
| 	if (wl->drm_fd != -1) { | ||||
| 		error(0, 0, "DRM FD already set"); | ||||
| 		reply.ret = -EINVAL; | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	cmsg = CMSG_FIRSTHDR(msg); | ||||
| 	if (!cmsg || | ||||
| 	    cmsg->cmsg_level != SOL_SOCKET || | ||||
| 	    cmsg->cmsg_type != SCM_RIGHTS) { | ||||
| 		error(0, 0, "invalid control message"); | ||||
| 		reply.ret = -EINVAL; | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	data = (union cmsg_data *) CMSG_DATA(cmsg); | ||||
| 	if (data->fd < 0) { | ||||
| 		error(0, 0, "missing drm fd in socket request"); | ||||
| 		reply.ret = -EINVAL; | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	if (fstat(data->fd, &s) < 0) { | ||||
| 		reply.ret = -errno; | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	if (major(s.st_rdev) != DRM_MAJOR) { | ||||
| 		fprintf(stderr, "FD is not for DRM\n"); | ||||
| 		reply.ret = -EPERM; | ||||
| 		goto out; | ||||
| 	} | ||||
|  | ||||
| 	wl->drm_fd = data->fd; | ||||
| 	reply.ret = drmSetMaster(data->fd); | ||||
| 	if (reply.ret < 0) | ||||
| 		reply.ret = -errno; | ||||
|  | ||||
| 	if (wl->verbose) | ||||
| 		fprintf(stderr, "mutter-launch: set drm FD, ret: %d, fd: %d\n", | ||||
| 			reply.ret, data->fd); | ||||
|  | ||||
| out: | ||||
| 	do { | ||||
| 		len = send(wl->sock[0], &reply, sizeof reply, 0); | ||||
| 	} while (len < 0 && errno == EINTR); | ||||
| 	if (len < 0) | ||||
| 		return -1; | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int | ||||
| handle_confirm_vt_switch(struct weston_launch *wl, struct msghdr *msg, ssize_t len) | ||||
| { | ||||
| @@ -274,6 +212,7 @@ handle_activate_vt(struct weston_launch *wl, struct msghdr *msg, ssize_t len) | ||||
| { | ||||
|         struct weston_launcher_reply reply; | ||||
| 	struct weston_launcher_activate_vt *message; | ||||
| 	unsigned vt; | ||||
|  | ||||
| 	reply.header.opcode = WESTON_LAUNCHER_ACTIVATE_VT; | ||||
| 	reply.ret = -1; | ||||
| @@ -285,7 +224,13 @@ handle_activate_vt(struct weston_launch *wl, struct msghdr *msg, ssize_t len) | ||||
|  | ||||
| 	message = msg->msg_iov->iov_base; | ||||
|  | ||||
| 	reply.ret = ioctl(wl->tty, VT_ACTIVATE, message->vt); | ||||
| 	/* Negative values mean that we're activating our own VT */ | ||||
| 	if (message->vt > 0) | ||||
| 		vt = message->vt; | ||||
| 	else | ||||
| 		vt = wl->vt; | ||||
|  | ||||
| 	reply.ret = ioctl(wl->tty, VT_ACTIVATE, vt); | ||||
| 	if (reply.ret < 0) | ||||
| 		reply.ret = -errno; | ||||
|  | ||||
| @@ -315,6 +260,7 @@ handle_open(struct weston_launch *wl, struct msghdr *msg, ssize_t len) | ||||
| 	struct iovec iov; | ||||
| 	struct weston_launcher_open *message; | ||||
| 	union cmsg_data *data; | ||||
| 	int dev_major; | ||||
|  | ||||
| 	reply.header.opcode = WESTON_LAUNCHER_OPEN; | ||||
| 	reply.ret = -1; | ||||
| @@ -331,6 +277,22 @@ handle_open(struct weston_launch *wl, struct msghdr *msg, ssize_t len) | ||||
| 		goto err0; | ||||
| 	} | ||||
|  | ||||
| 	dev_major = major(s.st_rdev); | ||||
|  | ||||
| 	if (dev_major != INPUT_MAJOR && | ||||
| 	    dev_major != DRM_MAJOR) { | ||||
| 		fprintf(stderr, "Device %s is not an input or DRM device\n", | ||||
| 			message->path); | ||||
| 		reply.ret = -EPERM; | ||||
| 		goto err0; | ||||
| 	} | ||||
|  | ||||
| 	if (dev_major == DRM_MAJOR && wl->drm_fd != -1) { | ||||
| 		fprintf(stderr, "Already have a DRM device open\n"); | ||||
| 		reply.ret = -EPERM; | ||||
| 		goto err0; | ||||
| 	} | ||||
|  | ||||
| 	fd = open(message->path, message->flags); | ||||
| 	if (fd < 0) { | ||||
| 		fprintf(stderr, "Error opening device %s: %m\n", | ||||
| @@ -339,13 +301,8 @@ handle_open(struct weston_launch *wl, struct msghdr *msg, ssize_t len) | ||||
| 		goto err0; | ||||
| 	} | ||||
|  | ||||
| 	if (major(s.st_rdev) != INPUT_MAJOR) { | ||||
| 		close(fd); | ||||
| 		fd = -1; | ||||
| 		fprintf(stderr, "Device %s is not an input device\n", | ||||
| 			message->path); | ||||
| 		reply.ret = -EPERM; | ||||
| 		goto err0; | ||||
| 	if (dev_major == DRM_MAJOR) { | ||||
| 		wl->drm_fd = fd; | ||||
| 	} | ||||
|  | ||||
| err0: | ||||
| @@ -413,9 +370,6 @@ handle_socket_msg(struct weston_launch *wl) | ||||
| 	case WESTON_LAUNCHER_OPEN: | ||||
| 		ret = handle_open(wl, &msg, len); | ||||
| 		break; | ||||
| 	case WESTON_LAUNCHER_DRM_SET_FD: | ||||
| 		ret = handle_setdrmfd(wl, &msg, len); | ||||
| 		break; | ||||
| 	case WESTON_LAUNCHER_CONFIRM_VT_SWITCH: | ||||
| 		ret = handle_confirm_vt_switch(wl, &msg, len); | ||||
| 		break; | ||||
| @@ -554,7 +508,7 @@ setup_tty(struct weston_launch *wl) | ||||
| 	struct stat buf; | ||||
| 	struct termios raw_attributes; | ||||
| 	struct vt_mode mode = { 0 }; | ||||
| 	char *session, *tty; | ||||
| 	char *session; | ||||
| 	char path[PATH_MAX]; | ||||
| 	int ok; | ||||
|  | ||||
| @@ -562,43 +516,12 @@ setup_tty(struct weston_launch *wl) | ||||
| 	if (ok < 0) | ||||
| 	  error(1, -ok, "could not determine current session"); | ||||
|  | ||||
| 	ok = sd_session_get_tty(session, &tty); | ||||
| 	if (ok == 0) { | ||||
| 		/* Old systemd only has the tty name in the TTY | ||||
| 		   field, new one has the full char device path. | ||||
|  | ||||
| 		   Check what we have and fix it properly. | ||||
| 		*/ | ||||
| 		if (strncmp(tty, "/dev", strlen("/dev")) == 0) { | ||||
| 			strncpy(path, tty, PATH_MAX); | ||||
| 			path[PATH_MAX-1] = 0; | ||||
| 		} else { | ||||
| 			snprintf(path, PATH_MAX, "/dev/%s", tty); | ||||
| 		} | ||||
|  | ||||
| 		wl->tty = open(path, O_RDWR | O_NOCTTY | O_CLOEXEC); | ||||
| 		free(tty); | ||||
| #ifdef HAVE_SD_SESSION_GET_VT | ||||
| 	} else if (ok == -ENOENT) { | ||||
| 		unsigned vt; | ||||
|  | ||||
| 		/* Negative errnos are cool, right? | ||||
| 		   So cool that we can't distinguish "session not found" | ||||
| 		   from "key does not exist in the session file"! | ||||
| 		   Let's assume the latter, as we got the value | ||||
| 		   from sd_pid_get_session()... | ||||
| 		*/ | ||||
|  | ||||
| 		ok = sd_session_get_vt(session, &vt); | ||||
| 	ok = sd_session_get_vt(session, &wl->vt); | ||||
| 	if (ok < 0) | ||||
| 		error(1, -ok, "could not determine current TTY"); | ||||
|  | ||||
| 		snprintf(path, PATH_MAX, "/dev/tty%u", vt); | ||||
| 	snprintf(path, PATH_MAX, "/dev/tty%u", wl->vt); | ||||
| 	wl->tty = open(path, O_RDWR | O_NOCTTY | O_CLOEXEC); | ||||
| 		free(tty); | ||||
| #endif | ||||
| 	} else | ||||
| 		error(1, -ok, "could not determine current TTY"); | ||||
|  | ||||
| 	if (wl->tty < 0) | ||||
| 		error(1, errno, "failed to open tty"); | ||||
|   | ||||
| @@ -31,9 +31,8 @@ enum weston_launcher_message_type { | ||||
|  | ||||
| enum weston_launcher_opcode { | ||||
| 	WESTON_LAUNCHER_OPEN              = (1 << 1 | WESTON_LAUNCHER_REQUEST), | ||||
| 	WESTON_LAUNCHER_DRM_SET_FD        = (2 << 1 | WESTON_LAUNCHER_REQUEST), | ||||
| 	WESTON_LAUNCHER_ACTIVATE_VT       = (3 << 1 | WESTON_LAUNCHER_REQUEST), | ||||
| 	WESTON_LAUNCHER_CONFIRM_VT_SWITCH = (4 << 1 | WESTON_LAUNCHER_REQUEST), | ||||
| 	WESTON_LAUNCHER_ACTIVATE_VT       = (2 << 1 | WESTON_LAUNCHER_REQUEST), | ||||
| 	WESTON_LAUNCHER_CONFIRM_VT_SWITCH = (3 << 1 | WESTON_LAUNCHER_REQUEST), | ||||
| }; | ||||
|  | ||||
| enum weston_launcher_server_opcode { | ||||
| @@ -53,7 +52,7 @@ struct weston_launcher_open { | ||||
|  | ||||
| struct weston_launcher_activate_vt { | ||||
| 	struct weston_launcher_message header; | ||||
| 	int vt; | ||||
| 	signed char vt; | ||||
| }; | ||||
|  | ||||
| struct weston_launcher_reply { | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user