Compare commits
	
		
			14 Commits
		
	
	
		
			3.13.3
			...
			wip/quadbu
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 0f214e24ee | ||
|   | cf67327f0e | ||
|   | 8e5bb17750 | ||
|   | 14d2f8fddc | ||
|   | c249c3f3e5 | ||
|   | db0383d19f | ||
|   | a175b3c947 | ||
|   | 554be56639 | ||
|   | b4de2458ab | ||
|   | 49952bdc69 | ||
|   | b2fd24a098 | ||
|   | fe9d2570d0 | ||
|   | b16ac1ba8c | ||
|   | 330ce648d3 | 
							
								
								
									
										35
									
								
								.cvsignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								.cvsignore
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| Makefile | ||||
| Makefile.in | ||||
| aclocal.m4 | ||||
| confdefs.h | ||||
| config.cache | ||||
| config.guess | ||||
| config.h | ||||
| config.log | ||||
| config.status | ||||
| config.sub | ||||
| configure | ||||
| configure.scan | ||||
| libtool | ||||
| ltconfig | ||||
| ltmain.sh | ||||
| stamp-h | ||||
| stamp-h.in | ||||
| stamp-h1 | ||||
| stamp.h | ||||
| version.h | ||||
| config.h.in | ||||
| install-sh | ||||
| missing | ||||
| mkinstalldirs | ||||
| INSTALL | ||||
| intl | ||||
| ABOUT-NLS | ||||
| COPYING | ||||
| intltool-* | ||||
| metacity.spec | ||||
| autom4te.cache | ||||
| compile | ||||
| depcomp | ||||
| omf.make | ||||
| xmldocs.make | ||||
							
								
								
									
										43
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										43
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -3,7 +3,6 @@ Makefile.in | ||||
| Makefile.in.in | ||||
| aclocal.m4 | ||||
| autom4te.cache | ||||
| build-aux | ||||
| compile | ||||
| config.guess | ||||
| config.h | ||||
| @@ -20,11 +19,11 @@ libtool | ||||
| ltmain.sh | ||||
| missing | ||||
| .deps | ||||
| 50-mutter-navigation.xml | ||||
| 50-mutter-system.xml | ||||
| 50-mutter-windows.xml | ||||
| mutter.desktop | ||||
| mutter-wayland.desktop | ||||
| src/50-mutter-navigation.xml | ||||
| src/50-mutter-system.xml | ||||
| src/50-mutter-windows.xml | ||||
| src/mutter-wm.desktop | ||||
| src/mutter.desktop | ||||
| *.o | ||||
| *.a | ||||
| *.lo | ||||
| @@ -33,6 +32,10 @@ mutter-wayland.desktop | ||||
| *.swp | ||||
| *.gir | ||||
| *.typelib | ||||
| tidy-enum-types.[ch] | ||||
| tidy-marshal.[ch] | ||||
| stamp-tidy-enum-types.h | ||||
| stamp-tidy-marshal.h | ||||
| stamp-h1 | ||||
| *.gmo | ||||
| *.make | ||||
| @@ -41,12 +44,14 @@ stamp-it | ||||
| .intltool-merge-cache | ||||
| POTFILES | ||||
| po/*.pot | ||||
| 50-metacity-desktop-key.xml | ||||
| 50-metacity-key.xml | ||||
| libmutter.pc | ||||
| mutter | ||||
| mutter-theme-viewer | ||||
| mutter.desktop | ||||
| org.gnome.mutter.gschema.valid | ||||
| org.gnome.mutter.gschema.xml | ||||
| org.gnome.mutter.wayland.gschema.valid | ||||
| org.gnome.mutter.wayland.gschema.xml | ||||
| testasyncgetprop | ||||
| testboxes | ||||
| testgradient | ||||
| @@ -61,22 +66,18 @@ test-focus | ||||
| test-gravity | ||||
| test-resizing | ||||
| test-size-hints | ||||
| # We can't say just "wm-tester" here or it will ignore the directory | ||||
| # rather than the binary | ||||
| src/wm-tester/wm-tester | ||||
| INSTALL | ||||
| mkinstalldirs | ||||
| src/mutter-enum-types.[ch] | ||||
| src/stamp-mutter-enum-types.h | ||||
| src/mutter-marshal.[ch] | ||||
| src/stamp-mutter-marshal.h | ||||
| src/meta-dbus-display-config.[ch] | ||||
| src/meta-dbus-xrandr.[ch] | ||||
| src/meta-dbus-idle-monitor.[ch] | ||||
| src/meta-dbus-login1.[ch] | ||||
| src/gtk-shell-protocol.c | ||||
| src/gtk-shell-server-protocol.h | ||||
| src/xdg-shell-protocol.c | ||||
| src/xdg-shell-server-protocol.h | ||||
| src/xserver-protocol.c | ||||
| src/xserver-server-protocol.h | ||||
| src/meta/meta-version.h | ||||
| src/mutter-plugins.pc | ||||
| doc/reference/*.args | ||||
| doc/reference/*.bak | ||||
| doc/reference/*.hierarchy | ||||
| @@ -94,11 +95,3 @@ 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 | ||||
| .dirstamp | ||||
|   | ||||
							
								
								
									
										159
									
								
								COMPLIANCE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								COMPLIANCE
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,159 @@ | ||||
| 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
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										298
									
								
								HACKING
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,298 @@ | ||||
| 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. | ||||
							
								
								
									
										8
									
								
								MAINTAINERS
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								MAINTAINERS
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| Tomas Frydrych | ||||
| Email: tf linux intel com | ||||
| Userid: tomasf | ||||
|  | ||||
| Owen Taylor | ||||
| Email: otaylor redhat com | ||||
| Userid: otaylor | ||||
|  | ||||
							
								
								
									
										43
									
								
								METACITY_MAINTAINERS
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								METACITY_MAINTAINERS
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| 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 | ||||
							
								
								
									
										13
									
								
								Makefile.am
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								Makefile.am
									
									
									
									
									
								
							| @@ -1,13 +1,12 @@ | ||||
|  | ||||
| SUBDIRS = data src po doc | ||||
| SUBDIRS=src po doc | ||||
|  | ||||
| ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} | ||||
|  | ||||
| DISTCLEANFILES = \ | ||||
| 	intltool-extract \ | ||||
| 	intltool-merge \ | ||||
| 	intltool-update \ | ||||
| 	po/stamp-it \ | ||||
| 	po/.intltool-merge-cache | ||||
| EXTRA_DIST = HACKING MAINTAINERS rationales.txt | ||||
|  | ||||
| DISTCLEANFILES = intltool-extract intltool-merge intltool-update po/stamp-it po/.intltool-merge-cache | ||||
|  | ||||
| DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc | ||||
|  | ||||
| ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} | ||||
|   | ||||
							
								
								
									
										226
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										226
									
								
								NEWS
									
									
									
									
									
								
							| @@ -1,82 +1,34 @@ | ||||
| 3.13.3 | ||||
| ====== | ||||
| * Improve behavior of window buttons with compositor menus [Florian; #731058] | ||||
| * Implement touch support on wayland [Carlos; #724442] | ||||
| * Update window shadows [Nikita; #731866] | ||||
| * Keep windows on the preferred output [Florian; #731760] | ||||
| * Misc bug fixes [Jonas, Florian, Jasper; #729601, #730681, #731353, #731332, | ||||
|   #730527, #662962] | ||||
|  | ||||
| Contributors: | ||||
|   Jonas Ådahl, Nikita Churaev, Carlos Garnacho, Florian Müllner, | ||||
|   Jasper St. Pierre, Rico Tzschichholz | ||||
|  | ||||
| 3.13.2 | ||||
| ====== | ||||
| * Add basic HiDPI support on wayland [Adel; #728902] | ||||
| * Fix crash when monitors change during suspend [Giovanni; #725637] | ||||
| * Replace mutter-launch with logind integration [Jasper; #724604] | ||||
| * Move window menu into the compositor [Jasper; #726352] | ||||
| * Fix delayed focus-follows-mouse support [Florian; #730541] | ||||
| * Support fallback app menu in window decorations [Florian; #730752] | ||||
| * Misc. bug fixes and cleanups [Giovanni, Jonas, Jasper; #729732, #729602, | ||||
|   #726714] | ||||
|  | ||||
| Contributors: | ||||
|   Jonas Ådahl, Giovanni Campagna, Adel Gadllah, Florian Müllner, | ||||
|   Jasper St. Pierre, Rico Tzschichholz | ||||
|  | ||||
| Translations: | ||||
|   Pau Iranzo [ca], Daniel Mustieles [es] | ||||
|  | ||||
| 3.13.1 | ||||
| 3.12.1 | ||||
| ====== | ||||
| * Fix opacity values from _NET_WM_WINDOW_OPACITY [Nirbheek; #727874] | ||||
| * Merge wayland branch [Jasper, Giovanni, Robert B., Neil, Adel, Rui, Jonas, | ||||
|   Lionel, Tim, Owen, Florian, Colin W., Cosimo, Ray, Kalev, Pavel, Robert A., | ||||
|   Magdalen, Marek, Matthias, Alban, Seán, Daniel, Stefano, Carlos, Colin G., | ||||
|   Andreas, Alexander, Ryan, Marc-André, Asad, Alberto, Bastien, Hans, | ||||
|   Debarshi, Sindhu, Andika, Rico, Olav] | ||||
| * Don't prevent workspace switches for present_with_time() [Florian; #728018] | ||||
| * Add shortcuts for switching to the last workspace [Elad; #659288] | ||||
| * Make move/resize menu items behave like the keybindings [Jasper; #728617] | ||||
| * Misc. bug fixes and cleanups  [Jasper, Bastien, Florian, Adel; #720631, | ||||
|   #727979, #728423, #728395, #729044] | ||||
| * Misc. cleanups [Jasper; #720631] | ||||
|  | ||||
| Contributors: | ||||
|   Jonas Ådahl, Elad Alfassa, Robert Ancell, Magdalen Berns, Robert Bragg, | ||||
|   Giovanni Campagna, Cosimo Cecchi, Marek Chalupa, Nirbheek Chauhan, | ||||
|   Matthias Clasen, Alban Crequy, Seán de Búrca, Daniel Drake, Jason Ekstrand, | ||||
|   Stefano Facchini, Adel Gadllah, Carlos Garnacho, Colin Guthrie, | ||||
|   Andreas Heider, Lionel Landwerlin, Alexander Larsson, Kalev Lember, | ||||
|   Ryan Lortie, Tim Lunn, Marc-André Lureau, Rui Matos, Asad Mehmood, | ||||
|   Alberto Milone, Florian Müllner, Bastien Nocera, Hans Petter Jansson, | ||||
|   Debarshi Ray, Neil Roberts, Sindhu S, Jasper St. Pierre, Ray Strode, | ||||
|   Andika Triwidada, Rico Tzschichholz, Pavel Vasin, Olav Vitters, | ||||
|   Colin Walters, A. Walton, Owen W. Taylor | ||||
|   Nirbheek Chauhan, Jasper St. Pierre | ||||
|  | ||||
| Translations: | ||||
|   Inaki Larranaga Murgoitio [eu], marablack3 [el], Daniel Mustieles [es], | ||||
|   Fran Diéguez [gl], Yosef Or Boczko [he], Dirgita [id] | ||||
|   Inaki Larranaga Murgoitio [eu], marablack3 [el] | ||||
|  | ||||
| 3.12.0 | ||||
| ====== | ||||
| * Fix grab issue with SSD xwayland windows [Rui; #726123] | ||||
| * Misc. bug fixes [Jasper, Ray, Rui, Florian; #727011] | ||||
|  | ||||
| Contributors: | ||||
|   Rui Matos, Florian Müllner, Jasper St. Pierre, Ray Strode | ||||
| Translations: | ||||
|   Ask H. Larsen [da], Мирослав Николић [sr, sr@latin], Andika Triwidada [id], | ||||
|   Daniel Korostil [uk], Petr Kovar [cs] | ||||
|  | ||||
| 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] | ||||
| * Add minimal handling of touch events [Carlos; #723552] | ||||
| * Misc bug fixes and cleanups [Owen, Adel, Jasper; #723580, #726352] | ||||
|  | ||||
| Contributors: | ||||
|   Giovanni Campagna, Marek Chalupa, Matthias Clasen, Adel Gadllah, Ryan Lortie, | ||||
|   Rui Matos, Florian Müllner, Jasper St. Pierre, Owen W. Taylor | ||||
|   Adel Gadllah, Carlos Garnacho, Rui Matos, Jasper St. Pierre, Owen W. Taylor | ||||
|  | ||||
| Translations: | ||||
|   Changwoo Ryu [ko], Rūdolfs Mazurs [lv], Wylmer Wang [zh_CN], | ||||
|   Chao-Hsiung Liao [zh_HK, zh_TW], Yuri Myasoedov [ru], Tiagosdot [pt], | ||||
|   Claude Paroz [fr], Duarte Loreto [pt], A S Alam [pa] | ||||
|  | ||||
| 3.11.91 | ||||
| ======= | ||||
| @@ -85,104 +37,125 @@ Contributors: | ||||
| * 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] | ||||
| * Misc. bug fixes [Carlos, Giovanni, Florian, Jasper; #724969, #724402, #722266, | ||||
|   #725338] | ||||
|  | ||||
| Contributors: | ||||
|   Giovanni Campagna, Adel Gadllah, Carlos Garnacho, Rui Matos, Florian Müllner, | ||||
|   Jasper St. Pierre, Owen W. Taylor | ||||
|   Jasper St. Pierre | ||||
|  | ||||
| Translations: | ||||
|   Aurimas Černius [lt], Milo Casagrande [it], Balázs Úr [hu], | ||||
|   Matej Urbančič [sl], Enrico Nicoletto [pt_BR], Yosef Or Boczko [he], | ||||
|   Piotr Drąg [pl], Fran Diéguez [gl] | ||||
|  | ||||
| 3.11.90 | ||||
| ======= | ||||
| * Use correct output property for backlight control [Robert; #723606] | ||||
| * 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] | ||||
| * Misc. bug fixes and cleanups [Ryan, Giovanni, Jasper; #722530, #724257, | ||||
|   #724258, #724364, #720631, #707851, #707897] | ||||
|  | ||||
| Contributors: | ||||
|   Giovanni Campagna, Marek Chalupa, Stefano Facchini, Adel Gadllah, | ||||
|   Robert Ancell, Giovanni Campagna, Stefano Facchini, Adel Gadllah, | ||||
|   Ryan Lortie, Florian Müllner, Jasper St. Pierre, Rico Tzschichholz | ||||
|  | ||||
| Translations: | ||||
|   Shankar Prasad [kn], Khaled Hosny [ar], Marek Černocký [cs], | ||||
|   Kjartan Maraas [nb], Daniel Korostil [uk] | ||||
|  | ||||
| 3.11.5 | ||||
| ====== | ||||
| * Fix CSD titlebars being placed off-screen [Jasper; #719772] | ||||
| * Add support for subsurfaces [Jonas; #705502] | ||||
| * Expose MetaWindow:skip-taskbar property [Florian; #723307] | ||||
| * Fix legacy tray icons showing up blank [Adel; #721596] | ||||
| * Fix configuration of cloned monitors [Adel; #710610] | ||||
| * Misc bug fixes and cleanups [Jasper, Adel, Marek, Jonas; #720631, #723468, | ||||
|   #720818, #723563, #723564] | ||||
| * Misc bug fixes and cleanups [Jasper, Adel, Jonas; #720631, #723468, #723563] | ||||
|  | ||||
| Contributors: | ||||
|   Jonas Ådahl, Marek Ch, Adel Gadllah, Florian Müllner, Jasper St. Pierre | ||||
|  | ||||
| Translations: | ||||
|   Rafael Ferreira [pt_BR], Enrico Nicoletto [pt_BR], Fran Diéguez [gl], | ||||
|   Chao-Hsiung Liao [zh_HK, zh_TW] | ||||
|  | ||||
| 3.11.4 | ||||
| ====== | ||||
| * Don't leave focus on windows that are being unmanaged [Owen; #711618] | ||||
| * Reduce server grabs [Daniel Drake; #721345, #721709] | ||||
| * Improve heuristic to determine display output name [Cosimo Cecchi; #721674] | ||||
| * Atomically unmaximize both directions [Jasper; #722108] | ||||
| * Misc bug fixes [Debarshi, Andika, Florian; #721517, #721674, #722347] | ||||
| * Misc bug fixes [Debarshi, Andika; #721517, #721674] | ||||
|  | ||||
| Contributors: | ||||
|   Cosimo Cecchi, Daniel Drake, Florian Müllner, Debarshi Ray, Jasper St. Pierre, | ||||
|   Cosimo Cecchi, Daniel Drake, Debarshi Ray, Jasper St. Pierre, | ||||
|   Andika Triwidada, Owen W. Taylor | ||||
|  | ||||
| Translations: | ||||
|   Rafael Ferreira [pt_BR], Dimitris Spingos [el], Daniel Mustieles [es], | ||||
|   Milo Casagrande [it], Yosef Or Boczko [he] | ||||
|  | ||||
| 3.11.3 | ||||
| ====== | ||||
| * Fix focus issues with external OSKs[Jasper; #715030] | ||||
| * xrandr: Use "hotplug_mode_update" property [Marc-André; #711216] | ||||
| * Fix position of attached dialogs for CSD windows [Giovanni, Owen; #707194] | ||||
| * Fix focus issues with external OSKs [Jasper; #715030] | ||||
| * Add a MetaCullable interface [Jasper; #714706] | ||||
| * Fix window keybindings [Rui; #719724] | ||||
| * Fix settings keyboard/pointer focus for new clients [Rui; #719725] | ||||
| * Fix window group paint volume [Owen; #719669] | ||||
| * Fix frame extents problems [Owen; #714707] | ||||
| * Add shortcut to move windows between monitors [Florian; #671054] | ||||
| * Fix problems with focus tracking [Owen; #720558] | ||||
| * Misc. bug fixes and cleanups: [Rui, Colin, Lionel, Jasper, Owen; #712833, | ||||
|   #719557, #719695, #719833, #678989, #720417, #720630] | ||||
| * Misc. bug fixes and cleanups [Rui, Jasper, Owen; #712833, #678989, #720106, | ||||
|   #720417, #720630] | ||||
|  | ||||
| Contributors: | ||||
|   Lionel Landwerlin, Rui Matos, Alberto Milone, Florian Müllner, | ||||
|   Jasper St. Pierre, Rico Tzschichholz, Owen W. Taylor, Colin Walters | ||||
|   Robert Bragg, Giovanni Campagna, Marc-André Lureau, Rui Matos, Alberto Milone, | ||||
|   Florian Müllner, Sindhu S, Jasper St. Pierre, Rico Tzschichholz, | ||||
|   Owen W. Taylor | ||||
|  | ||||
| Translations: | ||||
|   甘露(Gan  Lu) [zh_CN], Khaled Hosny [ar] | ||||
|  | ||||
| 3.11.2 | ||||
| ====== | ||||
| * Support setting a NULL opaque region [Andreas; #711518] | ||||
| * Sync keymap from X to wayland [Giovanni; #707446] | ||||
| * Implement support for subsurfaces [Jonas; #705502] | ||||
| * Don't focus the no-focus-window for globally active windows [Jasper; #710296] | ||||
| * Support "hotplug_mode_update" property [Marc-André; #711216] | ||||
| * Fix resize operations using mouse-button-modifier [Lionel; #710251] | ||||
| * Fix position of attached modals for CSD windows [Giovanni, Owen; #707194] | ||||
| * Misc. bug fixes [Rui, Jasper, Neil, Florian; #712247, #711731] | ||||
| * Misc. fixes and cleanups [Jasper, Rico, Florian; #711731] | ||||
|  | ||||
| Contributors: | ||||
|   Giovanni Campagna, Andreas Heider, Lionel Landwerlin, Marc-André Lureau, | ||||
|   Rui Matos, Florian Müllner, Neil Roberts, Sindhu S, Jasper St. Pierre, | ||||
|   Rico Tzschichholz, Owen W. Taylor, Jonas Ådahl | ||||
|   Lionel Landwerlin, Florian Müllner, Jasper St. Pierre, Rico Tzschichholz | ||||
|  | ||||
| 3.11.1 | ||||
| ====== | ||||
| * Fix tile previews getting stuck on right click during drags [Lionel; #704759] | ||||
| * Don't require at least one output device to be connected [Giovanni; #709009] | ||||
| * Name the guard window [Andrew; #710346] | ||||
| * Use new UPower API [Bastien] | ||||
| * Set hot spot when cursor set from wl_buffer [Jonas; #709593] | ||||
| * Expose min-backlight-step [Asad; #710380] | ||||
| * Misc. bug fixes and cleanups [Jasper, Olav, Magdalen; #709776] | ||||
| * Don't focus the no-focus-window for globally active windows [Jasper; #710296] | ||||
| * Misc. fixes and cleanups [Jasper, Rico, Olav, Magdalen; #709776] | ||||
|  | ||||
| Contributors: | ||||
|   Magdalen Berns, Lionel Landwerlin, Asad Mehmood, Bastien Nocera, | ||||
|   Jasper St. Pierre, Olav Vitters, Jonas Ådahl | ||||
|   Magdalen Berns, Giovanni Campagna, Asad Mehmood, Bastien Nocera, | ||||
|   Jasper St. Pierre, Rico Tzschichholz, Olav Vitters, Andrew Walton | ||||
|  | ||||
| Translations: | ||||
|   Reinout van Schouwen [nl] | ||||
|  | ||||
| 3.10.1 | ||||
| ====== | ||||
| * Don't apply fullscreen workarounds to CSD windows [Giovanni; #708718] | ||||
| * Fix hangs during DND operations [Adel; #709340] | ||||
| * Misc bug fixes [Dan, Giovanni, Jasper; #708813, #708420] | ||||
| * Use nearest-pixel interpolation when possible [Hans; #708389] | ||||
| * Fix tile previews getting stuck on right click during drags [Lionel; #704759] | ||||
| * Misc bug fixes [Giovanni, Jasper; #708420] | ||||
|  | ||||
| Contributors: | ||||
|   Giovanni Campagna, Adel Gadllah, Dan Horák, Hans Petter Jansson, | ||||
|   Giovanni Campagna, Adel Gadllah, Lionel Landwerlin, Hans Petter Jansson, | ||||
|   Jasper St. Pierre | ||||
|  | ||||
| Translations: | ||||
|   Khaled Hosny [ar], Reinout van Schouwen [nl], Carles Ferrando [ca@valencia] | ||||
|  | ||||
| 3.10.0.1 | ||||
| ======== | ||||
| * Fix bug when a window changed size twice in a single frame - this | ||||
| @@ -193,32 +166,24 @@ Contributors: | ||||
|  | ||||
| 3.10.0 | ||||
| ====== | ||||
| * Update dependencies [Giovanni; #708210] | ||||
|  | ||||
| Translations: | ||||
|   Ask H. Larsen [da], Gabor Kelemen [hu], Duarte Loreto [pt], | ||||
|   Yosef Or Boczko [he] | ||||
|  | ||||
| 3.9.92 | ||||
| ====== | ||||
| * Constrain the pointer position onto visible monitors [Giovanni; #706655] | ||||
| * Fix keyboard state handling in face of event compression [Giovanni; #706963] | ||||
| * Extend the MetaCursorTracker API with query pointer and cursor visibility [Giovanni; #707474] | ||||
| * Be stricter in checking and exposing the wayland protocol version [#707851] | ||||
| * Don't require plugins to pass event to Clutter [Giovanni; #707482] | ||||
| * Move the --wayland option from the binary to the library [Giovanni; #707897] | ||||
| * Implement running from gnome-session (environment variable setting, process group | ||||
|   handling, Clutter backend variables) [Giovanni; #706421] | ||||
| * Add support for more cursor types [Giovanni; #707919] | ||||
| * Drop man pages for removed utilities [Kalev; #706579] | ||||
| * Implement monitor configuration on KMS [Giovanni; #706308] | ||||
| * Implement HW cursors [Giovanni; #707573] | ||||
| * Implement minimal support for resizing and maximizing wayland clients [Giovanni; #707401] | ||||
| * Implement transient hints for wayland clients [Giovanni; #707401] | ||||
| * Implement popup menu surfaces and grabs [Giovanni; #707863] | ||||
| * Immediately fire idle watches that are already expired [Giovanni; #707302] | ||||
| * Don't create a dummy texture for the texture pipeline template [Neil; #707458] | ||||
| * Remove holes generated by disabling the laptop lid [Giovanni; #707473] | ||||
| * Misc bug fixes [Giovanni, Pavel, Adel; #707649, #706124, #707584, #707851, #707929, | ||||
|   #708070] | ||||
| * https://bugzilla.gnome.org/show_bug.cgi?id=707474 [Giovanni; #707474] | ||||
| * Don't require plugins to pass event to Clutter [Giovanni; #707482] | ||||
| * Add support for more cursor types [Giovanni; #707919] | ||||
| * Immediately fire idle watches that are already expired [Giovanni; #707302] | ||||
| * Misc bug fixes [Giovanni, Colin, Pavel; #707649, #707563, #708070] | ||||
|  | ||||
| Contributors: | ||||
|   Adel Gadllah, Giovanni Campagna, Kalev Lember, Pavel Vasin | ||||
|   Giovanni Campagna, Adel Gadllah, Colin Guthrie, Neil Roberts, | ||||
|   Jasper St. Pierre, Ray Strode, Pavel Vasin | ||||
|  | ||||
| Translations: | ||||
|   Мирослав Николић po/sr, sr@latin.po, Мирослав Николић [sr, sr@latin], | ||||
| @@ -231,30 +196,19 @@ Translations: | ||||
| 3.9.91 | ||||
| ====== | ||||
| * Drop man pages for removed utilities [Kalev; #706579] | ||||
| * Add support for idle tracking [Giovanni, Cosimo; #706005, #707250] | ||||
| * Add support for idle tracking [Giovanni; #706005] | ||||
| * Skip CRTC reconfigurations that have no effect [Giovanni; #706672] | ||||
| * Ignore skip-taskbar hints on parentless dialogs [Giovanni; #673399] | ||||
| * Don't save pixbuf data in user data [Tim; #706777] | ||||
| * Don't queue redraws for obscured regions [Adel; #703332] | ||||
| * Suppor the opaque region hints for wayland clients [Jasper; #707019] | ||||
| * Turn blending off when drawing entirely opaque regions [Jasper; #707019] | ||||
| * Turn blending off when drawing entirely opaque regions [Jasper; #706930] | ||||
| * Check event timestamps before reconfiguring [Giovanni; #706735] | ||||
| * Merge the DBus API for display configuration in the wayland branch [Giovanni] | ||||
| * Install an X IO error handler for XWayland [Giovanni; #706962] | ||||
| * Use the clutter xkbcommon integration for the wayland keyboard [Giovanni; #705862] | ||||
| * Add a setuid helper for running on KMS+evdev [Giovanni, Colin; #705861] | ||||
| * Add keybindings for switching VT [Giovanni; #705861] | ||||
| * Implement plugin modality when running as a wayland compositor [Giovanni; #705917] | ||||
| * Add support for the application menu for wayland clients [Giovanni; #707128] | ||||
| * Several Coverity spotted fixes [Jasper] | ||||
| * Don't create a dummy texture for the texture template [Neil; #707458] | ||||
| * Use a more conservative paint volume for obscured windows [Adel] | ||||
| * Misc bug fixes [Giovanni, Colin, Seán, Jasper, Cosimo; #706582, #706598, | ||||
|   #706787, #706729, #706825, #707081, #707090, #707267, #706982, #706289] | ||||
|   #706787, #706729, #706825, #707081, #707090, #707250, #707267] | ||||
|  | ||||
| Contributors: | ||||
|   Giovanni Campagna, Cosimo Cecchi, Adel Gadllah, Colin Guthrie, Kalev Lember, | ||||
|   Tim Lunn, Jasper St. Pierre, Neil Roberts, Rico Tzschichholz, Seán de Búrca | ||||
|   Tim Lunn, Jasper St. Pierre, Rico Tzschichholz, Seán de Búrca | ||||
|  | ||||
| Translations: | ||||
|   Piotr Drąg [pl], Alexandre Franke [fr], Kjartan Maraas [nb], | ||||
| @@ -263,8 +217,6 @@ Translations: | ||||
|  | ||||
| 3.9.90 | ||||
| ====== | ||||
| * First release from the wayland branch, includes basic support for running | ||||
|   as a wayland compositor [Robert, Neil, Giovanni] | ||||
| * Add support for _GTK_FRAME_EXTENTS [Jasper; #705766] | ||||
| * Fix quick consecutive <super> presses breaking keyboard input [Alban; #666101] | ||||
| * Work towards running as wayland compositor [Giovanni] | ||||
| @@ -279,8 +231,8 @@ Translations: | ||||
|  | ||||
| Contributors: | ||||
|   Robert Bragg, Giovanni Campagna, Alban Crequy, Adel Gadllah, | ||||
|   Alexander Larsson, Florian Müllner, Jasper St. Pierre, Neil Roberts, | ||||
|   Rico Tzschichholz, Colin Walters | ||||
|   Alexander Larsson, Florian Müllner, Jasper St. Pierre, Rico Tzschichholz, | ||||
|   Colin Walters | ||||
|  | ||||
| Translations: | ||||
|   Jiro Matsuzawa [ja], Kjartan Maraas [nb], Matej Urbančič [sl], | ||||
|   | ||||
							
								
								
									
										416
									
								
								README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										416
									
								
								README
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,416 @@ | ||||
| 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.11 | ||||
| REQUIRED_AUTOMAKE_VERSION=1.10 | ||||
|  | ||||
| (test -f $srcdir/configure.ac \ | ||||
|   && test -d $srcdir/src) || { | ||||
|   | ||||
							
								
								
									
										139
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										139
									
								
								configure.ac
									
									
									
									
									
								
							| @@ -1,8 +1,9 @@ | ||||
| AC_PREREQ(2.62) | ||||
| AC_PREREQ(2.50) | ||||
| AC_CONFIG_MACRO_DIR([m4]) | ||||
|  | ||||
| m4_define([mutter_major_version], [3]) | ||||
| m4_define([mutter_minor_version], [13]) | ||||
| m4_define([mutter_micro_version], [3]) | ||||
| m4_define([mutter_minor_version], [12]) | ||||
| m4_define([mutter_micro_version], [1]) | ||||
|  | ||||
| m4_define([mutter_version], | ||||
|           [mutter_major_version.mutter_minor_version.mutter_micro_version]) | ||||
| @@ -13,11 +14,10 @@ AC_INIT([mutter], [mutter_version], | ||||
|         [http://bugzilla.gnome.org/enter_bug.cgi?product=mutter]) | ||||
|  | ||||
| AC_CONFIG_MACRO_DIR([m4]) | ||||
| AC_CONFIG_AUX_DIR([build-aux]) | ||||
| AC_CONFIG_SRCDIR(src/core/display.c) | ||||
| AC_CONFIG_HEADERS(config.h) | ||||
|  | ||||
| AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz tar-ustar subdir-objects]) | ||||
| AM_INIT_AUTOMAKE([1.11 no-dist-gzip dist-xz tar-ustar]) | ||||
| m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],) | ||||
| AM_MAINTAINER_MODE([enable]) | ||||
|  | ||||
| @@ -40,14 +40,12 @@ GETTEXT_PACKAGE=mutter | ||||
| AC_SUBST(GETTEXT_PACKAGE) | ||||
| AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[Name of default gettext domain]) | ||||
|  | ||||
| LT_PREREQ([2.2.6]) | ||||
| LT_INIT([disable-static]) | ||||
| IT_PROG_INTLTOOL([0.41]) | ||||
| IT_PROG_INTLTOOL([0.34.90]) | ||||
| AC_PROG_CC | ||||
| AC_PROG_CC_C_O | ||||
| AC_PROG_INSTALL | ||||
| AC_ISC_POSIX | ||||
| AC_HEADER_STDC | ||||
| PKG_PROG_PKG_CONFIG([0.21]) | ||||
| AC_LIBTOOL_WIN32_DLL | ||||
| AM_PROG_LIBTOOL | ||||
|  | ||||
| # Sets GLIB_GENMARSHAL and GLIB_MKENUMS | ||||
| AM_PATH_GLIB_2_0() | ||||
| @@ -72,18 +70,13 @@ CLUTTER_PACKAGE=clutter-1.0 | ||||
|  | ||||
| MUTTER_PC_MODULES=" | ||||
|    gtk+-3.0 >= 3.9.11 | ||||
|    gio-2.0 >= 2.25.10 | ||||
|    gio-unix-2.0 >= 2.25.10 | ||||
|    pango >= 1.2.0 | ||||
|    cairo >= 1.10.0 | ||||
|    gsettings-desktop-schemas >= 3.7.3 | ||||
|    xcomposite >= 0.2 xfixes xext xdamage xi >= 1.6.0 | ||||
|    xcursor | ||||
|    $CLUTTER_PACKAGE >= 1.17.5 | ||||
|    clutter-wayland-1.0 | ||||
|    clutter-wayland-compositor-1.0 | ||||
|    clutter-egl-1.0 | ||||
|    xcomposite >= 0.2 xfixes xrender xdamage xi >= 1.6.0 | ||||
|    $CLUTTER_PACKAGE >= 1.19.5 | ||||
|    cogl-1.0 >= 1.17.1 | ||||
|    wayland-server >= 1.4.93 | ||||
|    upower-glib >= 0.99.0 | ||||
|    gnome-desktop-3.0 | ||||
| " | ||||
| @@ -114,12 +107,21 @@ AC_ARG_WITH(libcanberra, | ||||
|                  [disable the use of libcanberra for playing sounds]),, | ||||
|   with_libcanberra=auto) | ||||
|  | ||||
| AC_ARG_WITH([xwayland-path], | ||||
|             [AS_HELP_STRING([--with-xwayland-path], [Absolute path for an X Wayland server])], | ||||
|             [XWAYLAND_PATH="$withval"], | ||||
|             [XWAYLAND_PATH="$bindir/Xwayland"]) | ||||
| AC_ARG_ENABLE(xsync, | ||||
|   AC_HELP_STRING([--disable-xsync], | ||||
|                  [disable mutter's use of the XSync extension]),, | ||||
|   enable_xsync=auto) | ||||
|  | ||||
| AC_ARG_ENABLE(shape, | ||||
|   AC_HELP_STRING([--disable-shape], | ||||
|                  [disable mutter's use of the shaped window extension]),, | ||||
|   enable_shape=auto) | ||||
|  | ||||
| AM_GLIB_GNU_GETTEXT | ||||
|  | ||||
| ## here we get the flags we'll actually use | ||||
| # GRegex requires Glib-2.14.0 | ||||
| PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.14.0) | ||||
|  | ||||
| # Unconditionally use this dir to avoid a circular dep with gnomecc | ||||
| GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings" | ||||
| @@ -184,20 +186,22 @@ if test x$found_introspection != xno; then | ||||
|   AC_SUBST(META_GIR) | ||||
| fi | ||||
|  | ||||
| AC_PATH_PROG([WAYLAND_SCANNER],[wayland-scanner],[no]) | ||||
| AS_IF([test "x$WAYLAND_SCANNER" = "xno"], | ||||
|   AC_MSG_ERROR([Could not find wayland-scanner in your PATH, required for parsing wayland extension protocols])) | ||||
| AC_SUBST([WAYLAND_SCANNER]) | ||||
| AC_SUBST(XWAYLAND_PATH) | ||||
| AC_MSG_CHECKING([Xcursor]) | ||||
| if $PKG_CONFIG xcursor; then | ||||
|      have_xcursor=yes | ||||
|   else | ||||
|      have_xcursor=no | ||||
|   fi | ||||
|   AC_MSG_RESULT($have_xcursor) | ||||
|  | ||||
| if test x$have_xcursor = xyes; then | ||||
|   echo "Building with Xcursor" | ||||
|   MUTTER_PC_MODULES="$MUTTER_PC_MODULES xcursor" | ||||
|   AC_DEFINE(HAVE_XCURSOR, , [Building with Xcursor support]) | ||||
| fi | ||||
|  | ||||
| PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES) | ||||
|  | ||||
| PKG_CHECK_MODULES(MUTTER_NATIVE_BACKEND, [libdrm libsystemd], [have_native_backend=yes], [have_native_backend=no]) | ||||
| if test $have_native_backend = yes; then | ||||
|    AC_DEFINE([HAVE_NATIVE_BACKEND],[1],[Define if you want to enable the native (KMS) backend based on systemd]) | ||||
| fi | ||||
| AM_CONDITIONAL([HAVE_NATIVE_BACKEND],[test $have_native_backend = yes]) | ||||
|  | ||||
| PKG_CHECK_EXISTS([xi >= 1.6.99.1], | ||||
|                  AC_DEFINE([HAVE_XI23],[1],[Define if you have support for XInput 2.3 or greater])) | ||||
|  | ||||
| @@ -234,6 +238,28 @@ if test x$have_xinerama = xno; then | ||||
|    AC_MSG_ERROR([Xinerama extension was not found]) | ||||
| fi | ||||
|  | ||||
| SHAPE_LIBS= | ||||
| found_shape=no | ||||
| AC_CHECK_LIB(Xext, XShapeQueryExtension, | ||||
|                [AC_CHECK_HEADER(X11/extensions/shape.h, | ||||
|                                 SHAPE_LIBS=-lXext found_shape=yes)], | ||||
|                , $ALL_X_LIBS) | ||||
|  | ||||
| if test x$enable_shape = xno; then | ||||
|    found_shape=no | ||||
| fi | ||||
|  | ||||
| if test x$enable_shape = xyes; then | ||||
|    if test "$found_shape" = "no"; then | ||||
|       AC_MSG_ERROR([--enable-shape forced and Shape not found]) | ||||
|       exit 1 | ||||
|    fi | ||||
| fi | ||||
|  | ||||
| if test "x$found_shape" = "xyes"; then | ||||
|    AC_DEFINE(HAVE_SHAPE, , [Have the shape extension library]) | ||||
| fi | ||||
|  | ||||
| found_xkb=no | ||||
| AC_CHECK_LIB(X11, XkbQueryExtension, | ||||
|                [AC_CHECK_HEADER(X11/XKBlib.h, | ||||
| @@ -251,13 +277,37 @@ AC_CHECK_LIB(Xrandr, XRRUpdateConfiguration, | ||||
|                [AC_CHECK_HEADER(X11/extensions/Xrandr.h, | ||||
|                                 RANDR_LIBS=-lXrandr found_randr=yes,, | ||||
| 				[#include <X11/Xlib.h>])], | ||||
|                , -lXext $ALL_X_LIBS) | ||||
|                , -lXrender -lXext $ALL_X_LIBS) | ||||
|  | ||||
| if test "x$found_randr" = "xyes"; then | ||||
|    AC_DEFINE(HAVE_RANDR, , [Have the Xrandr extension library]) | ||||
| fi | ||||
|  | ||||
| MUTTER_LIBS="$MUTTER_LIBS $RANDR_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm" | ||||
| XSYNC_LIBS= | ||||
| found_xsync=no | ||||
| AC_CHECK_LIB(Xext, XSyncQueryExtension, | ||||
|                [AC_CHECK_HEADER(X11/extensions/sync.h, | ||||
|                                 found_xsync=yes,, | ||||
| 				[#include <X11/Xlib.h>])], | ||||
|                , $ALL_X_LIBS) | ||||
|  | ||||
| if test x$enable_xsync = xno; then | ||||
|    found_xsync=no | ||||
| fi | ||||
|  | ||||
| if test x$enable_xsync = xyes; then | ||||
|    if test "$found_xsync" = "no"; then | ||||
|       AC_MSG_ERROR([--enable-xsync forced and XSync not found]) | ||||
|       exit 1 | ||||
|    fi | ||||
| fi | ||||
|  | ||||
| if test "x$found_xsync" = "xyes"; then | ||||
|    XSYNC_LIBS=-lXext | ||||
|    AC_DEFINE(HAVE_XSYNC, , [Have the Xsync extension library]) | ||||
| fi | ||||
|  | ||||
| MUTTER_LIBS="$MUTTER_LIBS $XSYNC_LIBS $RANDR_LIBS $SHAPE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm" | ||||
|  | ||||
| found_sm=no | ||||
| case "$MUTTER_LIBS" in | ||||
| @@ -289,6 +339,17 @@ fi | ||||
|  | ||||
| AM_CONDITIONAL(HAVE_SM, test "$found_sm" = "yes") | ||||
|  | ||||
| HOST_ALIAS=$host_alias | ||||
| AC_SUBST(HOST_ALIAS) | ||||
|  | ||||
| AC_PATH_PROG(GDK_PIXBUF_CSOURCE, gdk-pixbuf-csource, no) | ||||
|  | ||||
| if test x"$GDK_PIXBUF_CSOURCE" = xno; then | ||||
|   AC_MSG_ERROR([gdk-pixbuf-csource executable not found in your path - should be installed with GTK]) | ||||
| fi | ||||
|  | ||||
| AC_SUBST(GDK_PIXBUF_CSOURCE) | ||||
|  | ||||
| AC_PATH_PROG(ZENITY, zenity, no) | ||||
| if test x"$ZENITY" = xno; then | ||||
|   AC_MSG_ERROR([zenity not found in your path - needed for dialogs]) | ||||
| @@ -371,15 +432,14 @@ changequote([,])dnl | ||||
|  | ||||
| AC_CONFIG_FILES([ | ||||
| Makefile | ||||
| data/Makefile | ||||
| doc/Makefile | ||||
| doc/man/Makefile | ||||
| doc/reference/Makefile | ||||
| doc/reference/meta-docs.sgml | ||||
| src/Makefile | ||||
| src/libmutter.pc | ||||
| src/mutter-plugins.pc | ||||
| src/compositor/plugins/Makefile | ||||
| src/meta/meta-version.h | ||||
| po/Makefile.in | ||||
| ]) | ||||
|  | ||||
| @@ -405,6 +465,9 @@ mutter-$VERSION | ||||
| 	libcanberra:              ${have_libcanberra} | ||||
| 	Introspection:            ${found_introspection} | ||||
| 	Session management:       ${found_sm} | ||||
| 	Shape extension:          ${found_shape} | ||||
| 	Xsync:                    ${found_xsync} | ||||
| 	Xcursor:                  ${have_xcursor} | ||||
| " | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -1,36 +0,0 @@ | ||||
| desktopfiles_in_files = \ | ||||
| 	mutter.desktop.in \ | ||||
| 	mutter-wayland.desktop.in | ||||
| desktopfilesdir = $(datadir)/applications | ||||
| desktopfiles_DATA = $(desktopfiles_in_files:.desktop.in=.desktop) | ||||
|  | ||||
| @INTLTOOL_DESKTOP_RULE@ | ||||
|  | ||||
| xml_in_files = \ | ||||
|         50-mutter-navigation.xml.in \ | ||||
|         50-mutter-system.xml.in \ | ||||
|         50-mutter-windows.xml.in | ||||
| xmldir = $(GNOME_KEYBINDINGS_KEYSDIR) | ||||
| xml_DATA = $(xml_in_files:.xml.in=.xml) | ||||
|  | ||||
| gschema_in_files = \ | ||||
| 	org.gnome.mutter.gschema.xml.in	\ | ||||
| 	org.gnome.mutter.wayland.gschema.xml.in | ||||
| gsettings_SCHEMAS = $(gschema_in_files:.xml.in=.xml) | ||||
|  | ||||
| @INTLTOOL_XML_NOMERGE_RULE@ | ||||
| @GSETTINGS_RULES@ | ||||
|  | ||||
| convertdir = $(datadir)/GConf/gsettings | ||||
| convert_DATA = mutter-schemas.convert | ||||
|  | ||||
| CLEANFILES = \ | ||||
| 	$(desktopfiles_DATA) \ | ||||
| 	$(gsettings_SCHEMAS) \ | ||||
| 	$(xml_DATA) | ||||
|  | ||||
| EXTRA_DIST = \ | ||||
| 	$(convert_DATA) \ | ||||
| 	$(desktopfiles_in_files) \ | ||||
| 	$(gschema_in_files) \ | ||||
| 	$(xml_in_files) | ||||
| @@ -1,33 +0,0 @@ | ||||
| <schemalist> | ||||
|   <schema id="org.gnome.mutter.wayland.keybindings" path="/org/gnome/mutter/wayland/keybindings/" | ||||
| 	  gettext-domain="@GETTEXT_DOMAIN@"> | ||||
|     <key name="switch-to-session-1" type="as"> | ||||
|       <default><![CDATA[['<Primary><Alt>F1']]]></default> | ||||
|       <_summary>Switch to VT 1</_summary> | ||||
|     </key> | ||||
|     <key name="switch-to-session-2" type="as"> | ||||
|       <default><![CDATA[['<Primary><Alt>F2']]]></default> | ||||
|       <_summary>Switch to VT 2</_summary> | ||||
|     </key> | ||||
|     <key name="switch-to-session-3" type="as"> | ||||
|       <default><![CDATA[['<Primary><Alt>F3']]]></default> | ||||
|       <_summary>Switch to VT 3</_summary> | ||||
|     </key> | ||||
|     <key name="switch-to-session-4" type="as"> | ||||
|       <default><![CDATA[['<Primary><Alt>F4']]]></default> | ||||
|       <_summary>Switch to VT 4</_summary> | ||||
|     </key> | ||||
|     <key name="switch-to-session-5" type="as"> | ||||
|       <default><![CDATA[['<Primary><Alt>F5']]]></default> | ||||
|       <_summary>Switch to VT 5</_summary> | ||||
|     </key> | ||||
|     <key name="switch-to-session-6" type="as"> | ||||
|       <default><![CDATA[['<Primary><Alt>F6']]]></default> | ||||
|       <_summary>Switch to VT 6</_summary> | ||||
|     </key> | ||||
|     <key name="switch-to-session-7" type="as"> | ||||
|       <default><![CDATA[['<Primary><Alt>F7']]]></default> | ||||
|       <_summary>Switch to VT 7</_summary> | ||||
|     </key> | ||||
|   </schema> | ||||
| </schemalist> | ||||
| @@ -1,4 +1,4 @@ | ||||
| SUBDIRS = man reference | ||||
|  | ||||
| EXTRA_DIST=theme-format.txt dialogs.txt code-overview.txt \ | ||||
| 	how-to-get-focus-right.txt rationales.txt | ||||
| 	how-to-get-focus-right.txt | ||||
|   | ||||
| @@ -79,6 +79,8 @@ IGNORE_HFILES= \ | ||||
| 	iconcache.h \ | ||||
| 	inlinepixbufs.h \ | ||||
| 	keybindings-private.h \ | ||||
| 	menu.h \ | ||||
| 	metaaccellabel.h \ | ||||
| 	meta-background-actor-private.h \ | ||||
| 	meta-background-group-private.h \ | ||||
| 	meta-module.h \ | ||||
|   | ||||
| @@ -555,7 +555,7 @@ meta_window_is_monitor_sized | ||||
| meta_window_is_override_redirect | ||||
| meta_window_is_skip_taskbar | ||||
| meta_window_get_rect | ||||
| meta_window_get_buffer_rect | ||||
| meta_window_get_input_rect | ||||
| meta_window_get_frame_rect | ||||
| meta_window_get_outer_rect | ||||
| meta_window_client_rect_to_frame_rect | ||||
|   | ||||
| @@ -21,6 +21,7 @@ environment.</description> | ||||
|   --> | ||||
|   <mailing-list rdf:resource="http://mail.gnome.org/mailman/listinfo/gnome-shell-list" /> | ||||
|   <download-page rdf:resource="http://download.gnome.org/sources/mutter/" /> | ||||
|   <download-page rdf:resource="http://download.gnome.org/sources/mutter-wayland/" /> | ||||
|   <bug-database rdf:resource="http://bugzilla.gnome.org/browse.cgi?product=mutter" /> | ||||
|  | ||||
|   <category rdf:resource="http://api.gnome.org/doap-extensions#desktop" /> | ||||
|   | ||||
| @@ -1,12 +1,8 @@ | ||||
| # List of source files containing translatable strings. | ||||
| # Please keep this file sorted alphabetically. | ||||
| data/50-mutter-navigation.xml.in | ||||
| data/50-mutter-system.xml.in | ||||
| data/50-mutter-windows.xml.in | ||||
| data/mutter.desktop.in | ||||
| data/org.gnome.mutter.gschema.xml.in | ||||
| data/org.gnome.mutter.wayland.gschema.xml.in | ||||
| src/backends/meta-monitor-manager.c | ||||
| src/50-mutter-navigation.xml.in | ||||
| src/50-mutter-system.xml.in | ||||
| src/50-mutter-windows.xml.in | ||||
| src/compositor/compositor.c | ||||
| src/compositor/meta-background.c | ||||
| src/core/bell.c | ||||
| @@ -16,15 +12,21 @@ src/core/display.c | ||||
| src/core/errors.c | ||||
| src/core/keybindings.c | ||||
| src/core/main.c | ||||
| src/core/monitor.c | ||||
| src/core/mutter.c | ||||
| src/core/prefs.c | ||||
| src/core/screen.c | ||||
| src/core/session.c | ||||
| src/core/util.c | ||||
| src/core/window.c | ||||
| src/core/window-props.c | ||||
| src/core/xprops.c | ||||
| src/mutter.desktop.in | ||||
| src/mutter-wm.desktop.in | ||||
| src/org.gnome.mutter.gschema.xml.in | ||||
| src/ui/frames.c | ||||
| src/ui/menu.c | ||||
| src/ui/metaaccellabel.c | ||||
| src/ui/resizepopup.c | ||||
| src/ui/theme.c | ||||
| src/ui/theme-parser.c | ||||
| src/x11/session.c | ||||
| src/x11/window-props.c | ||||
| src/x11/xprops.c | ||||
|   | ||||
| @@ -1 +1,2 @@ | ||||
| data/mutter-wayland.desktop.in | ||||
| src/metacity.schemas.in | ||||
|  | ||||
|   | ||||
							
								
								
									
										630
									
								
								po/es.po
									
									
									
									
									
								
							
							
						
						
									
										630
									
								
								po/es.po
									
									
									
									
									
								
							| @@ -14,16 +14,16 @@ msgstr "" | ||||
| "Project-Id-Version: mutter.master\n" | ||||
| "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" | ||||
| "product=mutter&keywords=I18N+L10N&component=general\n" | ||||
| "POT-Creation-Date: 2014-05-08 09:39+0000\n" | ||||
| "PO-Revision-Date: 2014-05-10 19:21+0200\n" | ||||
| "POT-Creation-Date: 2014-03-02 22:51+0000\n" | ||||
| "PO-Revision-Date: 2014-03-03 14:51+0100\n" | ||||
| "Last-Translator: Daniel Mustieles <daniel.mustieles@gmail.com>\n" | ||||
| "Language-Team: Español; Castellano <gnome-es-list@gnome.org>\n" | ||||
| "Language-Team: Español <gnome-es-list@gnome.org>\n" | ||||
| "Language: \n" | ||||
| "MIME-Version: 1.0\n" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
| "Plural-Forms: nplurals=2; plural=(n != 1);\n" | ||||
| "X-Generator: Gtranslator 2.91.6\n" | ||||
| "Plural-Forms: nplurals=2; plural=(n!=1);\n" | ||||
| "X-Generator: Gtranslator 2.91.5\n" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:1 | ||||
| msgid "Navigation" | ||||
| @@ -46,108 +46,102 @@ msgid "Move window to workspace 4" | ||||
| msgstr "Mover la ventana al área de trabajo 4" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:6 | ||||
| #| msgid "Move window to workspace 1" | ||||
| msgid "Move window to last workspace" | ||||
| msgstr "Mover la ventana a la última área de trabajo" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:7 | ||||
| msgid "Move window one workspace to the left" | ||||
| msgstr "Mover la ventana un área de trabajo a la izquierda" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:8 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:7 | ||||
| msgid "Move window one workspace to the right" | ||||
| msgstr "Mover la ventana un área de trabajo a la derecha" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:9 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:8 | ||||
| msgid "Move window one workspace up" | ||||
| msgstr "Subir la ventana un área de trabajo" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:10 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:9 | ||||
| msgid "Move window one workspace down" | ||||
| msgstr "Bajar la ventana un área de trabajo" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:11 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:10 | ||||
| #| msgid "Move window one workspace to the left" | ||||
| msgid "Move window one monitor to the left" | ||||
| msgstr "Mover la ventana una pantalla a la izquierda" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:12 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:11 | ||||
| #| msgid "Move window one workspace to the right" | ||||
| msgid "Move window one monitor to the right" | ||||
| msgstr "Mover la ventana una pantalla a la derecha" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:13 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:12 | ||||
| #| msgid "Move window one workspace up" | ||||
| msgid "Move window one monitor up" | ||||
| msgstr "Subir la ventana una pantalla" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:14 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:13 | ||||
| #| msgid "Move window one workspace down" | ||||
| msgid "Move window one monitor down" | ||||
| msgstr "Bajar la ventana una pantalla" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:15 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:14 | ||||
| msgid "Switch applications" | ||||
| msgstr "Cambiar entre aplicaciones" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:16 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:15 | ||||
| msgid "Switch windows" | ||||
| msgstr "Cambiar entre ventanas" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:17 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:16 | ||||
| msgid "Switch windows of an application" | ||||
| msgstr "Cambiar entre ventanas de una aplicación" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:18 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:17 | ||||
| msgid "Switch system controls" | ||||
| msgstr "Cambiar entre controles del sistema" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:19 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:18 | ||||
| msgid "Switch windows directly" | ||||
| msgstr "Cambiar entre ventanas directamente" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:20 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:19 | ||||
| msgid "Switch windows of an app directly" | ||||
| msgstr "Cambiar entre ventanas de una aplicación directamente" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:21 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:20 | ||||
| msgid "Switch system controls directly" | ||||
| msgstr "Cambiar entre controles del sistema directamente" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:22 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:21 | ||||
| msgid "Hide all normal windows" | ||||
| msgstr "Ocultar todas las ventanas normales" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:23 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:22 | ||||
| msgid "Switch to workspace 1" | ||||
| msgstr "Cambiar al área de trabajo 1" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:24 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:23 | ||||
| msgid "Switch to workspace 2" | ||||
| msgstr "Cambiar al área de trabajo 2" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:25 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:24 | ||||
| msgid "Switch to workspace 3" | ||||
| msgstr "Cambiar al área de trabajo 3" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:26 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:25 | ||||
| msgid "Switch to workspace 4" | ||||
| msgstr "Cambiar al área de trabajo 4" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:27 | ||||
| #| msgid "Switch to workspace 1" | ||||
| msgid "Switch to last workspace" | ||||
| msgstr "Cambiar a la útima área de trabajo" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:28 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:26 | ||||
| msgid "Move to workspace left" | ||||
| msgstr "Mover al área de trabajo de la izquierda" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:29 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:27 | ||||
| msgid "Move to workspace right" | ||||
| msgstr "Mover al área de trabajo de la derecha" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:30 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:28 | ||||
| msgid "Move to workspace above" | ||||
| msgstr "Mover al área de trabajo de la arriba" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:31 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:29 | ||||
| msgid "Move to workspace below" | ||||
| msgstr "Mover al área de trabajo de abajo" | ||||
|  | ||||
| @@ -239,29 +233,9 @@ msgstr "Ver división a la izquierda" | ||||
| msgid "View split on right" | ||||
| msgstr "Ver división a la derecha" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:412 | ||||
| msgid "Built-in display" | ||||
| msgstr "Pantalla integrada" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:437 | ||||
| msgid "Unknown" | ||||
| msgstr "Desconocida" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:439 | ||||
| msgid "Unknown Display" | ||||
| msgstr "Pantalla desconocida" | ||||
|  | ||||
| #. TRANSLATORS: this is a monitor vendor name, followed by a | ||||
| #. * size in inches, like 'Dell 15"' | ||||
| #. | ||||
| #: ../src/backends/meta-monitor-manager.c:447 | ||||
| #, c-format | ||||
| msgid "%s %s" | ||||
| msgstr "%s %s" | ||||
|  | ||||
| #. This probably means that a non-WM compositor like xcompmgr is running; | ||||
| #. * we have no way to get it to exit | ||||
| #: ../src/compositor/compositor.c:464 | ||||
| #: ../src/compositor/compositor.c:534 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Another compositing manager is already running on screen %i on display \"%s" | ||||
| @@ -270,24 +244,29 @@ msgstr "" | ||||
| "Ya existe un gestor de composición ejecutándose en la monitor %i, pantalla " | ||||
| "«%s»." | ||||
|  | ||||
| #: ../src/compositor/meta-background.c:990 | ||||
| #: ../src/compositor/meta-background.c:1074 | ||||
| msgid "background texture could not be created from file" | ||||
| msgstr "no se pudo crear la textura de fondo a partir de archivo" | ||||
|  | ||||
| #: ../src/core/bell.c:215 | ||||
| #: ../src/core/bell.c:321 | ||||
| msgid "Bell event" | ||||
| msgstr "Evento de campana" | ||||
|  | ||||
| #: ../src/core/delete.c:106 | ||||
| #: ../src/core/core.c:156 | ||||
| #, c-format | ||||
| msgid "Unknown window information request: %d" | ||||
| msgstr "Petición de información de ventana desconocida: %d" | ||||
|  | ||||
| #: ../src/core/delete.c:109 | ||||
| #, c-format | ||||
| msgid "“%s” is not responding." | ||||
| msgstr "«%s» no está respondiendo." | ||||
|  | ||||
| #: ../src/core/delete.c:108 | ||||
| #: ../src/core/delete.c:111 | ||||
| msgid "Application is not responding." | ||||
| msgstr "La aplicación no está respondiendo." | ||||
|  | ||||
| #: ../src/core/delete.c:113 | ||||
| #: ../src/core/delete.c:116 | ||||
| msgid "" | ||||
| "You may choose to wait a short while for it to continue or force the " | ||||
| "application to quit entirely." | ||||
| @@ -295,57 +274,68 @@ msgstr "" | ||||
| "Puede elegir esperar un rato para ver si continua o forzar la aplicación " | ||||
| "para cerrarla completamente." | ||||
|  | ||||
| #: ../src/core/delete.c:120 | ||||
| #: ../src/core/delete.c:123 | ||||
| msgid "_Wait" | ||||
| msgstr "_Esperar" | ||||
|  | ||||
| #: ../src/core/delete.c:120 | ||||
| #: ../src/core/delete.c:123 | ||||
| msgid "_Force Quit" | ||||
| msgstr "_Forzar la salida" | ||||
|  | ||||
| #: ../src/core/display.c:451 | ||||
| #: ../src/core/display.c:405 | ||||
| #, c-format | ||||
| msgid "Missing %s extension required for compositing" | ||||
| msgstr "Falta la extensión %s requerida para la composición" | ||||
|  | ||||
| #: ../src/core/display.c:497 | ||||
| #, c-format | ||||
| msgid "Failed to open X Window System display '%s'\n" | ||||
| msgstr "Ocurrió un error al abrir la pantalla de X Window System «%s»\n" | ||||
|  | ||||
| #: ../src/core/main.c:190 | ||||
| #: ../src/core/keybindings.c:1113 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Some other program is already using the key %s with modifiers %x as a " | ||||
| "binding\n" | ||||
| msgstr "" | ||||
| "Algún otro programa ya está usando la clave %s con el modificador %x como " | ||||
| "una vinculación\n" | ||||
|  | ||||
| #: ../src/core/keybindings.c:1310 | ||||
| #, c-format | ||||
| msgid "\"%s\" is not a valid accelerator\n" | ||||
| msgstr "«%s» no es un acelerador válido\n" | ||||
|  | ||||
| #: ../src/core/main.c:195 | ||||
| msgid "Disable connection to session manager" | ||||
| msgstr "Desactivar conexión al gestor de sesión" | ||||
|  | ||||
| #: ../src/core/main.c:196 | ||||
| #: ../src/core/main.c:201 | ||||
| msgid "Replace the running window manager" | ||||
| msgstr "Reemplazar el gestor de ventanas en ejecución" | ||||
|  | ||||
| #: ../src/core/main.c:202 | ||||
| #: ../src/core/main.c:207 | ||||
| msgid "Specify session management ID" | ||||
| msgstr "Especificar el ID se gestión de sesión" | ||||
|  | ||||
| #: ../src/core/main.c:207 | ||||
| #: ../src/core/main.c:212 | ||||
| msgid "X Display to use" | ||||
| msgstr "Pantalla X que usar" | ||||
|  | ||||
| #: ../src/core/main.c:213 | ||||
| #: ../src/core/main.c:218 | ||||
| msgid "Initialize session from savefile" | ||||
| msgstr "Inicializar sesión desde el archivo de salvaguarda" | ||||
|  | ||||
| #: ../src/core/main.c:219 | ||||
| #: ../src/core/main.c:224 | ||||
| msgid "Make X calls synchronous" | ||||
| msgstr "Hacer que las llamadas a las X sean síncronas" | ||||
|  | ||||
| #: ../src/core/main.c:225 | ||||
| msgid "Run as a wayland compositor" | ||||
| msgstr "Ejecutar como compositor Wayland" | ||||
|  | ||||
| #: ../src/core/main.c:231 | ||||
| msgid "Run as a full display server, rather than nested" | ||||
| msgstr "Ejecutar como servidor completo, en lugar de anidado" | ||||
|  | ||||
| #: ../src/core/main.c:476 | ||||
| #: ../src/core/main.c:544 | ||||
| #, c-format | ||||
| msgid "Failed to scan themes directory: %s\n" | ||||
| msgstr "Falló al inspeccionar la carpeta de temas: %s\n" | ||||
|  | ||||
| #: ../src/core/main.c:492 | ||||
| #: ../src/core/main.c:560 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Could not find a theme! Be sure %s exists and contains the usual themes.\n" | ||||
| @@ -353,6 +343,26 @@ msgstr "" | ||||
| "No se ha podido encontrar un tema. Asegúrese de que %s existe y contiene los " | ||||
| "temas usuales.\n" | ||||
|  | ||||
| #: ../src/core/monitor.c:699 | ||||
| msgid "Built-in display" | ||||
| msgstr "Pantalla integrada" | ||||
|  | ||||
| #: ../src/core/monitor.c:724 | ||||
| msgid "Unknown" | ||||
| msgstr "Desconocida" | ||||
|  | ||||
| #: ../src/core/monitor.c:726 | ||||
| msgid "Unknown Display" | ||||
| msgstr "Pantalla desconocida" | ||||
|  | ||||
| #. TRANSLATORS: this is a monitor vendor name, followed by a | ||||
| #. * size in inches, like 'Dell 15"' | ||||
| #. | ||||
| #: ../src/core/monitor.c:734 | ||||
| #, c-format | ||||
| msgid "%s %s" | ||||
| msgstr "%s %s" | ||||
|  | ||||
| #: ../src/core/mutter.c:39 | ||||
| #, c-format | ||||
| msgid "" | ||||
| @@ -376,17 +386,50 @@ msgstr "Imprimir versión" | ||||
| msgid "Mutter plugin to use" | ||||
| msgstr "Complemento de mutter que usar" | ||||
|  | ||||
| #: ../src/core/prefs.c:2005 | ||||
| #: ../src/core/prefs.c:1190 | ||||
| msgid "" | ||||
| "Workarounds for broken applications disabled. Some applications may not " | ||||
| "behave properly.\n" | ||||
| msgstr "" | ||||
| "Los arreglos para aplicaciones rotas se han deshabilitado. Algunas " | ||||
| "aplicaciones podrían no comportarse correctamente.\n" | ||||
|  | ||||
| #: ../src/core/prefs.c:1265 | ||||
| #, c-format | ||||
| msgid "Could not parse font description \"%s\" from GSettings key %s\n" | ||||
| msgstr "" | ||||
| "No se pudo analizar la descripción de la tipografía «%s» de la clave " | ||||
| "GSettings %s\n" | ||||
|  | ||||
| #: ../src/core/prefs.c:1331 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "\"%s\" found in configuration database is not a valid value for mouse button " | ||||
| "modifier\n" | ||||
| msgstr "" | ||||
| "«%s» encontrado en la base de datos de configuración no es un valor válido " | ||||
| "para el modificador del botón del ratón\n" | ||||
|  | ||||
| #: ../src/core/prefs.c:1894 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "\"%s\" found in configuration database is not a valid value for keybinding " | ||||
| "\"%s\"\n" | ||||
| msgstr "" | ||||
| "«%s» encontrado en la base de datos de configuración no es un valor válido " | ||||
| "para la combinación de teclas «%s»\n" | ||||
|  | ||||
| #: ../src/core/prefs.c:1984 | ||||
| #, c-format | ||||
| msgid "Workspace %d" | ||||
| msgstr "Área de trabajo %d" | ||||
|  | ||||
| #: ../src/core/screen.c:529 | ||||
| #: ../src/core/screen.c:539 | ||||
| #, c-format | ||||
| msgid "Screen %d on display '%s' is invalid\n" | ||||
| msgstr "La ventana %d en la pantalla «%s» no es válida\n" | ||||
|  | ||||
| #: ../src/core/screen.c:545 | ||||
| #: ../src/core/screen.c:555 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Screen %d on display \"%s\" already has a window manager; try using the --" | ||||
| @@ -395,16 +438,193 @@ msgstr "" | ||||
| "La ventana %d en la pantalla «%s» ya tiene un gestor de ventanas, intente " | ||||
| "usar la opción «--replace» para reemplazar el gestor de ventanas activo.\n" | ||||
|  | ||||
| #: ../src/core/screen.c:650 | ||||
| #: ../src/core/screen.c:582 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Could not acquire window manager selection on screen %d display \"%s\"\n" | ||||
| msgstr "" | ||||
| "No se ha podido obtener la selección del gestor de ventanas en la ventana %d " | ||||
| "en la pantalla «%s»\n" | ||||
|  | ||||
| #: ../src/core/screen.c:660 | ||||
| #, c-format | ||||
| msgid "Screen %d on display \"%s\" already has a window manager\n" | ||||
| msgstr "La ventana %d en la pantalla «%s» ya tiene un gestor de ventanas\n" | ||||
|  | ||||
| #: ../src/core/util.c:118 | ||||
| #: ../src/core/screen.c:848 | ||||
| #, c-format | ||||
| msgid "Could not release screen %d on display \"%s\"\n" | ||||
| msgstr "No se ha podido liberar el monitor %d en la pantalla «%s»\n" | ||||
|  | ||||
| #: ../src/core/session.c:842 ../src/core/session.c:849 | ||||
| #, c-format | ||||
| msgid "Could not create directory '%s': %s\n" | ||||
| msgstr "No se ha podido crear la carpeta «%s»: %s\n" | ||||
|  | ||||
| #: ../src/core/session.c:859 | ||||
| #, c-format | ||||
| msgid "Could not open session file '%s' for writing: %s\n" | ||||
| msgstr "No se ha podido abrir para escritura el archivo de sesión «%s»: %s\n" | ||||
|  | ||||
| #: ../src/core/session.c:1000 | ||||
| #, c-format | ||||
| msgid "Error writing session file '%s': %s\n" | ||||
| msgstr "Ocurrió un error al escribir en el archivo de sesión «%s»: %s\n" | ||||
|  | ||||
| #: ../src/core/session.c:1005 | ||||
| #, c-format | ||||
| msgid "Error closing session file '%s': %s\n" | ||||
| msgstr "Ocurrió un error al cerrar el archivo de sesión «%s»: %s\n" | ||||
|  | ||||
| #: ../src/core/session.c:1135 | ||||
| #, c-format | ||||
| msgid "Failed to parse saved session file: %s\n" | ||||
| msgstr "Ocurrió un error al interpretar el archivo de sesión guardado: %s\n" | ||||
|  | ||||
| #: ../src/core/session.c:1184 | ||||
| #, c-format | ||||
| msgid "<mutter_session> attribute seen but we already have the session ID" | ||||
| msgstr "" | ||||
| "Se ha visto el atributo <mutter_session> pero ya tenemos el ID de la sesión" | ||||
|  | ||||
| #: ../src/core/session.c:1197 ../src/core/session.c:1272 | ||||
| #: ../src/core/session.c:1304 ../src/core/session.c:1376 | ||||
| #: ../src/core/session.c:1436 | ||||
| #, c-format | ||||
| msgid "Unknown attribute %s on <%s> element" | ||||
| msgstr "Atributo desconocido %s en el elemento <%s>" | ||||
|  | ||||
| #: ../src/core/session.c:1214 | ||||
| #, c-format | ||||
| msgid "nested <window> tag" | ||||
| msgstr "etiqueta <window> anidada" | ||||
|  | ||||
| #: ../src/core/session.c:1456 | ||||
| #, c-format | ||||
| msgid "Unknown element %s" | ||||
| msgstr "Elemento desconocido %s" | ||||
|  | ||||
| #: ../src/core/session.c:1808 | ||||
| msgid "" | ||||
| "These windows do not support "save current setup" and will have to " | ||||
| "be restarted manually next time you log in." | ||||
| msgstr "" | ||||
| "Estas ventanas no soportan «guardar la configuración actual» y tendrán que " | ||||
| "reiniciarse manualmente la próxima vez que inicie una sesión." | ||||
|  | ||||
| #: ../src/core/util.c:82 | ||||
| #, c-format | ||||
| msgid "Failed to open debug log: %s\n" | ||||
| msgstr "Ocurrió un error al abrir el registro de errores: %s\n" | ||||
|  | ||||
| #: ../src/core/util.c:92 | ||||
| #, c-format | ||||
| msgid "Failed to fdopen() log file %s: %s\n" | ||||
| msgstr "Ocurrió un error al hacer fdopen() en el archivo de registro %s: %s\n" | ||||
|  | ||||
| #: ../src/core/util.c:98 | ||||
| #, c-format | ||||
| msgid "Opened log file %s\n" | ||||
| msgstr "Archivo de registro %s abierto\n" | ||||
|  | ||||
| #: ../src/core/util.c:117 | ||||
| msgid "Mutter was compiled without support for verbose mode\n" | ||||
| msgstr "Mutter fue compilado sin soporte para modo prolijo\n" | ||||
|  | ||||
| #: ../src/mutter.desktop.in.h:1 | ||||
| #: ../src/core/util.c:262 | ||||
| msgid "Window manager: " | ||||
| msgstr "Administrador de ventanas: " | ||||
|  | ||||
| # Diferenciar de eRRor en el gestor de ventanas, más abajo | ||||
| #: ../src/core/util.c:412 | ||||
| msgid "Bug in window manager: " | ||||
| msgstr "Error en el gestor de ventanas: " | ||||
|  | ||||
| #: ../src/core/util.c:443 | ||||
| msgid "Window manager warning: " | ||||
| msgstr "Advertencia del gestor de ventanas: " | ||||
|  | ||||
| #: ../src/core/util.c:471 | ||||
| msgid "Window manager error: " | ||||
| msgstr "Error del gestor de ventanas: " | ||||
|  | ||||
| #. first time through | ||||
| #: ../src/core/window.c:7564 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER " | ||||
| "window as specified in the ICCCM.\n" | ||||
| msgstr "" | ||||
| "La ventana %s ha establecido SM_CLIENT_ID sobre sí misma en vez de hacerlo " | ||||
| "en la ventana WM_CLIENT_LEADER como está especificado en el ICCCM.\n" | ||||
|  | ||||
| #. We ignore mwm_has_resize_func because WM_NORMAL_HINTS is the | ||||
| #. * authoritative source for that info. Some apps such as mplayer or | ||||
| #. * xine disable resize via MWM but not WM_NORMAL_HINTS, but that | ||||
| #. * leads to e.g. us not fullscreening their windows.  Apps that set | ||||
| #. * MWM but not WM_NORMAL_HINTS are basically broken. We complain | ||||
| #. * about these apps but make them work. | ||||
| #. | ||||
| #: ../src/core/window.c:8489 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Window %s sets an MWM hint indicating it isn't resizable, but sets min size " | ||||
| "%d x %d and max size %d x %d; this doesn't make much sense.\n" | ||||
| msgstr "" | ||||
| "La ventana %s ha establecido la propiedad MWM indicando que no es " | ||||
| "redimensionable, pero configuró el tamaño mínimo a %d x %d y el tamaño " | ||||
| "máximo a %d x %d ; esto no tiene mucho sentido.\n" | ||||
|  | ||||
| #: ../src/core/window-props.c:349 | ||||
| #, c-format | ||||
| msgid "Application set a bogus _NET_WM_PID %lu\n" | ||||
| msgstr "La aplicación establecio un _NET_WM_PID %lu erróneo\n" | ||||
|  | ||||
| #: ../src/core/window-props.c:465 | ||||
| #, c-format | ||||
| msgid "%s (on %s)" | ||||
| msgstr "%s (on %s)" | ||||
|  | ||||
| #: ../src/core/window-props.c:1548 | ||||
| #, c-format | ||||
| msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n" | ||||
| msgstr "" | ||||
| "WM_TRANSIENT_FOR no válido para la ventana 0x%lx especificada para %s.\n" | ||||
|  | ||||
| #: ../src/core/window-props.c:1559 | ||||
| #, c-format | ||||
| msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n" | ||||
| msgstr "WM_TRANSIENT_FOR ventana 0x%lx para %s crearía un bucle.\n" | ||||
|  | ||||
| #: ../src/core/xprops.c:153 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Window 0x%lx has property %s\n" | ||||
| "that was expected to have type %s format %d\n" | ||||
| "and actually has type %s format %d n_items %d.\n" | ||||
| "This is most likely an application bug, not a window manager bug.\n" | ||||
| "The window has title=\"%s\" class=\"%s\" name=\"%s\"\n" | ||||
| msgstr "" | ||||
| "La ventana 0x%lx tiene la propiedad %s \n" | ||||
| "que se esperaba tuviese el tipo %s con el formato %d\n" | ||||
| "y actualmente tiene un tipo %s con el formato %d y n_items %d\n" | ||||
| "Esto no parece ser un error de la aplicación ni del gestor de ventanas.\n" | ||||
| "La ventana tiene título=«%s» la clase=«%s» y el nombre=«%s»\n" | ||||
|  | ||||
| #: ../src/core/xprops.c:409 | ||||
| #, c-format | ||||
| msgid "Property %s on window 0x%lx contained invalid UTF-8\n" | ||||
| msgstr "La propiedad %s en la ventana 0x%lx contiene UTF-8 no válido\n" | ||||
|  | ||||
| #: ../src/core/xprops.c:492 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Property %s on window 0x%lx contained invalid UTF-8 for item %d in the list\n" | ||||
| msgstr "" | ||||
| "La propiedad %s en la ventana 0x%lx contiene UTF-8 no válido para el " | ||||
| "elemento %d de la lista\n" | ||||
|  | ||||
| #: ../src/mutter.desktop.in.h:1 ../src/mutter-wm.desktop.in.h:1 | ||||
| msgid "Mutter" | ||||
| msgstr "Mutter" | ||||
|  | ||||
| @@ -536,53 +756,13 @@ msgstr "" | ||||
| "la pantalla, se maximizan." | ||||
|  | ||||
| #: ../src/org.gnome.mutter.gschema.xml.in.h:19 | ||||
| msgid "Place new windows in the center" | ||||
| msgstr "Colocar las ventanas nuevas en el centro" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.gschema.xml.in.h:20 | ||||
| msgid "" | ||||
| "When true, the new windows will always be put in the center of the active " | ||||
| "screen of the monitor." | ||||
| msgstr "" | ||||
| "Cuando es cierto, las ventanas nuevas se colocarán siempre en el centro de " | ||||
| "la pantalla activa del monitor." | ||||
|  | ||||
| #: ../src/org.gnome.mutter.gschema.xml.in.h:21 | ||||
| msgid "Select window from tab popup" | ||||
| msgstr "Seleccionar ventana de la pestaña emergente" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.gschema.xml.in.h:22 | ||||
| #: ../src/org.gnome.mutter.gschema.xml.in.h:20 | ||||
| msgid "Cancel tab popup" | ||||
| msgstr "Cancelar pestaña emergente" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:1 | ||||
| msgid "Switch to VT 1" | ||||
| msgstr "Cambiar al VT 1" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:2 | ||||
| msgid "Switch to VT 2" | ||||
| msgstr "Cambiar al VT 2" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:3 | ||||
| msgid "Switch to VT 3" | ||||
| msgstr "Cambiar al VT 3" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:4 | ||||
| msgid "Switch to VT 4" | ||||
| msgstr "Cambiar al VT 4" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:5 | ||||
| msgid "Switch to VT 5" | ||||
| msgstr "Cambiar al VT 5" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:6 | ||||
| msgid "Switch to VT 6" | ||||
| msgstr "Cambiar al VT 6" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:7 | ||||
| msgid "Switch to VT 7" | ||||
| msgstr "Cambiar al VT 7" | ||||
|  | ||||
| #. Translators: Translate this string the same way as you do in libwnck! | ||||
| #: ../src/ui/menu.c:65 | ||||
| msgid "Mi_nimize" | ||||
| @@ -665,22 +845,22 @@ msgstr "Mover al área de trabajo de a_bajo" | ||||
| msgid "_Close" | ||||
| msgstr "_Cerrar" | ||||
|  | ||||
| #: ../src/ui/menu.c:198 | ||||
| #: ../src/ui/menu.c:200 | ||||
| #, c-format | ||||
| msgid "Workspace %d%n" | ||||
| msgstr "Área de trabajo %d%n" | ||||
|  | ||||
| #: ../src/ui/menu.c:208 | ||||
| #: ../src/ui/menu.c:210 | ||||
| #, c-format | ||||
| msgid "Workspace 1_0" | ||||
| msgstr "Área de trabajo 1_0" | ||||
|  | ||||
| #: ../src/ui/menu.c:210 | ||||
| #: ../src/ui/menu.c:212 | ||||
| #, c-format | ||||
| msgid "Workspace %s%d" | ||||
| msgstr "Área de trabajo %s%d" | ||||
|  | ||||
| #: ../src/ui/menu.c:380 | ||||
| #: ../src/ui/menu.c:382 | ||||
| msgid "Move to Another _Workspace" | ||||
| msgstr "Mover a _otro área de trabajo" | ||||
|  | ||||
| @@ -1480,175 +1660,6 @@ msgstr "<%s> especificado dos veces para este tema" | ||||
| msgid "Failed to find a valid file for theme %s\n" | ||||
| msgstr "Falló al encontrar un archivo válido para el tema%s\n" | ||||
|  | ||||
| #: ../src/x11/session.c:1815 | ||||
| msgid "" | ||||
| "These windows do not support "save current setup" and will have to " | ||||
| "be restarted manually next time you log in." | ||||
| msgstr "" | ||||
| "Estas ventanas no soportan «guardar la configuración actual» y tendrán que " | ||||
| "reiniciarse manualmente la próxima vez que inicie una sesión." | ||||
|  | ||||
| #: ../src/x11/window-props.c:465 | ||||
| #, c-format | ||||
| msgid "%s (on %s)" | ||||
| msgstr "%s (on %s)" | ||||
|  | ||||
| #~ msgid "Mutter (wayland compositor)" | ||||
| #~ msgstr "Mutter (compositor Wayland)" | ||||
|  | ||||
| #~ msgid "Unknown window information request: %d" | ||||
| #~ msgstr "Petición de información de ventana desconocida: %d" | ||||
|  | ||||
| #~ msgid "Missing %s extension required for compositing" | ||||
| #~ msgstr "Falta la extensión %s requerida para la composición" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Some other program is already using the key %s with modifiers %x as a " | ||||
| #~ "binding\n" | ||||
| #~ msgstr "" | ||||
| #~ "Algún otro programa ya está usando la clave %s con el modificador %x como " | ||||
| #~ "una vinculación\n" | ||||
|  | ||||
| #~ msgid "\"%s\" is not a valid accelerator\n" | ||||
| #~ msgstr "«%s» no es un acelerador válido\n" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Workarounds for broken applications disabled. Some applications may not " | ||||
| #~ "behave properly.\n" | ||||
| #~ msgstr "" | ||||
| #~ "Los arreglos para aplicaciones rotas se han deshabilitado. Algunas " | ||||
| #~ "aplicaciones podrían no comportarse correctamente.\n" | ||||
|  | ||||
| #~ msgid "Could not parse font description \"%s\" from GSettings key %s\n" | ||||
| #~ msgstr "" | ||||
| #~ "No se pudo analizar la descripción de la tipografía «%s» de la clave " | ||||
| #~ "GSettings %s\n" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "\"%s\" found in configuration database is not a valid value for mouse " | ||||
| #~ "button modifier\n" | ||||
| #~ msgstr "" | ||||
| #~ "«%s» encontrado en la base de datos de configuración no es un valor " | ||||
| #~ "válido para el modificador del botón del ratón\n" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "\"%s\" found in configuration database is not a valid value for " | ||||
| #~ "keybinding \"%s\"\n" | ||||
| #~ msgstr "" | ||||
| #~ "«%s» encontrado en la base de datos de configuración no es un valor " | ||||
| #~ "válido para la combinación de teclas «%s»\n" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Could not acquire window manager selection on screen %d display \"%s\"\n" | ||||
| #~ msgstr "" | ||||
| #~ "No se ha podido obtener la selección del gestor de ventanas en la ventana " | ||||
| #~ "%d en la pantalla «%s»\n" | ||||
|  | ||||
| #~ msgid "Could not release screen %d on display \"%s\"\n" | ||||
| #~ msgstr "No se ha podido liberar el monitor %d en la pantalla «%s»\n" | ||||
|  | ||||
| #~ msgid "Could not create directory '%s': %s\n" | ||||
| #~ msgstr "No se ha podido crear la carpeta «%s»: %s\n" | ||||
|  | ||||
| #~ msgid "Could not open session file '%s' for writing: %s\n" | ||||
| #~ msgstr "" | ||||
| #~ "No se ha podido abrir para escritura el archivo de sesión «%s»: %s\n" | ||||
|  | ||||
| #~ msgid "Error writing session file '%s': %s\n" | ||||
| #~ msgstr "Ocurrió un error al escribir en el archivo de sesión «%s»: %s\n" | ||||
|  | ||||
| #~ msgid "Error closing session file '%s': %s\n" | ||||
| #~ msgstr "Ocurrió un error al cerrar el archivo de sesión «%s»: %s\n" | ||||
|  | ||||
| #~ msgid "Failed to parse saved session file: %s\n" | ||||
| #~ msgstr "Ocurrió un error al interpretar el archivo de sesión guardado: %s\n" | ||||
|  | ||||
| #~ msgid "<mutter_session> attribute seen but we already have the session ID" | ||||
| #~ msgstr "" | ||||
| #~ "Se ha visto el atributo <mutter_session> pero ya tenemos el ID de la " | ||||
| #~ "sesión" | ||||
|  | ||||
| #~ msgid "Unknown attribute %s on <%s> element" | ||||
| #~ msgstr "Atributo desconocido %s en el elemento <%s>" | ||||
|  | ||||
| #~ msgid "nested <window> tag" | ||||
| #~ msgstr "etiqueta <window> anidada" | ||||
|  | ||||
| #~ msgid "Unknown element %s" | ||||
| #~ msgstr "Elemento desconocido %s" | ||||
|  | ||||
| #~ msgid "Failed to open debug log: %s\n" | ||||
| #~ msgstr "Ocurrió un error al abrir el registro de errores: %s\n" | ||||
|  | ||||
| #~ msgid "Failed to fdopen() log file %s: %s\n" | ||||
| #~ msgstr "" | ||||
| #~ "Ocurrió un error al hacer fdopen() en el archivo de registro %s: %s\n" | ||||
|  | ||||
| #~ msgid "Opened log file %s\n" | ||||
| #~ msgstr "Archivo de registro %s abierto\n" | ||||
|  | ||||
| #~ msgid "Window manager: " | ||||
| #~ msgstr "Administrador de ventanas: " | ||||
|  | ||||
| # Diferenciar de eRRor en el gestor de ventanas, más abajo | ||||
| #~ msgid "Bug in window manager: " | ||||
| #~ msgstr "Error en el gestor de ventanas: " | ||||
|  | ||||
| #~ msgid "Window manager warning: " | ||||
| #~ msgstr "Advertencia del gestor de ventanas: " | ||||
|  | ||||
| #~ msgid "Window manager error: " | ||||
| #~ msgstr "Error del gestor de ventanas: " | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER " | ||||
| #~ "window as specified in the ICCCM.\n" | ||||
| #~ msgstr "" | ||||
| #~ "La ventana %s ha establecido SM_CLIENT_ID sobre sí misma en vez de " | ||||
| #~ "hacerlo en la ventana WM_CLIENT_LEADER como está especificado en el " | ||||
| #~ "ICCCM.\n" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Window %s sets an MWM hint indicating it isn't resizable, but sets min " | ||||
| #~ "size %d x %d and max size %d x %d; this doesn't make much sense.\n" | ||||
| #~ msgstr "" | ||||
| #~ "La ventana %s ha establecido la propiedad MWM indicando que no es " | ||||
| #~ "redimensionable, pero configuró el tamaño mínimo a %d x %d y el tamaño " | ||||
| #~ "máximo a %d x %d ; esto no tiene mucho sentido.\n" | ||||
|  | ||||
| #~ msgid "Application set a bogus _NET_WM_PID %lu\n" | ||||
| #~ msgstr "La aplicación establecio un _NET_WM_PID %lu erróneo\n" | ||||
|  | ||||
| #~ msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n" | ||||
| #~ msgstr "" | ||||
| #~ "WM_TRANSIENT_FOR no válido para la ventana 0x%lx especificada para %s.\n" | ||||
|  | ||||
| #~ msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n" | ||||
| #~ msgstr "WM_TRANSIENT_FOR ventana 0x%lx para %s crearía un bucle.\n" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Window 0x%lx has property %s\n" | ||||
| #~ "that was expected to have type %s format %d\n" | ||||
| #~ "and actually has type %s format %d n_items %d.\n" | ||||
| #~ "This is most likely an application bug, not a window manager bug.\n" | ||||
| #~ "The window has title=\"%s\" class=\"%s\" name=\"%s\"\n" | ||||
| #~ msgstr "" | ||||
| #~ "La ventana 0x%lx tiene la propiedad %s \n" | ||||
| #~ "que se esperaba tuviese el tipo %s con el formato %d\n" | ||||
| #~ "y actualmente tiene un tipo %s con el formato %d y n_items %d\n" | ||||
| #~ "Esto no parece ser un error de la aplicación ni del gestor de ventanas.\n" | ||||
| #~ "La ventana tiene título=«%s» la clase=«%s» y el nombre=«%s»\n" | ||||
|  | ||||
| #~ msgid "Property %s on window 0x%lx contained invalid UTF-8\n" | ||||
| #~ msgstr "La propiedad %s en la ventana 0x%lx contiene UTF-8 no válido\n" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Property %s on window 0x%lx contained invalid UTF-8 for item %d in the " | ||||
| #~ "list\n" | ||||
| #~ msgstr "" | ||||
| #~ "La propiedad %s en la ventana 0x%lx contiene UTF-8 no válido para el " | ||||
| #~ "elemento %d de la lista\n" | ||||
|  | ||||
| #~ msgid "Usage: %s\n" | ||||
| #~ msgstr "Uso: %s\n" | ||||
|  | ||||
| @@ -1848,6 +1859,15 @@ msgstr "%s (on %s)" | ||||
| #~ msgid "Put Window On Only One Workspace" | ||||
| #~ msgstr "Poner la ventana sólo en un área de trabajo" | ||||
|  | ||||
| #~ msgid "Switch to workspace 5" | ||||
| #~ msgstr "Cambiar al área de trabajo 5" | ||||
|  | ||||
| #~ msgid "Switch to workspace 6" | ||||
| #~ msgstr "Cambiar al área de trabajo 6" | ||||
|  | ||||
| #~ msgid "Switch to workspace 7" | ||||
| #~ msgstr "Cambiar al área de trabajo 7" | ||||
|  | ||||
| #~ msgid "Switch to workspace 8" | ||||
| #~ msgstr "Cambiar al área de trabajo 8" | ||||
|  | ||||
| @@ -2029,11 +2049,11 @@ msgstr "%s (on %s)" | ||||
|  | ||||
| #~ msgid "GConf key %s is already in use and can't be used to override %s\n" | ||||
| #~ msgstr "" | ||||
| #~ "La clave de GConf %s ya está en uso y no se puede usar para sobrescribir " | ||||
| #~ "La clave de GConf %s ya está en uso y no se puede usar para sobreescribir " | ||||
| #~ "%s\n" | ||||
|  | ||||
| #~ msgid "Can't override GConf key, %s not found\n" | ||||
| #~ msgstr "No se puede sobrescribir la clave de GConf, no se encontró %s\n" | ||||
| #~ msgstr "No se puede sobreescribir la clave de GConf, no se encontró %s\n" | ||||
|  | ||||
| #~ msgid "Error setting number of workspaces to %d: %s\n" | ||||
| #~ msgstr "" | ||||
|   | ||||
							
								
								
									
										533
									
								
								po/gl.po
									
									
									
									
									
								
							
							
						
						
									
										533
									
								
								po/gl.po
									
									
									
									
									
								
							| @@ -14,8 +14,8 @@ msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: gl\n" | ||||
| "Report-Msgid-Bugs-To: \n" | ||||
| "POT-Creation-Date: 2014-04-10 13:26+0200\n" | ||||
| "PO-Revision-Date: 2014-04-10 13:27+0200\n" | ||||
| "POT-Creation-Date: 2014-03-03 21:29+0100\n" | ||||
| "PO-Revision-Date: 2014-03-03 21:30+0200\n" | ||||
| "Last-Translator: Fran Dieguez <frandieguez@gnome.org>\n" | ||||
| "Language-Team: gnome-l10n-gl@gnome.org\n" | ||||
| "Language: gl\n" | ||||
| @@ -229,29 +229,9 @@ msgstr "Dividir vista á esquerda" | ||||
| msgid "View split on right" | ||||
| msgstr "Dividir vista á dereita" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:465 | ||||
| msgid "Built-in display" | ||||
| msgstr "Pantalla embebida" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:490 | ||||
| msgid "Unknown" | ||||
| msgstr "Descoñecido" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:492 | ||||
| msgid "Unknown Display" | ||||
| msgstr "Pantalla descoñecida" | ||||
|  | ||||
| #. TRANSLATORS: this is a monitor vendor name, followed by a | ||||
| #. * size in inches, like 'Dell 15"' | ||||
| #. | ||||
| #: ../src/backends/meta-monitor-manager.c:500 | ||||
| #, c-format | ||||
| msgid "%s %s" | ||||
| msgstr "%s %s" | ||||
|  | ||||
| #. This probably means that a non-WM compositor like xcompmgr is running; | ||||
| #. * we have no way to get it to exit | ||||
| #: ../src/compositor/compositor.c:505 | ||||
| #: ../src/compositor/compositor.c:534 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Another compositing manager is already running on screen %i on display \"%s" | ||||
| @@ -260,24 +240,29 @@ msgstr "" | ||||
| "Xa se está a executar outro xestor de composición na pantalla %i na " | ||||
| "visualización «%s»" | ||||
|  | ||||
| #: ../src/compositor/meta-background.c:990 | ||||
| #: ../src/compositor/meta-background.c:1074 | ||||
| msgid "background texture could not be created from file" | ||||
| msgstr "a textura do fondo non puido crearse desde o ficheiro" | ||||
|  | ||||
| #: ../src/core/bell.c:213 | ||||
| #: ../src/core/bell.c:321 | ||||
| msgid "Bell event" | ||||
| msgstr "Evento de campá" | ||||
|  | ||||
| #: ../src/core/delete.c:106 | ||||
| #: ../src/core/core.c:156 | ||||
| #, c-format | ||||
| msgid "Unknown window information request: %d" | ||||
| msgstr "Petición de información de xanela descoñecida: %d" | ||||
|  | ||||
| #: ../src/core/delete.c:109 | ||||
| #, c-format | ||||
| msgid "“%s” is not responding." | ||||
| msgstr "«%s» non está respondendo." | ||||
|  | ||||
| #: ../src/core/delete.c:108 | ||||
| #: ../src/core/delete.c:111 | ||||
| msgid "Application is not responding." | ||||
| msgstr "O Aplicativo non está respondendo." | ||||
|  | ||||
| #: ../src/core/delete.c:113 | ||||
| #: ../src/core/delete.c:116 | ||||
| msgid "" | ||||
| "You may choose to wait a short while for it to continue or force the " | ||||
| "application to quit entirely." | ||||
| @@ -285,57 +270,68 @@ msgstr "" | ||||
| "Pode elixir esperar un momento para ver se continúa ou forzar ao aplicativo " | ||||
| "a pechar completamente." | ||||
|  | ||||
| #: ../src/core/delete.c:120 | ||||
| #: ../src/core/delete.c:123 | ||||
| msgid "_Wait" | ||||
| msgstr "Espe_rar" | ||||
|  | ||||
| #: ../src/core/delete.c:120 | ||||
| #: ../src/core/delete.c:123 | ||||
| msgid "_Force Quit" | ||||
| msgstr "_Forzar a saída" | ||||
|  | ||||
| #: ../src/core/display.c:453 | ||||
| #: ../src/core/display.c:405 | ||||
| #, c-format | ||||
| msgid "Missing %s extension required for compositing" | ||||
| msgstr "Falta a extensión %s que se require para a composición" | ||||
|  | ||||
| #: ../src/core/display.c:497 | ||||
| #, c-format | ||||
| msgid "Failed to open X Window System display '%s'\n" | ||||
| msgstr "Produciuse un erro ao abrir a visualización do X Window System «%s»\n" | ||||
|  | ||||
| #: ../src/core/main.c:200 | ||||
| #: ../src/core/keybindings.c:1113 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Some other program is already using the key %s with modifiers %x as a " | ||||
| "binding\n" | ||||
| msgstr "" | ||||
| "Algún outro programa xa está usando a tecla %s cos modificadores %x como " | ||||
| "combinación\n" | ||||
|  | ||||
| #: ../src/core/keybindings.c:1310 | ||||
| #, c-format | ||||
| msgid "\"%s\" is not a valid accelerator\n" | ||||
| msgstr "«%s» non é un acelerador correcto\n" | ||||
|  | ||||
| #: ../src/core/main.c:195 | ||||
| msgid "Disable connection to session manager" | ||||
| msgstr "Desactivar a conexión ao xestor de sesión" | ||||
|  | ||||
| #: ../src/core/main.c:206 | ||||
| #: ../src/core/main.c:201 | ||||
| msgid "Replace the running window manager" | ||||
| msgstr "Substituír o xestor de xanelas en execución" | ||||
|  | ||||
| #: ../src/core/main.c:212 | ||||
| #: ../src/core/main.c:207 | ||||
| msgid "Specify session management ID" | ||||
| msgstr "Especificar o ID de xestión de sesión" | ||||
|  | ||||
| #: ../src/core/main.c:217 | ||||
| #: ../src/core/main.c:212 | ||||
| msgid "X Display to use" | ||||
| msgstr "Pantalla X que se vai usar" | ||||
|  | ||||
| #: ../src/core/main.c:223 | ||||
| #: ../src/core/main.c:218 | ||||
| msgid "Initialize session from savefile" | ||||
| msgstr "Inicializar sesión desde o ficheiro de salvagarda" | ||||
|  | ||||
| #: ../src/core/main.c:229 | ||||
| #: ../src/core/main.c:224 | ||||
| msgid "Make X calls synchronous" | ||||
| msgstr "Facer que as chamadas a X sexan sincrónicas" | ||||
|  | ||||
| #: ../src/core/main.c:235 | ||||
| msgid "Run as a wayland compositor" | ||||
| msgstr "Executar como compositor de wayland" | ||||
|  | ||||
| #: ../src/core/main.c:241 | ||||
| msgid "Run as a full display server, rather than nested" | ||||
| msgstr "Executar como un servidor de pantalla completo, fronte a un aniñado" | ||||
|  | ||||
| #: ../src/core/main.c:486 | ||||
| #: ../src/core/main.c:544 | ||||
| #, c-format | ||||
| msgid "Failed to scan themes directory: %s\n" | ||||
| msgstr "Produciuse un erro ao dixitalizar o directorio de temas: %s\n" | ||||
|  | ||||
| #: ../src/core/main.c:502 | ||||
| #: ../src/core/main.c:560 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Could not find a theme! Be sure %s exists and contains the usual themes.\n" | ||||
| @@ -343,6 +339,26 @@ msgstr "" | ||||
| "Non foi posíbel atopar ningún tema! Asegúrese de que %s existe e de que " | ||||
| "contén os temas habituais.\n" | ||||
|  | ||||
| #: ../src/core/monitor.c:699 | ||||
| msgid "Built-in display" | ||||
| msgstr "Pantalla embebida" | ||||
|  | ||||
| #: ../src/core/monitor.c:724 | ||||
| msgid "Unknown" | ||||
| msgstr "Descoñecido" | ||||
|  | ||||
| #: ../src/core/monitor.c:726 | ||||
| msgid "Unknown Display" | ||||
| msgstr "Pantalla descoñecida" | ||||
|  | ||||
| #. TRANSLATORS: this is a monitor vendor name, followed by a | ||||
| #. * size in inches, like 'Dell 15"' | ||||
| #. | ||||
| #: ../src/core/monitor.c:734 | ||||
| #, c-format | ||||
| msgid "%s %s" | ||||
| msgstr "%s %s" | ||||
|  | ||||
| #: ../src/core/mutter.c:39 | ||||
| #, c-format | ||||
| msgid "" | ||||
| @@ -366,17 +382,50 @@ msgstr "Imprimir versión" | ||||
| msgid "Mutter plugin to use" | ||||
| msgstr "Engadido de mutter que usar" | ||||
|  | ||||
| #: ../src/core/prefs.c:1985 | ||||
| #: ../src/core/prefs.c:1190 | ||||
| msgid "" | ||||
| "Workarounds for broken applications disabled. Some applications may not " | ||||
| "behave properly.\n" | ||||
| msgstr "" | ||||
| "Desactiváronse os arranxos para aplicativos danados. Pode que algúns " | ||||
| "aplicativos non se comporten correctamente.\n" | ||||
|  | ||||
| #: ../src/core/prefs.c:1265 | ||||
| #, c-format | ||||
| msgid "Could not parse font description \"%s\" from GSettings key %s\n" | ||||
| msgstr "" | ||||
| "Non foi posíbel analizar a descrición do tipo de letra «%s» da chave " | ||||
| "GSettings %s\n" | ||||
|  | ||||
| #: ../src/core/prefs.c:1331 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "\"%s\" found in configuration database is not a valid value for mouse button " | ||||
| "modifier\n" | ||||
| msgstr "" | ||||
| "«%s» atopados na base de datos de configuración non é un valor correcto para " | ||||
| "o modificador do botón do rato\n" | ||||
|  | ||||
| #: ../src/core/prefs.c:1894 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "\"%s\" found in configuration database is not a valid value for keybinding " | ||||
| "\"%s\"\n" | ||||
| msgstr "" | ||||
| "«%s» atopados na base de datos de configuración non é un valor correcto para " | ||||
| "a combinación de teclas «%s»\n" | ||||
|  | ||||
| #: ../src/core/prefs.c:1984 | ||||
| #, c-format | ||||
| msgid "Workspace %d" | ||||
| msgstr "Espazo de traballo %d" | ||||
|  | ||||
| #: ../src/core/screen.c:543 | ||||
| #: ../src/core/screen.c:539 | ||||
| #, c-format | ||||
| msgid "Screen %d on display '%s' is invalid\n" | ||||
| msgstr "A pantalla %d na visualización «%s» non é válida\n" | ||||
|  | ||||
| #: ../src/core/screen.c:559 | ||||
| #: ../src/core/screen.c:555 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Screen %d on display \"%s\" already has a window manager; try using the --" | ||||
| @@ -385,23 +434,194 @@ msgstr "" | ||||
| "A visualización %d na pantalla «%s» ten xa un xestor de xanelas, tente usar " | ||||
| "a opción --replace para substituír o xestor de xanelas.\n" | ||||
|  | ||||
| #: ../src/core/screen.c:664 | ||||
| #: ../src/core/screen.c:582 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Could not acquire window manager selection on screen %d display \"%s\"\n" | ||||
| msgstr "" | ||||
| "Non foi posíbel obter a selección do xestor de xanelas na pantalla %d na " | ||||
| "visualización «%s»\n" | ||||
|  | ||||
| #: ../src/core/screen.c:660 | ||||
| #, c-format | ||||
| msgid "Screen %d on display \"%s\" already has a window manager\n" | ||||
| msgstr "A visualización %d na pantalla «%s» ten xa un xestor de xanelas\n" | ||||
|  | ||||
| #: ../src/core/util.c:118 | ||||
| #: ../src/core/screen.c:848 | ||||
| #, c-format | ||||
| msgid "Could not release screen %d on display \"%s\"\n" | ||||
| msgstr "Non foi posíbel liberar a visualización %d na pantalla «%s»\n" | ||||
|  | ||||
| #: ../src/core/session.c:842 ../src/core/session.c:849 | ||||
| #, c-format | ||||
| msgid "Could not create directory '%s': %s\n" | ||||
| msgstr "Non foi posíbel crear o directorio «%s»: %s\n" | ||||
|  | ||||
| #: ../src/core/session.c:859 | ||||
| #, c-format | ||||
| msgid "Could not open session file '%s' for writing: %s\n" | ||||
| msgstr "Non foi posíbel abrir o ficheiro de sesión «%s» para escritura: %s\n" | ||||
|  | ||||
| #: ../src/core/session.c:1000 | ||||
| #, c-format | ||||
| msgid "Error writing session file '%s': %s\n" | ||||
| msgstr "Produciuse un erro ao escribir o ficheiro de sesión «%s»: %s\n" | ||||
|  | ||||
| #: ../src/core/session.c:1005 | ||||
| #, c-format | ||||
| msgid "Error closing session file '%s': %s\n" | ||||
| msgstr "Produciuse un erro ao pechar o ficheiro de sesión «%s»: %s\n" | ||||
|  | ||||
| #: ../src/core/session.c:1135 | ||||
| #, c-format | ||||
| msgid "Failed to parse saved session file: %s\n" | ||||
| msgstr "Produciuse un erro ao analizar o ficheiro de sesión gardado: %s\n" | ||||
|  | ||||
| #: ../src/core/session.c:1184 | ||||
| #, c-format | ||||
| msgid "<mutter_session> attribute seen but we already have the session ID" | ||||
| msgstr "O atributo <mutter_session> foi visto pero xa temos o ID de sesión" | ||||
|  | ||||
| #: ../src/core/session.c:1197 ../src/core/session.c:1272 | ||||
| #: ../src/core/session.c:1304 ../src/core/session.c:1376 | ||||
| #: ../src/core/session.c:1436 | ||||
| #, c-format | ||||
| msgid "Unknown attribute %s on <%s> element" | ||||
| msgstr "Atributo descoñecido %s no elemento <%s>" | ||||
|  | ||||
| #: ../src/core/session.c:1214 | ||||
| #, c-format | ||||
| msgid "nested <window> tag" | ||||
| msgstr "etiqueta <window> aniñada" | ||||
|  | ||||
| #: ../src/core/session.c:1456 | ||||
| #, c-format | ||||
| msgid "Unknown element %s" | ||||
| msgstr "Elemento descoñecido %s" | ||||
|  | ||||
| #: ../src/core/session.c:1808 | ||||
| msgid "" | ||||
| "These windows do not support "save current setup" and will have to " | ||||
| "be restarted manually next time you log in." | ||||
| msgstr "" | ||||
| "Estas xanelas non soportan "save current setup" e terán que " | ||||
| "reiniciarse manualmente a próxima vez que inicie a sesión." | ||||
|  | ||||
| #: ../src/core/util.c:82 | ||||
| #, c-format | ||||
| msgid "Failed to open debug log: %s\n" | ||||
| msgstr "Produciuse un erro ao abrir o rexistro de depuración: %s\n" | ||||
|  | ||||
| #: ../src/core/util.c:92 | ||||
| #, c-format | ||||
| msgid "Failed to fdopen() log file %s: %s\n" | ||||
| msgstr "Produciuse un erro ao facer fdopen() no ficheiro de rexistro %s: %s\n" | ||||
|  | ||||
| #: ../src/core/util.c:98 | ||||
| #, c-format | ||||
| msgid "Opened log file %s\n" | ||||
| msgstr "Ficheiro de rexistro %s aberto\n" | ||||
|  | ||||
| #: ../src/core/util.c:117 | ||||
| msgid "Mutter was compiled without support for verbose mode\n" | ||||
| msgstr "Mutter foi compilado sen compatibilidade para o modo detallado\n" | ||||
|  | ||||
| #: ../src/mutter.desktop.in.h:1 | ||||
| #: ../src/core/util.c:262 | ||||
| msgid "Window manager: " | ||||
| msgstr "Xestor de xanelas: " | ||||
|  | ||||
| #: ../src/core/util.c:412 | ||||
| msgid "Bug in window manager: " | ||||
| msgstr "Fallo no xestor de xanelas: " | ||||
|  | ||||
| #: ../src/core/util.c:443 | ||||
| msgid "Window manager warning: " | ||||
| msgstr "Aviso do xestor de xanelas: " | ||||
|  | ||||
| #: ../src/core/util.c:471 | ||||
| msgid "Window manager error: " | ||||
| msgstr "Erro do xestor de xanelas: " | ||||
|  | ||||
| #. first time through | ||||
| #: ../src/core/window.c:7564 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER " | ||||
| "window as specified in the ICCCM.\n" | ||||
| msgstr "" | ||||
| "A xanela %s estabelece SM_CLIENT_ID sobre si mesma en vez de facelo na " | ||||
| "xanela WM_CLIENT_LEADER como está especificado no ICCCM.\n" | ||||
|  | ||||
| #. We ignore mwm_has_resize_func because WM_NORMAL_HINTS is the | ||||
| #. * authoritative source for that info. Some apps such as mplayer or | ||||
| #. * xine disable resize via MWM but not WM_NORMAL_HINTS, but that | ||||
| #. * leads to e.g. us not fullscreening their windows.  Apps that set | ||||
| #. * MWM but not WM_NORMAL_HINTS are basically broken. We complain | ||||
| #. * about these apps but make them work. | ||||
| #. | ||||
| #: ../src/core/window.c:8489 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Window %s sets an MWM hint indicating it isn't resizable, but sets min size " | ||||
| "%d x %d and max size %d x %d; this doesn't make much sense.\n" | ||||
| msgstr "" | ||||
| "A xanela %s estabeleceu a propiedade MWM indicando que non é redimensionábel " | ||||
| "mais configurou o tamaño mínimo a %d x %d e o tamaño máximo a %d x %d, isto " | ||||
| "non ten moito sentido.\n" | ||||
|  | ||||
| #: ../src/core/window-props.c:349 | ||||
| #, c-format | ||||
| msgid "Application set a bogus _NET_WM_PID %lu\n" | ||||
| msgstr "O aplicativo configurou un _NET_WM_PID %lu falso\n" | ||||
|  | ||||
| #: ../src/core/window-props.c:465 | ||||
| #, c-format | ||||
| msgid "%s (on %s)" | ||||
| msgstr "%s (en %s)" | ||||
|  | ||||
| #: ../src/core/window-props.c:1548 | ||||
| #, c-format | ||||
| msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n" | ||||
| msgstr "" | ||||
| "WM_TRANSIENT_FOR non válido para a xanela 0x%lx especificada para %s.\n" | ||||
|  | ||||
| #: ../src/core/window-props.c:1559 | ||||
| #, c-format | ||||
| msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n" | ||||
| msgstr "WM_TRANSIENT_FOR xanela 0x%lx para %s crearía un bucle.\n" | ||||
|  | ||||
| #: ../src/core/xprops.c:153 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Window 0x%lx has property %s\n" | ||||
| "that was expected to have type %s format %d\n" | ||||
| "and actually has type %s format %d n_items %d.\n" | ||||
| "This is most likely an application bug, not a window manager bug.\n" | ||||
| "The window has title=\"%s\" class=\"%s\" name=\"%s\"\n" | ||||
| msgstr "" | ||||
| "A xanela 0x%lx ten a propiedade %s\n" | ||||
| "que se esperaba que tivese o tipo %s co formato %d\n" | ||||
| "e actualmente ten un tipo %s co formato %d e n_items %d.\n" | ||||
| "Isto non parece ser un fallo do aplicativo nin do xestor de xanelas.\n" | ||||
| "A xanela ten título=«%s» a clase=«%s» e o nome=«%s»\n" | ||||
|  | ||||
| #: ../src/core/xprops.c:409 | ||||
| #, c-format | ||||
| msgid "Property %s on window 0x%lx contained invalid UTF-8\n" | ||||
| msgstr "A propiedade %s na xanela 0x%lx contén UTF-8 non válido\n" | ||||
|  | ||||
| #: ../src/core/xprops.c:492 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Property %s on window 0x%lx contained invalid UTF-8 for item %d in the list\n" | ||||
| msgstr "" | ||||
| "A propiedade %s na xanela 0x%lx contén UTF-8 non válido para o elemento da " | ||||
| "lista %d\n" | ||||
|  | ||||
| #: ../src/mutter.desktop.in.h:1 ../src/mutter-wm.desktop.in.h:1 | ||||
| msgid "Mutter" | ||||
| msgstr "Mutter" | ||||
|  | ||||
| #: ../src/mutter-wayland.desktop.in.h:1 | ||||
| msgid "Mutter (wayland compositor)" | ||||
| msgstr "Mutter (compositor de wayland)" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.gschema.xml.in.h:1 | ||||
| msgid "Modifier to use for extended window management operations" | ||||
| msgstr "" | ||||
| @@ -533,34 +753,6 @@ msgstr "Seleccionar xanela da lapela emerxente" | ||||
| msgid "Cancel tab popup" | ||||
| msgstr "Cancelar lapela emerxente" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:1 | ||||
| msgid "Switch to VT 1" | ||||
| msgstr "Cambiar á VT 1" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:2 | ||||
| msgid "Switch to VT 2" | ||||
| msgstr "Cambiar á VT 2" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:3 | ||||
| msgid "Switch to VT 3" | ||||
| msgstr "Cambiar á VT 3" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:4 | ||||
| msgid "Switch to VT 4" | ||||
| msgstr "Cambiar á VT 4" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:5 | ||||
| msgid "Switch to VT 5" | ||||
| msgstr "Cambiar á VT 5" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:6 | ||||
| msgid "Switch to VT 6" | ||||
| msgstr "Cambiar á VT 6" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:7 | ||||
| msgid "Switch to VT 7" | ||||
| msgstr "Cambiar á VT 7" | ||||
|  | ||||
| #. Translators: Translate this string the same way as you do in libwnck! | ||||
| #: ../src/ui/menu.c:65 | ||||
| msgid "Mi_nimize" | ||||
| @@ -1446,168 +1638,6 @@ msgstr "<%s> especificada dúas veces para este tema" | ||||
| msgid "Failed to find a valid file for theme %s\n" | ||||
| msgstr "Produciuse un erro ao buscar un ficheiro correcto para o tema %s\n" | ||||
|  | ||||
| #: ../src/x11/session.c:1815 | ||||
| msgid "" | ||||
| "These windows do not support "save current setup" and will have to " | ||||
| "be restarted manually next time you log in." | ||||
| msgstr "" | ||||
| "Estas xanelas non soportan "save current setup" e terán que " | ||||
| "reiniciarse manualmente a próxima vez que inicie a sesión." | ||||
|  | ||||
| #: ../src/x11/window-props.c:465 | ||||
| #, c-format | ||||
| msgid "%s (on %s)" | ||||
| msgstr "%s (en %s)" | ||||
|  | ||||
| #~ msgid "Unknown window information request: %d" | ||||
| #~ msgstr "Petición de información de xanela descoñecida: %d" | ||||
|  | ||||
| #~ msgid "Missing %s extension required for compositing" | ||||
| #~ msgstr "Falta a extensión %s que se require para a composición" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Some other program is already using the key %s with modifiers %x as a " | ||||
| #~ "binding\n" | ||||
| #~ msgstr "" | ||||
| #~ "Algún outro programa xa está usando a tecla %s cos modificadores %x como " | ||||
| #~ "combinación\n" | ||||
|  | ||||
| #~ msgid "\"%s\" is not a valid accelerator\n" | ||||
| #~ msgstr "«%s» non é un acelerador correcto\n" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Workarounds for broken applications disabled. Some applications may not " | ||||
| #~ "behave properly.\n" | ||||
| #~ msgstr "" | ||||
| #~ "Desactiváronse os arranxos para aplicativos danados. Pode que algúns " | ||||
| #~ "aplicativos non se comporten correctamente.\n" | ||||
|  | ||||
| #~ msgid "Could not parse font description \"%s\" from GSettings key %s\n" | ||||
| #~ msgstr "" | ||||
| #~ "Non foi posíbel analizar a descrición do tipo de letra «%s» da chave " | ||||
| #~ "GSettings %s\n" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "\"%s\" found in configuration database is not a valid value for mouse " | ||||
| #~ "button modifier\n" | ||||
| #~ msgstr "" | ||||
| #~ "«%s» atopados na base de datos de configuración non é un valor correcto " | ||||
| #~ "para o modificador do botón do rato\n" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "\"%s\" found in configuration database is not a valid value for " | ||||
| #~ "keybinding \"%s\"\n" | ||||
| #~ msgstr "" | ||||
| #~ "«%s» atopados na base de datos de configuración non é un valor correcto " | ||||
| #~ "para a combinación de teclas «%s»\n" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Could not acquire window manager selection on screen %d display \"%s\"\n" | ||||
| #~ msgstr "" | ||||
| #~ "Non foi posíbel obter a selección do xestor de xanelas na pantalla %d na " | ||||
| #~ "visualización «%s»\n" | ||||
|  | ||||
| #~ msgid "Could not release screen %d on display \"%s\"\n" | ||||
| #~ msgstr "Non foi posíbel liberar a visualización %d na pantalla «%s»\n" | ||||
|  | ||||
| #~ msgid "Could not create directory '%s': %s\n" | ||||
| #~ msgstr "Non foi posíbel crear o directorio «%s»: %s\n" | ||||
|  | ||||
| #~ msgid "Could not open session file '%s' for writing: %s\n" | ||||
| #~ msgstr "" | ||||
| #~ "Non foi posíbel abrir o ficheiro de sesión «%s» para escritura: %s\n" | ||||
|  | ||||
| #~ msgid "Error writing session file '%s': %s\n" | ||||
| #~ msgstr "Produciuse un erro ao escribir o ficheiro de sesión «%s»: %s\n" | ||||
|  | ||||
| #~ msgid "Error closing session file '%s': %s\n" | ||||
| #~ msgstr "Produciuse un erro ao pechar o ficheiro de sesión «%s»: %s\n" | ||||
|  | ||||
| #~ msgid "Failed to parse saved session file: %s\n" | ||||
| #~ msgstr "Produciuse un erro ao analizar o ficheiro de sesión gardado: %s\n" | ||||
|  | ||||
| #~ msgid "<mutter_session> attribute seen but we already have the session ID" | ||||
| #~ msgstr "O atributo <mutter_session> foi visto pero xa temos o ID de sesión" | ||||
|  | ||||
| #~ msgid "Unknown attribute %s on <%s> element" | ||||
| #~ msgstr "Atributo descoñecido %s no elemento <%s>" | ||||
|  | ||||
| #~ msgid "nested <window> tag" | ||||
| #~ msgstr "etiqueta <window> aniñada" | ||||
|  | ||||
| #~ msgid "Unknown element %s" | ||||
| #~ msgstr "Elemento descoñecido %s" | ||||
|  | ||||
| #~ msgid "Failed to open debug log: %s\n" | ||||
| #~ msgstr "Produciuse un erro ao abrir o rexistro de depuración: %s\n" | ||||
|  | ||||
| #~ msgid "Failed to fdopen() log file %s: %s\n" | ||||
| #~ msgstr "" | ||||
| #~ "Produciuse un erro ao facer fdopen() no ficheiro de rexistro %s: %s\n" | ||||
|  | ||||
| #~ msgid "Opened log file %s\n" | ||||
| #~ msgstr "Ficheiro de rexistro %s aberto\n" | ||||
|  | ||||
| #~ msgid "Window manager: " | ||||
| #~ msgstr "Xestor de xanelas: " | ||||
|  | ||||
| #~ msgid "Bug in window manager: " | ||||
| #~ msgstr "Fallo no xestor de xanelas: " | ||||
|  | ||||
| #~ msgid "Window manager warning: " | ||||
| #~ msgstr "Aviso do xestor de xanelas: " | ||||
|  | ||||
| #~ msgid "Window manager error: " | ||||
| #~ msgstr "Erro do xestor de xanelas: " | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER " | ||||
| #~ "window as specified in the ICCCM.\n" | ||||
| #~ msgstr "" | ||||
| #~ "A xanela %s estabelece SM_CLIENT_ID sobre si mesma en vez de facelo na " | ||||
| #~ "xanela WM_CLIENT_LEADER como está especificado no ICCCM.\n" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Window %s sets an MWM hint indicating it isn't resizable, but sets min " | ||||
| #~ "size %d x %d and max size %d x %d; this doesn't make much sense.\n" | ||||
| #~ msgstr "" | ||||
| #~ "A xanela %s estabeleceu a propiedade MWM indicando que non é " | ||||
| #~ "redimensionábel mais configurou o tamaño mínimo a %d x %d e o tamaño " | ||||
| #~ "máximo a %d x %d, isto non ten moito sentido.\n" | ||||
|  | ||||
| #~ msgid "Application set a bogus _NET_WM_PID %lu\n" | ||||
| #~ msgstr "O aplicativo configurou un _NET_WM_PID %lu falso\n" | ||||
|  | ||||
| #~ msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n" | ||||
| #~ msgstr "" | ||||
| #~ "WM_TRANSIENT_FOR non válido para a xanela 0x%lx especificada para %s.\n" | ||||
|  | ||||
| #~ msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n" | ||||
| #~ msgstr "WM_TRANSIENT_FOR xanela 0x%lx para %s crearía un bucle.\n" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Window 0x%lx has property %s\n" | ||||
| #~ "that was expected to have type %s format %d\n" | ||||
| #~ "and actually has type %s format %d n_items %d.\n" | ||||
| #~ "This is most likely an application bug, not a window manager bug.\n" | ||||
| #~ "The window has title=\"%s\" class=\"%s\" name=\"%s\"\n" | ||||
| #~ msgstr "" | ||||
| #~ "A xanela 0x%lx ten a propiedade %s\n" | ||||
| #~ "que se esperaba que tivese o tipo %s co formato %d\n" | ||||
| #~ "e actualmente ten un tipo %s co formato %d e n_items %d.\n" | ||||
| #~ "Isto non parece ser un fallo do aplicativo nin do xestor de xanelas.\n" | ||||
| #~ "A xanela ten título=«%s» a clase=«%s» e o nome=«%s»\n" | ||||
|  | ||||
| #~ msgid "Property %s on window 0x%lx contained invalid UTF-8\n" | ||||
| #~ msgstr "A propiedade %s na xanela 0x%lx contén UTF-8 non válido\n" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Property %s on window 0x%lx contained invalid UTF-8 for item %d in the " | ||||
| #~ "list\n" | ||||
| #~ msgstr "" | ||||
| #~ "A propiedade %s na xanela 0x%lx contén UTF-8 non válido para o elemento " | ||||
| #~ "da lista %d\n" | ||||
|  | ||||
| #~ msgid "Usage: %s\n" | ||||
| #~ msgstr "Uso: %s\n" | ||||
|  | ||||
| @@ -1806,6 +1836,15 @@ msgstr "%s (en %s)" | ||||
| #~ msgid "Put Window On Only One Workspace" | ||||
| #~ msgstr "Pór a xanela nun só espazo de traballo" | ||||
|  | ||||
| #~ msgid "Switch to workspace 5" | ||||
| #~ msgstr "Cambiar ao espazo de traballo 5" | ||||
|  | ||||
| #~ msgid "Switch to workspace 6" | ||||
| #~ msgstr "Cambiar ao espazo de traballo 6" | ||||
|  | ||||
| #~ msgid "Switch to workspace 7" | ||||
| #~ msgstr "Cambiar ao espazo de traballo 7" | ||||
|  | ||||
| #~ msgid "Switch to workspace 8" | ||||
| #~ msgstr "Cambiar ao espazo de traballo 8" | ||||
|  | ||||
|   | ||||
							
								
								
									
										593
									
								
								po/he.po
									
									
									
									
									
								
							
							
						
						
									
										593
									
								
								po/he.po
									
									
									
									
									
								
							| @@ -10,8 +10,8 @@ msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: metacity.HEAD.he\n" | ||||
| "Report-Msgid-Bugs-To: \n" | ||||
| "POT-Creation-Date: 2014-04-27 03:52+0300\n" | ||||
| "PO-Revision-Date: 2014-04-27 03:52+0300\n" | ||||
| "POT-Creation-Date: 2014-03-02 01:10+0200\n" | ||||
| "PO-Revision-Date: 2014-03-02 01:11+0200\n" | ||||
| "Last-Translator: Yosef Or Boczko <yoseforb@gnome.org>\n" | ||||
| "Language-Team: עברית <>\n" | ||||
| "Language: he\n" | ||||
| @@ -42,106 +42,98 @@ msgid "Move window to workspace 4" | ||||
| msgstr "העברה החלון למרחב עבודה 4" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:6 | ||||
| msgid "Move window to last workspace" | ||||
| msgstr "העברת החלון למרחב העבודה האחרון" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:7 | ||||
| msgid "Move window one workspace to the left" | ||||
| msgstr "העברת החלון למרחב העבודה שמשמאל" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:8 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:7 | ||||
| msgid "Move window one workspace to the right" | ||||
| msgstr "העברת החלון למרחב העבודה שמימין" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:9 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:8 | ||||
| msgid "Move window one workspace up" | ||||
| msgstr "העברת החלון למרחב העבודה שמלמעלה" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:10 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:9 | ||||
| msgid "Move window one workspace down" | ||||
| msgstr "העברת החלון למרחב העבודה שמלמטה" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:11 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:10 | ||||
| msgid "Move window one monitor to the left" | ||||
| msgstr "העברת החלון לצג שמשמאל" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:12 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:11 | ||||
| msgid "Move window one monitor to the right" | ||||
| msgstr "העברת החלון לצג שמימין" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:13 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:12 | ||||
| msgid "Move window one monitor up" | ||||
| msgstr "העברת החלון לצג שמלמעלה" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:14 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:13 | ||||
| msgid "Move window one monitor down" | ||||
| msgstr "העברת החלון לצג שמלמטה" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:15 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:14 | ||||
| msgid "Switch applications" | ||||
| msgstr "החלפה בין יישומים" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:16 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:15 | ||||
| msgid "Switch windows" | ||||
| msgstr "החלפת חלונות" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:17 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:16 | ||||
| msgid "Switch windows of an application" | ||||
| msgstr "החלפה בין חלונות של יישום" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:18 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:17 | ||||
| msgid "Switch system controls" | ||||
| msgstr "החלפה בין פקדי המערכת" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:19 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:18 | ||||
| msgid "Switch windows directly" | ||||
| msgstr "החלפת החלונות באופן ישיר" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:20 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:19 | ||||
| msgid "Switch windows of an app directly" | ||||
| msgstr "החלפת חלונות של יישום באופן ישיר" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:21 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:20 | ||||
| msgid "Switch system controls directly" | ||||
| msgstr "החלפת פקדי המערכת באופן ישיר" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:22 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:21 | ||||
| msgid "Hide all normal windows" | ||||
| msgstr "הסתרת כל החלונות הרגילים" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:23 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:22 | ||||
| msgid "Switch to workspace 1" | ||||
| msgstr "מעבר למרחב עבודה 1" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:24 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:23 | ||||
| msgid "Switch to workspace 2" | ||||
| msgstr "מעבר למרחב עבודה 2" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:25 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:24 | ||||
| msgid "Switch to workspace 3" | ||||
| msgstr "מעבר למרחב עבודה 3" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:26 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:25 | ||||
| msgid "Switch to workspace 4" | ||||
| msgstr "מעבר למרחב עבודה 4" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:27 | ||||
| msgid "Switch to last workspace" | ||||
| msgstr "מעבר למרחב העבודה האחרון" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:28 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:26 | ||||
| msgid "Move to workspace left" | ||||
| msgstr "העברה למרחב העבודה לשמאל" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:29 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:27 | ||||
| msgid "Move to workspace right" | ||||
| msgstr "העברה למרחב העבודה לימין" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:30 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:28 | ||||
| msgid "Move to workspace above" | ||||
| msgstr "העברה למרחב העבודה שמלמעלה" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:31 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:29 | ||||
| msgid "Move to workspace below" | ||||
| msgstr "העברה למרחב העבודה שמלמטה" | ||||
|  | ||||
| @@ -233,116 +225,130 @@ msgstr "פיצול הצפייה משמאל" | ||||
| msgid "View split on right" | ||||
| msgstr "פיצול הצפייה מימין" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:412 | ||||
| msgid "Built-in display" | ||||
| msgstr "תצוגה מובנית" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:437 | ||||
| msgid "Unknown" | ||||
| msgstr "לא ידוע" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:439 | ||||
| msgid "Unknown Display" | ||||
| msgstr "תצוגה לא ידועה" | ||||
|  | ||||
| #. TRANSLATORS: this is a monitor vendor name, followed by a | ||||
| #. * size in inches, like 'Dell 15"' | ||||
| #. | ||||
| #: ../src/backends/meta-monitor-manager.c:447 | ||||
| #, c-format | ||||
| msgid "%s %s" | ||||
| msgstr "%s %s" | ||||
|  | ||||
| #. This probably means that a non-WM compositor like xcompmgr is running; | ||||
| #. * we have no way to get it to exit | ||||
| #: ../src/compositor/compositor.c:464 | ||||
| #: ../src/compositor/compositor.c:534 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Another compositing manager is already running on screen %i on display \"%s" | ||||
| "\"." | ||||
| msgstr "מנהל תצוגת חלונות אחר כבר פועל במסך %i בתצוגה „%s“." | ||||
|  | ||||
| #: ../src/compositor/meta-background.c:990 | ||||
| #: ../src/compositor/meta-background.c:1074 | ||||
| msgid "background texture could not be created from file" | ||||
| msgstr "לא ניתן ליצור מרקם רקע מקובץ" | ||||
|  | ||||
| #: ../src/core/bell.c:215 | ||||
| #: ../src/core/bell.c:321 | ||||
| msgid "Bell event" | ||||
| msgstr "אירוע פעמון" | ||||
|  | ||||
| #: ../src/core/delete.c:106 | ||||
| #: ../src/core/core.c:156 | ||||
| #, c-format | ||||
| msgid "Unknown window information request: %d" | ||||
| msgstr "Unknown window information request: %d" | ||||
|  | ||||
| #: ../src/core/delete.c:109 | ||||
| #, c-format | ||||
| msgid "“%s” is not responding." | ||||
| msgstr "„%s“ אינו מגיב." | ||||
|  | ||||
| #: ../src/core/delete.c:108 | ||||
| #: ../src/core/delete.c:111 | ||||
| msgid "Application is not responding." | ||||
| msgstr "היישום אינו מגיב." | ||||
|  | ||||
| #: ../src/core/delete.c:113 | ||||
| #: ../src/core/delete.c:116 | ||||
| msgid "" | ||||
| "You may choose to wait a short while for it to continue or force the " | ||||
| "application to quit entirely." | ||||
| msgstr "" | ||||
| "באפשרותך להמתין זמן קצר ולתת ליישום להמשיך או להכריח את היישום להסתיים." | ||||
|  | ||||
| #: ../src/core/delete.c:120 | ||||
| #: ../src/core/delete.c:123 | ||||
| msgid "_Wait" | ||||
| msgstr "ה_מתנה" | ||||
|  | ||||
| #: ../src/core/delete.c:120 | ||||
| #: ../src/core/delete.c:123 | ||||
| msgid "_Force Quit" | ||||
| msgstr "_אילוץ סגירה" | ||||
|  | ||||
| #: ../src/core/display.c:452 | ||||
| #: ../src/core/display.c:405 | ||||
| #, c-format | ||||
| msgid "Missing %s extension required for compositing" | ||||
| msgstr "Missing %s extension required for compositing" | ||||
|  | ||||
| #: ../src/core/display.c:497 | ||||
| #, c-format | ||||
| msgid "Failed to open X Window System display '%s'\n" | ||||
| msgstr "Failed to open X Window System display '%s'\n" | ||||
|  | ||||
| #: ../src/core/main.c:190 | ||||
| #: ../src/core/keybindings.c:1113 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Some other program is already using the key %s with modifiers %x as a " | ||||
| "binding\n" | ||||
| msgstr "תכנית אחרת כבר משתמשת במקש %s עם המקש %x כצירוף\n" | ||||
|  | ||||
| #: ../src/core/keybindings.c:1310 | ||||
| #, c-format | ||||
| msgid "\"%s\" is not a valid accelerator\n" | ||||
| msgstr "\"%s\" אינו מקש האצה תקני\n" | ||||
|  | ||||
| #: ../src/core/main.c:195 | ||||
| msgid "Disable connection to session manager" | ||||
| msgstr "Disable connection to session manager" | ||||
|  | ||||
| #: ../src/core/main.c:196 | ||||
| #: ../src/core/main.c:201 | ||||
| msgid "Replace the running window manager" | ||||
| msgstr "Replace the running window manager" | ||||
|  | ||||
| #: ../src/core/main.c:202 | ||||
| #: ../src/core/main.c:207 | ||||
| msgid "Specify session management ID" | ||||
| msgstr "Specify session management ID" | ||||
|  | ||||
| #: ../src/core/main.c:207 | ||||
| #: ../src/core/main.c:212 | ||||
| msgid "X Display to use" | ||||
| msgstr "X Display to use" | ||||
|  | ||||
| #: ../src/core/main.c:213 | ||||
| #: ../src/core/main.c:218 | ||||
| msgid "Initialize session from savefile" | ||||
| msgstr "Initialize session from savefile" | ||||
|  | ||||
| #: ../src/core/main.c:219 | ||||
| #: ../src/core/main.c:224 | ||||
| msgid "Make X calls synchronous" | ||||
| msgstr "Make X calls synchronous" | ||||
|  | ||||
| #: ../src/core/main.c:225 | ||||
| msgid "Run as a wayland compositor" | ||||
| msgstr "Run as a wayland compositor" | ||||
|  | ||||
| #: ../src/core/main.c:231 | ||||
| msgid "Run as a full display server, rather than nested" | ||||
| msgstr "Run as a full display server, rather than nested" | ||||
|  | ||||
| #: ../src/core/main.c:476 | ||||
| #: ../src/core/main.c:544 | ||||
| #, c-format | ||||
| msgid "Failed to scan themes directory: %s\n" | ||||
| msgstr "Failed to scan themes directory: %s\n" | ||||
|  | ||||
| #: ../src/core/main.c:492 | ||||
| #: ../src/core/main.c:560 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Could not find a theme! Be sure %s exists and contains the usual themes.\n" | ||||
| msgstr "" | ||||
| "Could not find a theme! Be sure %s exists and contains the usual themes.\n" | ||||
|  | ||||
| #: ../src/core/monitor.c:699 | ||||
| msgid "Built-in display" | ||||
| msgstr "תצוגה מובנית" | ||||
|  | ||||
| #: ../src/core/monitor.c:724 | ||||
| msgid "Unknown" | ||||
| msgstr "לא ידוע" | ||||
|  | ||||
| #: ../src/core/monitor.c:726 | ||||
| msgid "Unknown Display" | ||||
| msgstr "תצוגה לא ידועה" | ||||
|  | ||||
| #. TRANSLATORS: this is a monitor vendor name, followed by a | ||||
| #. * size in inches, like 'Dell 15"' | ||||
| #. | ||||
| #: ../src/core/monitor.c:734 | ||||
| #, c-format | ||||
| msgid "%s %s" | ||||
| msgstr "%s %s" | ||||
|  | ||||
| #: ../src/core/mutter.c:39 | ||||
| #, c-format | ||||
| msgid "" | ||||
| @@ -365,17 +371,48 @@ msgstr "Print version" | ||||
| msgid "Mutter plugin to use" | ||||
| msgstr "תוסף ה־mutter לשימוש" | ||||
|  | ||||
| #: ../src/core/prefs.c:2005 | ||||
| #: ../src/core/prefs.c:1190 | ||||
| msgid "" | ||||
| "Workarounds for broken applications disabled. Some applications may not " | ||||
| "behave properly.\n" | ||||
| msgstr "" | ||||
| "Workarounds for broken applications disabled. Some applications may not " | ||||
| "behave properly.\n" | ||||
|  | ||||
| #: ../src/core/prefs.c:1265 | ||||
| #, c-format | ||||
| msgid "Could not parse font description \"%s\" from GSettings key %s\n" | ||||
| msgstr "Could not parse font description \"%s\" from GSettings key %s\n" | ||||
|  | ||||
| #: ../src/core/prefs.c:1331 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "\"%s\" found in configuration database is not a valid value for mouse button " | ||||
| "modifier\n" | ||||
| msgstr "" | ||||
| "\"%s\" found in configuration database is not a valid value for mouse button " | ||||
| "modifier\n" | ||||
|  | ||||
| #: ../src/core/prefs.c:1894 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "\"%s\" found in configuration database is not a valid value for keybinding " | ||||
| "\"%s\"\n" | ||||
| msgstr "" | ||||
| "\"%s\" found in configuration database is not a valid value for keybinding " | ||||
| "\"%s\"\n" | ||||
|  | ||||
| #: ../src/core/prefs.c:1984 | ||||
| #, c-format | ||||
| msgid "Workspace %d" | ||||
| msgstr "מרחב עבודה %d" | ||||
|  | ||||
| #: ../src/core/screen.c:543 | ||||
| #: ../src/core/screen.c:539 | ||||
| #, c-format | ||||
| msgid "Screen %d on display '%s' is invalid\n" | ||||
| msgstr "Screen %d on display '%s' is invalid\n" | ||||
|  | ||||
| #: ../src/core/screen.c:559 | ||||
| #: ../src/core/screen.c:555 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Screen %d on display \"%s\" already has a window manager; try using the --" | ||||
| @@ -384,23 +421,190 @@ msgstr "" | ||||
| "Screen %d on display \"%s\" already has a window manager; try using the --" | ||||
| "replace option to replace the current window manager.\n" | ||||
|  | ||||
| #: ../src/core/screen.c:664 | ||||
| #: ../src/core/screen.c:582 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Could not acquire window manager selection on screen %d display \"%s\"\n" | ||||
| msgstr "" | ||||
| "Could not acquire window manager selection on screen %d display \"%s\"\n" | ||||
|  | ||||
| #: ../src/core/screen.c:660 | ||||
| #, c-format | ||||
| msgid "Screen %d on display \"%s\" already has a window manager\n" | ||||
| msgstr "Screen %d on display \"%s\" already has a window manager\n" | ||||
|  | ||||
| #: ../src/core/util.c:118 | ||||
| #: ../src/core/screen.c:848 | ||||
| #, c-format | ||||
| msgid "Could not release screen %d on display \"%s\"\n" | ||||
| msgstr "Could not release screen %d on display \"%s\"\n" | ||||
|  | ||||
| #: ../src/core/session.c:842 ../src/core/session.c:849 | ||||
| #, c-format | ||||
| msgid "Could not create directory '%s': %s\n" | ||||
| msgstr "Could not create directory '%s': %s\n" | ||||
|  | ||||
| #: ../src/core/session.c:859 | ||||
| #, c-format | ||||
| msgid "Could not open session file '%s' for writing: %s\n" | ||||
| msgstr "Could not open session file '%s' for writing: %s\n" | ||||
|  | ||||
| #: ../src/core/session.c:1000 | ||||
| #, c-format | ||||
| msgid "Error writing session file '%s': %s\n" | ||||
| msgstr "Error writing session file '%s': %s\n" | ||||
|  | ||||
| #: ../src/core/session.c:1005 | ||||
| #, c-format | ||||
| msgid "Error closing session file '%s': %s\n" | ||||
| msgstr "Error closing session file '%s': %s\n" | ||||
|  | ||||
| #: ../src/core/session.c:1135 | ||||
| #, c-format | ||||
| msgid "Failed to parse saved session file: %s\n" | ||||
| msgstr "Failed to parse saved session file: %s\n" | ||||
|  | ||||
| #: ../src/core/session.c:1184 | ||||
| #, c-format | ||||
| msgid "<mutter_session> attribute seen but we already have the session ID" | ||||
| msgstr "התכונה <mutter_session> מופיעה אך כבר יש בידינו את מספר זיהוי ההפעלה" | ||||
|  | ||||
| #: ../src/core/session.c:1197 ../src/core/session.c:1272 | ||||
| #: ../src/core/session.c:1304 ../src/core/session.c:1376 | ||||
| #: ../src/core/session.c:1436 | ||||
| #, c-format | ||||
| msgid "Unknown attribute %s on <%s> element" | ||||
| msgstr "Unknown attribute %s on <%s> element" | ||||
|  | ||||
| #: ../src/core/session.c:1214 | ||||
| #, c-format | ||||
| msgid "nested <window> tag" | ||||
| msgstr "nested <window> tag" | ||||
|  | ||||
| #: ../src/core/session.c:1456 | ||||
| #, c-format | ||||
| msgid "Unknown element %s" | ||||
| msgstr "Unknown element %s" | ||||
|  | ||||
| #: ../src/core/session.c:1808 | ||||
| msgid "" | ||||
| "These windows do not support "save current setup" and will have to " | ||||
| "be restarted manually next time you log in." | ||||
| msgstr "" | ||||
| "חלונות אלו אינם תומכים ב"שמירת ההגדרות הנוכחיות", ויהיה צורך " | ||||
| "באתחול ידני בכניסה הבאה שלך." | ||||
|  | ||||
| #: ../src/core/util.c:82 | ||||
| #, c-format | ||||
| msgid "Failed to open debug log: %s\n" | ||||
| msgstr "Failed to open debug log: %s\n" | ||||
|  | ||||
| #: ../src/core/util.c:92 | ||||
| #, c-format | ||||
| msgid "Failed to fdopen() log file %s: %s\n" | ||||
| msgstr "Failed to fdopen() log file %s: %s\n" | ||||
|  | ||||
| #: ../src/core/util.c:98 | ||||
| #, c-format | ||||
| msgid "Opened log file %s\n" | ||||
| msgstr "Opened log file %s\n" | ||||
|  | ||||
| #: ../src/core/util.c:117 | ||||
| msgid "Mutter was compiled without support for verbose mode\n" | ||||
| msgstr "Mutter הודר ללא תמיכה במצב פירוט\n" | ||||
|  | ||||
| #: ../src/mutter.desktop.in.h:1 | ||||
| #: ../src/core/util.c:262 | ||||
| msgid "Window manager: " | ||||
| msgstr "Window manager: " | ||||
|  | ||||
| #: ../src/core/util.c:412 | ||||
| msgid "Bug in window manager: " | ||||
| msgstr "Bug in window manager: " | ||||
|  | ||||
| #: ../src/core/util.c:443 | ||||
| msgid "Window manager warning: " | ||||
| msgstr "Window manager warning: " | ||||
|  | ||||
| #: ../src/core/util.c:471 | ||||
| msgid "Window manager error: " | ||||
| msgstr "Window manager error: " | ||||
|  | ||||
| #. first time through | ||||
| #: ../src/core/window.c:7564 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER " | ||||
| "window as specified in the ICCCM.\n" | ||||
| msgstr "" | ||||
| "Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER " | ||||
| "window as specified in the ICCCM.\n" | ||||
|  | ||||
| #. We ignore mwm_has_resize_func because WM_NORMAL_HINTS is the | ||||
| #. * authoritative source for that info. Some apps such as mplayer or | ||||
| #. * xine disable resize via MWM but not WM_NORMAL_HINTS, but that | ||||
| #. * leads to e.g. us not fullscreening their windows.  Apps that set | ||||
| #. * MWM but not WM_NORMAL_HINTS are basically broken. We complain | ||||
| #. * about these apps but make them work. | ||||
| #. | ||||
| #: ../src/core/window.c:8489 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Window %s sets an MWM hint indicating it isn't resizable, but sets min size " | ||||
| "%d x %d and max size %d x %d; this doesn't make much sense.\n" | ||||
| msgstr "" | ||||
| "Window %s sets an MWM hint indicating it isn't resizable, but sets min size " | ||||
| "%d x %d and max size %d x %d; this doesn't make much sense.\n" | ||||
|  | ||||
| #: ../src/core/window-props.c:349 | ||||
| #, c-format | ||||
| msgid "Application set a bogus _NET_WM_PID %lu\n" | ||||
| msgstr "Application set a bogus _NET_WM_PID %lu\n" | ||||
|  | ||||
| #: ../src/core/window-props.c:465 | ||||
| #, c-format | ||||
| msgid "%s (on %s)" | ||||
| msgstr "%s (מעל %s)" | ||||
|  | ||||
| #: ../src/core/window-props.c:1548 | ||||
| #, c-format | ||||
| msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n" | ||||
| msgstr "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n" | ||||
|  | ||||
| #: ../src/core/window-props.c:1559 | ||||
| #, c-format | ||||
| msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n" | ||||
| msgstr "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n" | ||||
|  | ||||
| #: ../src/core/xprops.c:153 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Window 0x%lx has property %s\n" | ||||
| "that was expected to have type %s format %d\n" | ||||
| "and actually has type %s format %d n_items %d.\n" | ||||
| "This is most likely an application bug, not a window manager bug.\n" | ||||
| "The window has title=\"%s\" class=\"%s\" name=\"%s\"\n" | ||||
| msgstr "" | ||||
| "Window 0x%lx has property %s\n" | ||||
| "that was expected to have type %s format %d\n" | ||||
| "and actually has type %s format %d n_items %d.\n" | ||||
| "This is most likely an application bug, not a window manager bug.\n" | ||||
| "The window has title=\"%s\" class=\"%s\" name=\"%s\"\n" | ||||
|  | ||||
| #: ../src/core/xprops.c:409 | ||||
| #, c-format | ||||
| msgid "Property %s on window 0x%lx contained invalid UTF-8\n" | ||||
| msgstr "Property %s on window 0x%lx contained invalid UTF-8\n" | ||||
|  | ||||
| #: ../src/core/xprops.c:492 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Property %s on window 0x%lx contained invalid UTF-8 for item %d in the list\n" | ||||
| msgstr "" | ||||
| "Property %s on window 0x%lx contained invalid UTF-8 for item %d in the list\n" | ||||
|  | ||||
| #: ../src/mutter.desktop.in.h:1 ../src/mutter-wm.desktop.in.h:1 | ||||
| msgid "Mutter" | ||||
| msgstr "Mutter" | ||||
|  | ||||
| #: ../src/mutter-wayland.desktop.in.h:1 | ||||
| msgid "Mutter (wayland compositor)" | ||||
| msgstr "Mutter (wayland מסדר)" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.gschema.xml.in.h:1 | ||||
| msgid "Modifier to use for extended window management operations" | ||||
| msgstr "Modifier to use for extended window management operations" | ||||
| @@ -522,53 +726,13 @@ msgstr "" | ||||
| "automatically get maximized." | ||||
|  | ||||
| #: ../src/org.gnome.mutter.gschema.xml.in.h:19 | ||||
| msgid "Place new windows in the center" | ||||
| msgstr "Place new windows in the center" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.gschema.xml.in.h:20 | ||||
| msgid "" | ||||
| "When true, the new windows will always be put in the center of the active " | ||||
| "screen of the monitor." | ||||
| msgstr "" | ||||
| "When true, the new windows will always be put in the center of the active " | ||||
| "screen of the monitor." | ||||
|  | ||||
| #: ../src/org.gnome.mutter.gschema.xml.in.h:21 | ||||
| msgid "Select window from tab popup" | ||||
| msgstr "Select window from tab popup" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.gschema.xml.in.h:22 | ||||
| #: ../src/org.gnome.mutter.gschema.xml.in.h:20 | ||||
| msgid "Cancel tab popup" | ||||
| msgstr "Cancel tab popup" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:1 | ||||
| msgid "Switch to VT 1" | ||||
| msgstr "מעבר ל־VT 1" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:2 | ||||
| msgid "Switch to VT 2" | ||||
| msgstr "מעבר ל־VT 2" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:3 | ||||
| msgid "Switch to VT 3" | ||||
| msgstr "מעבר ל־VT 3" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:4 | ||||
| msgid "Switch to VT 4" | ||||
| msgstr "מעבר ל־VT 4" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:5 | ||||
| msgid "Switch to VT 5" | ||||
| msgstr "מעבר ל־VT 5" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:6 | ||||
| msgid "Switch to VT 6" | ||||
| msgstr "מעבר ל־VT 6" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:7 | ||||
| msgid "Switch to VT 7" | ||||
| msgstr "מעבר ל־VT 7" | ||||
|  | ||||
| #. Translators: Translate this string the same way as you do in libwnck! | ||||
| #: ../src/ui/menu.c:65 | ||||
| msgid "Mi_nimize" | ||||
| @@ -651,22 +815,22 @@ msgstr "הזזת החלון למרחב העבודה שלמ_טה" | ||||
| msgid "_Close" | ||||
| msgstr "_סגור" | ||||
|  | ||||
| #: ../src/ui/menu.c:198 | ||||
| #: ../src/ui/menu.c:200 | ||||
| #, c-format | ||||
| msgid "Workspace %d%n" | ||||
| msgstr "מרחב עבודה %d%n" | ||||
|  | ||||
| #: ../src/ui/menu.c:208 | ||||
| #: ../src/ui/menu.c:210 | ||||
| #, c-format | ||||
| msgid "Workspace 1_0" | ||||
| msgstr "מרחב עבודה 1_0" | ||||
|  | ||||
| #: ../src/ui/menu.c:210 | ||||
| #: ../src/ui/menu.c:212 | ||||
| #, c-format | ||||
| msgid "Workspace %s%d" | ||||
| msgstr "מרחב עבודה %s%d" | ||||
|  | ||||
| #: ../src/ui/menu.c:380 | ||||
| #: ../src/ui/menu.c:382 | ||||
| msgid "Move to Another _Workspace" | ||||
| msgstr "הזז_ת החלון למרחב עבודה אחר" | ||||
|  | ||||
| @@ -1433,160 +1597,6 @@ msgstr "<%s> צוין פעמיים עבור ערכת נושא זו" | ||||
| msgid "Failed to find a valid file for theme %s\n" | ||||
| msgstr "Failed to find a valid file for theme %s\n" | ||||
|  | ||||
| #: ../src/x11/session.c:1815 | ||||
| msgid "" | ||||
| "These windows do not support "save current setup" and will have to " | ||||
| "be restarted manually next time you log in." | ||||
| msgstr "" | ||||
| "חלונות אלו אינם תומכים ב"שמירת ההגדרות הנוכחיות", ויהיה צורך " | ||||
| "באתחול ידני בכניסה הבאה שלך." | ||||
|  | ||||
| #: ../src/x11/window-props.c:465 | ||||
| #, c-format | ||||
| msgid "%s (on %s)" | ||||
| msgstr "%s (מעל %s)" | ||||
|  | ||||
| #~ msgid "Unknown window information request: %d" | ||||
| #~ msgstr "Unknown window information request: %d" | ||||
|  | ||||
| #~ msgid "Missing %s extension required for compositing" | ||||
| #~ msgstr "Missing %s extension required for compositing" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Some other program is already using the key %s with modifiers %x as a " | ||||
| #~ "binding\n" | ||||
| #~ msgstr "תכנית אחרת כבר משתמשת במקש %s עם המקש %x כצירוף\n" | ||||
|  | ||||
| #~ msgid "\"%s\" is not a valid accelerator\n" | ||||
| #~ msgstr "\"%s\" אינו מקש האצה תקני\n" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Workarounds for broken applications disabled. Some applications may not " | ||||
| #~ "behave properly.\n" | ||||
| #~ msgstr "" | ||||
| #~ "Workarounds for broken applications disabled. Some applications may not " | ||||
| #~ "behave properly.\n" | ||||
|  | ||||
| #~ msgid "Could not parse font description \"%s\" from GSettings key %s\n" | ||||
| #~ msgstr "Could not parse font description \"%s\" from GSettings key %s\n" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "\"%s\" found in configuration database is not a valid value for mouse " | ||||
| #~ "button modifier\n" | ||||
| #~ msgstr "" | ||||
| #~ "\"%s\" found in configuration database is not a valid value for mouse " | ||||
| #~ "button modifier\n" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "\"%s\" found in configuration database is not a valid value for " | ||||
| #~ "keybinding \"%s\"\n" | ||||
| #~ msgstr "" | ||||
| #~ "\"%s\" found in configuration database is not a valid value for " | ||||
| #~ "keybinding \"%s\"\n" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Could not acquire window manager selection on screen %d display \"%s\"\n" | ||||
| #~ msgstr "" | ||||
| #~ "Could not acquire window manager selection on screen %d display \"%s\"\n" | ||||
|  | ||||
| #~ msgid "Could not release screen %d on display \"%s\"\n" | ||||
| #~ msgstr "Could not release screen %d on display \"%s\"\n" | ||||
|  | ||||
| #~ msgid "Could not create directory '%s': %s\n" | ||||
| #~ msgstr "Could not create directory '%s': %s\n" | ||||
|  | ||||
| #~ msgid "Could not open session file '%s' for writing: %s\n" | ||||
| #~ msgstr "Could not open session file '%s' for writing: %s\n" | ||||
|  | ||||
| #~ msgid "Error writing session file '%s': %s\n" | ||||
| #~ msgstr "Error writing session file '%s': %s\n" | ||||
|  | ||||
| #~ msgid "Error closing session file '%s': %s\n" | ||||
| #~ msgstr "Error closing session file '%s': %s\n" | ||||
|  | ||||
| #~ msgid "Failed to parse saved session file: %s\n" | ||||
| #~ msgstr "Failed to parse saved session file: %s\n" | ||||
|  | ||||
| #~ msgid "<mutter_session> attribute seen but we already have the session ID" | ||||
| #~ msgstr "" | ||||
| #~ "התכונה <mutter_session> מופיעה אך כבר יש בידינו את מספר זיהוי ההפעלה" | ||||
|  | ||||
| #~ msgid "Unknown attribute %s on <%s> element" | ||||
| #~ msgstr "Unknown attribute %s on <%s> element" | ||||
|  | ||||
| #~ msgid "nested <window> tag" | ||||
| #~ msgstr "nested <window> tag" | ||||
|  | ||||
| #~ msgid "Unknown element %s" | ||||
| #~ msgstr "Unknown element %s" | ||||
|  | ||||
| #~ msgid "Failed to open debug log: %s\n" | ||||
| #~ msgstr "Failed to open debug log: %s\n" | ||||
|  | ||||
| #~ msgid "Failed to fdopen() log file %s: %s\n" | ||||
| #~ msgstr "Failed to fdopen() log file %s: %s\n" | ||||
|  | ||||
| #~ msgid "Opened log file %s\n" | ||||
| #~ msgstr "Opened log file %s\n" | ||||
|  | ||||
| #~ msgid "Window manager: " | ||||
| #~ msgstr "Window manager: " | ||||
|  | ||||
| #~ msgid "Bug in window manager: " | ||||
| #~ msgstr "Bug in window manager: " | ||||
|  | ||||
| #~ msgid "Window manager warning: " | ||||
| #~ msgstr "Window manager warning: " | ||||
|  | ||||
| #~ msgid "Window manager error: " | ||||
| #~ msgstr "Window manager error: " | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER " | ||||
| #~ "window as specified in the ICCCM.\n" | ||||
| #~ msgstr "" | ||||
| #~ "Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER " | ||||
| #~ "window as specified in the ICCCM.\n" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Window %s sets an MWM hint indicating it isn't resizable, but sets min " | ||||
| #~ "size %d x %d and max size %d x %d; this doesn't make much sense.\n" | ||||
| #~ msgstr "" | ||||
| #~ "Window %s sets an MWM hint indicating it isn't resizable, but sets min " | ||||
| #~ "size %d x %d and max size %d x %d; this doesn't make much sense.\n" | ||||
|  | ||||
| #~ msgid "Application set a bogus _NET_WM_PID %lu\n" | ||||
| #~ msgstr "Application set a bogus _NET_WM_PID %lu\n" | ||||
|  | ||||
| #~ msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n" | ||||
| #~ msgstr "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n" | ||||
|  | ||||
| #~ msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n" | ||||
| #~ msgstr "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Window 0x%lx has property %s\n" | ||||
| #~ "that was expected to have type %s format %d\n" | ||||
| #~ "and actually has type %s format %d n_items %d.\n" | ||||
| #~ "This is most likely an application bug, not a window manager bug.\n" | ||||
| #~ "The window has title=\"%s\" class=\"%s\" name=\"%s\"\n" | ||||
| #~ msgstr "" | ||||
| #~ "Window 0x%lx has property %s\n" | ||||
| #~ "that was expected to have type %s format %d\n" | ||||
| #~ "and actually has type %s format %d n_items %d.\n" | ||||
| #~ "This is most likely an application bug, not a window manager bug.\n" | ||||
| #~ "The window has title=\"%s\" class=\"%s\" name=\"%s\"\n" | ||||
|  | ||||
| #~ msgid "Property %s on window 0x%lx contained invalid UTF-8\n" | ||||
| #~ msgstr "Property %s on window 0x%lx contained invalid UTF-8\n" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Property %s on window 0x%lx contained invalid UTF-8 for item %d in the " | ||||
| #~ "list\n" | ||||
| #~ msgstr "" | ||||
| #~ "Property %s on window 0x%lx contained invalid UTF-8 for item %d in the " | ||||
| #~ "list\n" | ||||
|  | ||||
| #~ msgid "Usage: %s\n" | ||||
| #~ msgstr "שימוש: %s\n" | ||||
|  | ||||
| @@ -1782,6 +1792,15 @@ msgstr "%s (מעל %s)" | ||||
| #~ msgid "Put Window On Only One Workspace" | ||||
| #~ msgstr "הראה את החלון על סביבת עבודה אחת בלבד" | ||||
|  | ||||
| #~ msgid "Switch to workspace 5" | ||||
| #~ msgstr "מעבר למרחב עבודה 5" | ||||
|  | ||||
| #~ msgid "Switch to workspace 6" | ||||
| #~ msgstr "מעבר למרחב עבודה 6" | ||||
|  | ||||
| #~ msgid "Switch to workspace 7" | ||||
| #~ msgstr "מעבר למרחב עבודה 7" | ||||
|  | ||||
| #~ msgid "Switch to workspace 8" | ||||
| #~ msgstr "מעבר למרחב עבודה 8" | ||||
|  | ||||
|   | ||||
							
								
								
									
										620
									
								
								po/id.po
									
									
									
									
									
								
							
							
						
						
									
										620
									
								
								po/id.po
									
									
									
									
									
								
							| @@ -4,22 +4,22 @@ | ||||
| # | ||||
| # Mohammad DAMT <mdamt@bisnisweb.com>, 2003-2005. | ||||
| # Ahmad Riza H Nst  <rizahnst@eriagempita.co.id>, 2006. | ||||
| # Dirgita <dirgitadevina@yahoo.co.id>, 2011, 2012, 2014. | ||||
| # Dirgita <dirgitadevina@yahoo.co.id>, 2011, 2012. | ||||
| # Andika Triwidada <andika@gmail.com>, 2011, 2012, 2013, 2014. | ||||
| msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: mutter master\n" | ||||
| "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" | ||||
| "product=mutter&keywords=I18N+L10N&component=general\n" | ||||
| "POT-Creation-Date: 2014-04-22 20:56+0000\n" | ||||
| "PO-Revision-Date: 2014-04-22 21:23+0700\n" | ||||
| "Last-Translator: Dirgita <dirgitadevina@yahoo.co.id>\n" | ||||
| "Language-Team: Indonesian <gnome-l10n-id@googlegroups.com>\n" | ||||
| "Language: Indonesian\n" | ||||
| "POT-Creation-Date: 2014-03-20 22:58+0000\n" | ||||
| "PO-Revision-Date: 2014-03-21 17:41+0700\n" | ||||
| "Last-Translator: Andika Triwidada <andika@gmail.com>\n" | ||||
| "Language-Team: Indonesian <gnome@i15n.org>\n" | ||||
| "Language: id\n" | ||||
| "MIME-Version: 1.0\n" | ||||
| "Content-Type: text/plain; charset=UTF-8\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
| "X-Generator: Lokalize 1.5\n" | ||||
| "X-Generator: Poedit 1.5.7\n" | ||||
| "Plural-Forms: nplurals=1; plural=0;\n" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:1 | ||||
| @@ -43,108 +43,98 @@ msgid "Move window to workspace 4" | ||||
| msgstr "Pindahkan jendela ke area kerja 4" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:6 | ||||
| #| msgid "Move window to workspace 1" | ||||
| msgid "Move window to last workspace" | ||||
| msgstr "Pindahkan jendela ke area kerja terakhir" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:7 | ||||
| msgid "Move window one workspace to the left" | ||||
| msgstr "Pindahkan jendela satu area kerja ke kiri" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:8 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:7 | ||||
| msgid "Move window one workspace to the right" | ||||
| msgstr "Pindahkan jendela satu area kerja ke kanan" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:9 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:8 | ||||
| msgid "Move window one workspace up" | ||||
| msgstr "Pindahkan jendela ke area kerja atas" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:10 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:9 | ||||
| msgid "Move window one workspace down" | ||||
| msgstr "Pindahkan jendela ke area kerja bawah" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:11 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:10 | ||||
| msgid "Move window one monitor to the left" | ||||
| msgstr "Pindahkan jendela satu monitor ke kiri" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:12 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:11 | ||||
| msgid "Move window one monitor to the right" | ||||
| msgstr "Pindahkan jendela satu monitor ke kanan" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:13 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:12 | ||||
| msgid "Move window one monitor up" | ||||
| msgstr "Pindahkan jendela satu monitor ke atas" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:14 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:13 | ||||
| msgid "Move window one monitor down" | ||||
| msgstr "Pindahkan jendela satu monitor ke bawah" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:15 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:14 | ||||
| msgid "Switch applications" | ||||
| msgstr "Berpindah aplikasi" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:16 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:15 | ||||
| msgid "Switch windows" | ||||
| msgstr "Berpindah jendela" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:17 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:16 | ||||
| msgid "Switch windows of an application" | ||||
| msgstr "Berpindah jendela aplikasi" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:18 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:17 | ||||
| msgid "Switch system controls" | ||||
| msgstr "Berpindah kendali sistem" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:19 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:18 | ||||
| msgid "Switch windows directly" | ||||
| msgstr "Berpindah jendela secara langsung" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:20 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:19 | ||||
| msgid "Switch windows of an app directly" | ||||
| msgstr "Berpindah jendela aplikasi secara langsung" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:21 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:20 | ||||
| msgid "Switch system controls directly" | ||||
| msgstr "Berpindah kendali sistem secara langsung" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:22 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:21 | ||||
| msgid "Hide all normal windows" | ||||
| msgstr "Menyembunyikan semua jendela normal" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:23 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:22 | ||||
| msgid "Switch to workspace 1" | ||||
| msgstr "Pindah ke area kerja 1" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:24 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:23 | ||||
| msgid "Switch to workspace 2" | ||||
| msgstr "Pindah ke area kerja 2" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:25 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:24 | ||||
| msgid "Switch to workspace 3" | ||||
| msgstr "Pindah ke area kerja 3" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:26 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:25 | ||||
| msgid "Switch to workspace 4" | ||||
| msgstr "Pindah ke area kerja 4" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:27 | ||||
| #| msgid "Switch to workspace 1" | ||||
| msgid "Switch to last workspace" | ||||
| msgstr "Pindah ke area kerja terakhir" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:28 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:26 | ||||
| msgid "Move to workspace left" | ||||
| msgstr "Pindah ke area kerja kiri" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:29 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:27 | ||||
| msgid "Move to workspace right" | ||||
| msgstr "Pindah ke area kerja kanan" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:30 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:28 | ||||
| msgid "Move to workspace above" | ||||
| msgstr "Pindah ke area kerja atas" | ||||
|  | ||||
| #: ../src/50-mutter-navigation.xml.in.h:31 | ||||
| #: ../src/50-mutter-navigation.xml.in.h:29 | ||||
| msgid "Move to workspace below" | ||||
| msgstr "Pindah ke area kerja bawah" | ||||
|  | ||||
| @@ -236,29 +226,9 @@ msgstr "Tampilan dipisah ke kiri" | ||||
| msgid "View split on right" | ||||
| msgstr "Tampilan dipisah ke kanan" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:412 | ||||
| msgid "Built-in display" | ||||
| msgstr "Tampilan bawaan" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:437 | ||||
| msgid "Unknown" | ||||
| msgstr "Tak Dikenal" | ||||
|  | ||||
| #: ../src/backends/meta-monitor-manager.c:439 | ||||
| msgid "Unknown Display" | ||||
| msgstr "Tampilan Tak Dikenal" | ||||
|  | ||||
| #. TRANSLATORS: this is a monitor vendor name, followed by a | ||||
| #. * size in inches, like 'Dell 15"' | ||||
| #. | ||||
| #: ../src/backends/meta-monitor-manager.c:447 | ||||
| #, c-format | ||||
| msgid "%s %s" | ||||
| msgstr "%s %s" | ||||
|  | ||||
| #. This probably means that a non-WM compositor like xcompmgr is running; | ||||
| #. * we have no way to get it to exit | ||||
| #: ../src/compositor/compositor.c:506 | ||||
| #: ../src/compositor/compositor.c:534 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Another compositing manager is already running on screen %i on display \"%s" | ||||
| @@ -266,86 +236,120 @@ msgid "" | ||||
| msgstr "" | ||||
| "Manajer komposit lain telah berjalan pada layar %i pada tampilan \"%s\"." | ||||
|  | ||||
| #: ../src/compositor/meta-background.c:990 | ||||
| #: ../src/compositor/meta-background.c:1074 | ||||
| msgid "background texture could not be created from file" | ||||
| msgstr "tekstur latar tak bisa dibuat dari berkas" | ||||
|  | ||||
| #: ../src/core/bell.c:215 | ||||
| #: ../src/core/bell.c:321 | ||||
| msgid "Bell event" | ||||
| msgstr "Bel peristiwa" | ||||
|  | ||||
| #: ../src/core/delete.c:106 | ||||
| #: ../src/core/core.c:156 | ||||
| #, c-format | ||||
| msgid "Unknown window information request: %d" | ||||
| msgstr "Permintaan informasi jendela tak dikenal: %d" | ||||
|  | ||||
| #: ../src/core/delete.c:109 | ||||
| #, c-format | ||||
| msgid "“%s” is not responding." | ||||
| msgstr "\"%s\" tak merespon." | ||||
|  | ||||
| #: ../src/core/delete.c:108 | ||||
| #: ../src/core/delete.c:111 | ||||
| msgid "Application is not responding." | ||||
| msgstr "Aplikasi tak merespon." | ||||
|  | ||||
| #: ../src/core/delete.c:113 | ||||
| #: ../src/core/delete.c:116 | ||||
| msgid "" | ||||
| "You may choose to wait a short while for it to continue or force the " | ||||
| "application to quit entirely." | ||||
| msgstr "" | ||||
| "Anda bisa memilih untuk menunggu sebentar atau memaksa aplikasi keluar." | ||||
|  | ||||
| #: ../src/core/delete.c:120 | ||||
| #: ../src/core/delete.c:123 | ||||
| msgid "_Wait" | ||||
| msgstr "_Tunggu" | ||||
|  | ||||
| #: ../src/core/delete.c:120 | ||||
| #: ../src/core/delete.c:123 | ||||
| msgid "_Force Quit" | ||||
| msgstr "_Matikan Paksa" | ||||
|  | ||||
| #: ../src/core/display.c:448 | ||||
| #: ../src/core/display.c:405 | ||||
| #, c-format | ||||
| msgid "Missing %s extension required for compositing" | ||||
| msgstr "Kehilangan ekstensi %s yang diperlukan untuk pengkomposisian" | ||||
|  | ||||
| #: ../src/core/display.c:497 | ||||
| #, c-format | ||||
| msgid "Failed to open X Window System display '%s'\n" | ||||
| msgstr "Gagal membuka tampilan X Window System '%s'\n" | ||||
|  | ||||
| #: ../src/core/main.c:190 | ||||
| #: ../src/core/keybindings.c:1105 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Some other program is already using the key %s with modifiers %x as a " | ||||
| "binding\n" | ||||
| msgstr "Ada program lain yang menggunakan tombol %s dengan kombinasi %x\n" | ||||
|  | ||||
| #: ../src/core/keybindings.c:1308 | ||||
| #, c-format | ||||
| msgid "\"%s\" is not a valid accelerator\n" | ||||
| msgstr "\"%s\" bukan akselerator yang valid\n" | ||||
|  | ||||
| #: ../src/core/main.c:195 | ||||
| msgid "Disable connection to session manager" | ||||
| msgstr "Menonaktifkan koneksi ke manajer sesi" | ||||
|  | ||||
| #: ../src/core/main.c:196 | ||||
| #: ../src/core/main.c:201 | ||||
| msgid "Replace the running window manager" | ||||
| msgstr "Mengganti manajer jendela yang tengah berjalan" | ||||
|  | ||||
| #: ../src/core/main.c:202 | ||||
| #: ../src/core/main.c:207 | ||||
| msgid "Specify session management ID" | ||||
| msgstr "Tentukan kode pengaturan sesi" | ||||
|  | ||||
| #: ../src/core/main.c:207 | ||||
| #: ../src/core/main.c:212 | ||||
| msgid "X Display to use" | ||||
| msgstr "Tampilan X yang digunakna" | ||||
|  | ||||
| #: ../src/core/main.c:213 | ||||
| #: ../src/core/main.c:218 | ||||
| msgid "Initialize session from savefile" | ||||
| msgstr "Aktifkan sesi dari berkas simpanan" | ||||
|  | ||||
| #: ../src/core/main.c:219 | ||||
| #: ../src/core/main.c:224 | ||||
| msgid "Make X calls synchronous" | ||||
| msgstr "Buat panggilan X selaras" | ||||
|  | ||||
| #: ../src/core/main.c:225 | ||||
| msgid "Run as a wayland compositor" | ||||
| msgstr "Jalankan sebagai kompositor wayland" | ||||
|  | ||||
| #: ../src/core/main.c:231 | ||||
| msgid "Run as a full display server, rather than nested" | ||||
| msgstr "Jalankan sebagai server tampilan penuh, ketimbang tampilan bersarang" | ||||
|  | ||||
| #: ../src/core/main.c:476 | ||||
| #: ../src/core/main.c:544 | ||||
| #, c-format | ||||
| msgid "Failed to scan themes directory: %s\n" | ||||
| msgstr "Gagal memeriksa direktori tema: %s\n" | ||||
|  | ||||
| #: ../src/core/main.c:492 | ||||
| #: ../src/core/main.c:560 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Could not find a theme! Be sure %s exists and contains the usual themes.\n" | ||||
| msgstr "Tak menemukan tema! Pastikan %s ada dan berisi tema yang biasa.\n" | ||||
|  | ||||
| #: ../src/core/monitor.c:699 | ||||
| msgid "Built-in display" | ||||
| msgstr "Tampilan bawaan" | ||||
|  | ||||
| #: ../src/core/monitor.c:724 | ||||
| msgid "Unknown" | ||||
| msgstr "Tidak Dikenal" | ||||
|  | ||||
| #: ../src/core/monitor.c:726 | ||||
| msgid "Unknown Display" | ||||
| msgstr "Tampilan Tidak Dikenal" | ||||
|  | ||||
| #. TRANSLATORS: this is a monitor vendor name, followed by a | ||||
| #. * size in inches, like 'Dell 15"' | ||||
| #. | ||||
| #: ../src/core/monitor.c:734 | ||||
| #, c-format | ||||
| msgid "%s %s" | ||||
| msgstr "%s %s" | ||||
|  | ||||
| #: ../src/core/mutter.c:39 | ||||
| #, c-format | ||||
| msgid "" | ||||
| @@ -370,17 +374,48 @@ msgstr "Cetak versi" | ||||
| msgid "Mutter plugin to use" | ||||
| msgstr "Pengaya Mutter yang dipakai" | ||||
|  | ||||
| #: ../src/core/prefs.c:1988 | ||||
| #: ../src/core/prefs.c:1190 | ||||
| msgid "" | ||||
| "Workarounds for broken applications disabled. Some applications may not " | ||||
| "behave properly.\n" | ||||
| msgstr "" | ||||
| "Pencegahan kesalahan bagi aplikasi yang rusak sedang dinonaktifkan. Mungkin " | ||||
| "nanti ada beberapa aplikasi yang akan bertingkah aneh.\n" | ||||
|  | ||||
| #: ../src/core/prefs.c:1265 | ||||
| #, c-format | ||||
| msgid "Could not parse font description \"%s\" from GSettings key %s\n" | ||||
| msgstr "Tak dapat mengurai deskripsi fonta \"%s\" dari kunci GSettings %s\n" | ||||
|  | ||||
| #: ../src/core/prefs.c:1331 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "\"%s\" found in configuration database is not a valid value for mouse button " | ||||
| "modifier\n" | ||||
| msgstr "" | ||||
| "\"%s\" yang ada pada database konfigurasi bukanlah nilai yang benar untuk " | ||||
| "tombol mouse.\n" | ||||
|  | ||||
| #: ../src/core/prefs.c:1894 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "\"%s\" found in configuration database is not a valid value for keybinding " | ||||
| "\"%s\"\n" | ||||
| msgstr "" | ||||
| "\"%s\" yang ada pada database konfigurasi bernilai tidak benar untuk " | ||||
| "kombinasi tombol \"%s\"\n" | ||||
|  | ||||
| #: ../src/core/prefs.c:1984 | ||||
| #, c-format | ||||
| msgid "Workspace %d" | ||||
| msgstr "Area kerja %d" | ||||
|  | ||||
| #: ../src/core/screen.c:543 | ||||
| #: ../src/core/screen.c:539 | ||||
| #, c-format | ||||
| msgid "Screen %d on display '%s' is invalid\n" | ||||
| msgstr "Layar %d pada tampilan '%s' tidak benar\n" | ||||
|  | ||||
| #: ../src/core/screen.c:559 | ||||
| #: ../src/core/screen.c:555 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Screen %d on display \"%s\" already has a window manager; try using the --" | ||||
| @@ -389,23 +424,192 @@ msgstr "" | ||||
| "Layar %d pada tampilan \"%s\" sudah memiliki pengatur jendela. Cobalah " | ||||
| "gunakan pilihan --replace untuk mengganti pengatur jendela yang aktif.\n" | ||||
|  | ||||
| #: ../src/core/screen.c:664 | ||||
| #: ../src/core/screen.c:582 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Could not acquire window manager selection on screen %d display \"%s\"\n" | ||||
| msgstr "" | ||||
| "Tidak dapat mendapatkan pilihan pengatur jendela pada layar %d tampilan \"%s" | ||||
| "\"\n" | ||||
|  | ||||
| #: ../src/core/screen.c:660 | ||||
| #, c-format | ||||
| msgid "Screen %d on display \"%s\" already has a window manager\n" | ||||
| msgstr "Layar %d pada tampilan \"%s\" sudah ada pengatur jendelanya\n" | ||||
|  | ||||
| #: ../src/core/util.c:118 | ||||
| #: ../src/core/screen.c:848 | ||||
| #, c-format | ||||
| msgid "Could not release screen %d on display \"%s\"\n" | ||||
| msgstr "Layar %d pada tampilan \"%s\" tidak dapat dilepas\n" | ||||
|  | ||||
| #: ../src/core/session.c:842 ../src/core/session.c:849 | ||||
| #, c-format | ||||
| msgid "Could not create directory '%s': %s\n" | ||||
| msgstr "Tidak dapat membuat direktori '%s': %s\n" | ||||
|  | ||||
| #: ../src/core/session.c:859 | ||||
| #, c-format | ||||
| msgid "Could not open session file '%s' for writing: %s\n" | ||||
| msgstr "Tidak dapat menulis ke dalam berkas sesi '%s': %s\n" | ||||
|  | ||||
| #: ../src/core/session.c:1000 | ||||
| #, c-format | ||||
| msgid "Error writing session file '%s': %s\n" | ||||
| msgstr "Ada error saat menulisi berkas sesi '%s': %s\n" | ||||
|  | ||||
| #: ../src/core/session.c:1005 | ||||
| #, c-format | ||||
| msgid "Error closing session file '%s': %s\n" | ||||
| msgstr "Ada error saat menutup berkas sesi '%s': %s\n" | ||||
|  | ||||
| #: ../src/core/session.c:1135 | ||||
| #, c-format | ||||
| msgid "Failed to parse saved session file: %s\n" | ||||
| msgstr "Gagal membaca berkas sesi simpanan: %s\n" | ||||
|  | ||||
| #: ../src/core/session.c:1184 | ||||
| #, c-format | ||||
| msgid "<mutter_session> attribute seen but we already have the session ID" | ||||
| msgstr "Atribut <mutter_session> terlihat tapi kode sesi sudah ada sebelumnya" | ||||
|  | ||||
| #: ../src/core/session.c:1197 ../src/core/session.c:1272 | ||||
| #: ../src/core/session.c:1304 ../src/core/session.c:1376 | ||||
| #: ../src/core/session.c:1436 | ||||
| #, c-format | ||||
| msgid "Unknown attribute %s on <%s> element" | ||||
| msgstr "Atribut %s tidak dikenal pada elemen <%s>" | ||||
|  | ||||
| #: ../src/core/session.c:1214 | ||||
| #, c-format | ||||
| msgid "nested <window> tag" | ||||
| msgstr "Ada tag <window> bersarang" | ||||
|  | ||||
| #: ../src/core/session.c:1456 | ||||
| #, c-format | ||||
| msgid "Unknown element %s" | ||||
| msgstr "Elemen %s tidak dikenal" | ||||
|  | ||||
| #: ../src/core/session.c:1808 | ||||
| msgid "" | ||||
| "These windows do not support "save current setup" and will have to " | ||||
| "be restarted manually next time you log in." | ||||
| msgstr "" | ||||
| "Jendela ini tidak bisa "menyimpan setelan aktif saat ini" dan bila " | ||||
| "log masuk kali lain Anda harus menjalankannya ulang." | ||||
|  | ||||
| #: ../src/core/util.c:82 | ||||
| #, c-format | ||||
| msgid "Failed to open debug log: %s\n" | ||||
| msgstr "Gagal membuka log debug: %s\n" | ||||
|  | ||||
| #: ../src/core/util.c:92 | ||||
| #, c-format | ||||
| msgid "Failed to fdopen() log file %s: %s\n" | ||||
| msgstr "Gagal melakukan fdopen pada berkas log %s: %s\n" | ||||
|  | ||||
| #: ../src/core/util.c:98 | ||||
| #, c-format | ||||
| msgid "Opened log file %s\n" | ||||
| msgstr "Berkas log yang dibuka %s\n" | ||||
|  | ||||
| #: ../src/core/util.c:117 | ||||
| msgid "Mutter was compiled without support for verbose mode\n" | ||||
| msgstr "Muter dikompilasi tanpa dukungan mode riuh\n" | ||||
|  | ||||
| #: ../src/mutter.desktop.in.h:1 | ||||
| #: ../src/core/util.c:262 | ||||
| msgid "Window manager: " | ||||
| msgstr "Pengatur jendela: " | ||||
|  | ||||
| #: ../src/core/util.c:412 | ||||
| msgid "Bug in window manager: " | ||||
| msgstr "Bug pada pengatur jendela: " | ||||
|  | ||||
| #: ../src/core/util.c:443 | ||||
| msgid "Window manager warning: " | ||||
| msgstr "Peringatan pengatur jendela: " | ||||
|  | ||||
| #: ../src/core/util.c:471 | ||||
| msgid "Window manager error: " | ||||
| msgstr "Eror pengatur jendela: " | ||||
|  | ||||
| #. first time through | ||||
| #: ../src/core/window.c:7562 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER " | ||||
| "window as specified in the ICCCM.\n" | ||||
| msgstr "" | ||||
| "Jendela %s menyetel SM_CLIENT_ID pada dirinya sendiri, padahal seharusnya " | ||||
| "disetel pada jendela WM_CLIENT_LEADER sesuai aturan ICCCM.\n" | ||||
|  | ||||
| #. We ignore mwm_has_resize_func because WM_NORMAL_HINTS is the | ||||
| #. * authoritative source for that info. Some apps such as mplayer or | ||||
| #. * xine disable resize via MWM but not WM_NORMAL_HINTS, but that | ||||
| #. * leads to e.g. us not fullscreening their windows.  Apps that set | ||||
| #. * MWM but not WM_NORMAL_HINTS are basically broken. We complain | ||||
| #. * about these apps but make them work. | ||||
| #. | ||||
| #: ../src/core/window.c:8487 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Window %s sets an MWM hint indicating it isn't resizable, but sets min size " | ||||
| "%d x %d and max size %d x %d; this doesn't make much sense.\n" | ||||
| msgstr "" | ||||
| "Jendela %s menyetel hint MWM yang menandakan bahwa ia tidak dapat dirubah " | ||||
| "ukurannya, sedangkan ukuran minimalnya adalah %d x %d dan maksimal %d x %d " | ||||
| "yang tidak masuk di akal.\n" | ||||
|  | ||||
| #: ../src/core/window-props.c:349 | ||||
| #, c-format | ||||
| msgid "Application set a bogus _NET_WM_PID %lu\n" | ||||
| msgstr "Aplikasi telah membuat _NET_WM_PID %lu bohongan\n" | ||||
|  | ||||
| #: ../src/core/window-props.c:465 | ||||
| #, c-format | ||||
| msgid "%s (on %s)" | ||||
| msgstr "%s (pada %s)" | ||||
|  | ||||
| #: ../src/core/window-props.c:1548 | ||||
| #, c-format | ||||
| msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n" | ||||
| msgstr "WM_TRANSIENT_FOR salah jendela 0x%lx ditentukan untuk %s.\n" | ||||
|  | ||||
| #: ../src/core/window-props.c:1559 | ||||
| #, c-format | ||||
| msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n" | ||||
| msgstr "Jendela WM_TRANSIENT_FOR 0x%lx untuk %s akan membuat loop.\n" | ||||
|  | ||||
| #: ../src/core/xprops.c:153 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Window 0x%lx has property %s\n" | ||||
| "that was expected to have type %s format %d\n" | ||||
| "and actually has type %s format %d n_items %d.\n" | ||||
| "This is most likely an application bug, not a window manager bug.\n" | ||||
| "The window has title=\"%s\" class=\"%s\" name=\"%s\"\n" | ||||
| msgstr "" | ||||
| "Jendela 0x%lx memiliki properti %s\n" | ||||
| "yang seharusnya memiliki tipe %s format %d.\n" | ||||
| "Sekarang dia memiliki tipe %s format %d n_items %d.\n" | ||||
| "Sepertinya ini adalah bug aplikasinya, bukan bug pengatur jendela.\n" | ||||
| "Judul jendelanya adalah \"%s\" class=\"%s\" dan bernama=\"%s\"\n" | ||||
|  | ||||
| #: ../src/core/xprops.c:409 | ||||
| #, c-format | ||||
| msgid "Property %s on window 0x%lx contained invalid UTF-8\n" | ||||
| msgstr "Properti %s pada jendela 0x%lx berisi karakter UTF-8 yang salah\n" | ||||
|  | ||||
| #: ../src/core/xprops.c:492 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Property %s on window 0x%lx contained invalid UTF-8 for item %d in the list\n" | ||||
| msgstr "" | ||||
| "Properti %s pada jendela 0x%lx di obyek %d berisi karakter UTF-8 yang salah\n" | ||||
|  | ||||
| #: ../src/mutter.desktop.in.h:1 ../src/mutter-wm.desktop.in.h:1 | ||||
| msgid "Mutter" | ||||
| msgstr "Mutter" | ||||
|  | ||||
| #: ../src/mutter-wayland.desktop.in.h:1 | ||||
| msgid "Mutter (wayland compositor)" | ||||
| msgstr "Mutter (kompositor wayland)" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.gschema.xml.in.h:1 | ||||
| msgid "Modifier to use for extended window management operations" | ||||
| msgstr "Tombol yang digunakan untuk memperluas operasi manajemen jendela" | ||||
| @@ -534,34 +738,6 @@ msgstr "Pilih jendela dari popup tab" | ||||
| msgid "Cancel tab popup" | ||||
| msgstr "Batalkan popup tab" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:1 | ||||
| msgid "Switch to VT 1" | ||||
| msgstr "Pindah ke VT 1" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:2 | ||||
| msgid "Switch to VT 2" | ||||
| msgstr "Pindah ke VT 2" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:3 | ||||
| msgid "Switch to VT 3" | ||||
| msgstr "Pindah ke VT 3" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:4 | ||||
| msgid "Switch to VT 4" | ||||
| msgstr "Pindah ke VT 4" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:5 | ||||
| msgid "Switch to VT 5" | ||||
| msgstr "Pindah ke VT 5" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:6 | ||||
| msgid "Switch to VT 6" | ||||
| msgstr "Pindah ke VT 6" | ||||
|  | ||||
| #: ../src/org.gnome.mutter.wayland.gschema.xml.in.h:7 | ||||
| msgid "Switch to VT 7" | ||||
| msgstr "Pindah ke VT 7" | ||||
|  | ||||
| #. Translators: Translate this string the same way as you do in libwnck! | ||||
| #: ../src/ui/menu.c:65 | ||||
| msgid "Mi_nimize" | ||||
| @@ -869,7 +1045,7 @@ msgstr "" | ||||
| #: ../src/ui/theme.c:1354 | ||||
| #, c-format | ||||
| msgid "Could not parse alpha value \"%s\" in blended color" | ||||
| msgstr "Tak dapat membaca nilai alpha \"%s\" pada pencampuran warna" | ||||
| msgstr "Tidak dapat membaca nilai alpha \"%s\" pada pencampuran warna" | ||||
|  | ||||
| #: ../src/ui/theme.c:1364 | ||||
| #, c-format | ||||
| @@ -889,7 +1065,7 @@ msgstr "" | ||||
| #: ../src/ui/theme.c:1422 | ||||
| #, c-format | ||||
| msgid "Could not parse shade factor \"%s\" in shaded color" | ||||
| msgstr "Tak dapat membaca faktor bayangan \"%s\" pada warna berbayang" | ||||
| msgstr "Tidak dapat membaca faktor bayangan \"%s\" pada warna berbayang" | ||||
|  | ||||
| #: ../src/ui/theme.c:1432 | ||||
| #, c-format | ||||
| @@ -899,7 +1075,7 @@ msgstr "Faktor bayangan \"%s\" pada warna berbayang bernilai negatif" | ||||
| #: ../src/ui/theme.c:1461 | ||||
| #, c-format | ||||
| msgid "Could not parse color \"%s\"" | ||||
| msgstr "Tak dapat membaca warna \"%s\"" | ||||
| msgstr "Tidak dapat membaca warna \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:1778 | ||||
| #, c-format | ||||
| @@ -1026,7 +1202,7 @@ msgstr "Gagal membuka tema \"%s\": %s\n" | ||||
| #: ../src/ui/theme.c:5237 ../src/ui/theme.c:5244 | ||||
| #, c-format | ||||
| msgid "No <%s> set for theme \"%s\"" | ||||
| msgstr "Tak ada <%s> yang ditentukan untuk tema \"%s\"" | ||||
| msgstr "Tidak ada <%s> yang ditentukan untuk tema \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme.c:5252 | ||||
| #, c-format | ||||
| @@ -1034,7 +1210,7 @@ msgid "" | ||||
| "No frame style set for window type \"%s\" in theme \"%s\", add a <window " | ||||
| "type=\"%s\" style_set=\"whatever\"/> element" | ||||
| msgstr "" | ||||
| "Tak ada gaya frame untuk tipe window \"%s\" pada tema \"%s\". Tambah dulu " | ||||
| "Tidak ada gaya frame untuk tipe window \"%s\" pada tema \"%s\". Tambah dulu " | ||||
| "elemen <window type=\"%s\" style_set=\"whatever\"/>" | ||||
|  | ||||
| #: ../src/ui/theme.c:5659 ../src/ui/theme.c:5721 ../src/ui/theme.c:5784 | ||||
| @@ -1055,7 +1231,7 @@ msgstr "Konstanta \"%s\" telah didefinisikan sebelumnya" | ||||
| #: ../src/ui/theme-parser.c:234 | ||||
| #, c-format | ||||
| msgid "No \"%s\" attribute on element <%s>" | ||||
| msgstr "Tak ada atribut \"%s\" pada elemen <%s>" | ||||
| msgstr "Tidak ada atribut \"%s\" pada elemen <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:263 ../src/ui/theme-parser.c:281 | ||||
| #, c-format | ||||
| @@ -1075,12 +1251,12 @@ msgstr "Atribut \"%s\" tidak diperkenankan pada elemen <%s> pada konteks ini" | ||||
| #: ../src/ui/theme-parser.c:596 | ||||
| #, c-format | ||||
| msgid "Could not parse \"%s\" as an integer" | ||||
| msgstr "Tak dapat menguraikan \"%s\" sebagai integer" | ||||
| msgstr "Tidak dapat menguraikan \"%s\" sebagai integer" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:605 ../src/ui/theme-parser.c:660 | ||||
| #, c-format | ||||
| msgid "Did not understand trailing characters \"%s\" in string \"%s\"" | ||||
| msgstr "Tak mengerti karakter \"%s\" kenapa ada dibuntut string \"%s\"" | ||||
| msgstr "Tidak mengerti karakter \"%s\" kenapa ada dibuntut string \"%s\"" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:615 | ||||
| #, c-format | ||||
| @@ -1095,7 +1271,7 @@ msgstr "Integer %ld terlalu besar, maksimal %d" | ||||
| #: ../src/ui/theme-parser.c:651 ../src/ui/theme-parser.c:767 | ||||
| #, c-format | ||||
| msgid "Could not parse \"%s\" as a floating point number" | ||||
| msgstr "Tak dapat membaca \"%s\" sebagai angka floating point" | ||||
| msgstr "Tidak dapat membaca \"%s\" sebagai angka floating point" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:682 ../src/ui/theme-parser.c:710 | ||||
| #, c-format | ||||
| @@ -1180,8 +1356,8 @@ msgid "" | ||||
| "Cannot specify both \"button_width\"/\"button_height\" and \"aspect_ratio\" " | ||||
| "for buttons" | ||||
| msgstr "" | ||||
| "Tak dapat menyatakan \"button_width\"/\"button_height\" dan \"aspect_ratio\" " | ||||
| "sekaligus untuk tombol" | ||||
| "Tidak dapat menyatakan \"button_width\"/\"button_height\" dan \"aspect_ratio" | ||||
| "\" sekaligus untuk tombol" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1452 | ||||
| #, c-format | ||||
| @@ -1201,12 +1377,12 @@ msgstr "Batas \"%s\" tidak dikenal" | ||||
| #: ../src/ui/theme-parser.c:1870 | ||||
| #, c-format | ||||
| msgid "No \"start_angle\" or \"from\" attribute on element <%s>" | ||||
| msgstr "Tak ada atribut \"start_angle\" atau \"from\" pada elemen <%s>" | ||||
| msgstr "Tidak ada atribut \"start_angle\" atau \"from\" pada elemen <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:1877 | ||||
| #, c-format | ||||
| msgid "No \"extent_angle\" or \"to\" attribute on element <%s>" | ||||
| msgstr "Tak ada atribut \"extent_angle\" atau \"to\" pada elemen <%s>" | ||||
| msgstr "Tidak ada atribut \"extent_angle\" atau \"to\" pada elemen <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2117 | ||||
| #, c-format | ||||
| @@ -1237,7 +1413,7 @@ msgstr "Panah \"%s\" tidak dikenal untuk elemen <%s>" | ||||
| #: ../src/ui/theme-parser.c:2696 ../src/ui/theme-parser.c:2792 | ||||
| #, c-format | ||||
| msgid "No <draw_ops> called \"%s\" has been defined" | ||||
| msgstr "Tak ada <draw_ops> bernama \"%s\" yang telah didefinisikan" | ||||
| msgstr "Tidak ada <draw_ops> bernama \"%s\" yang telah didefinisikan" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2708 ../src/ui/theme-parser.c:2804 | ||||
| #, c-format | ||||
| @@ -1258,7 +1434,7 @@ msgstr "Gaya frame sudah memiliki bagian pada posisi %s" | ||||
| #: ../src/ui/theme-parser.c:2944 ../src/ui/theme-parser.c:3021 | ||||
| #, c-format | ||||
| msgid "No <draw_ops> with the name \"%s\" has been defined" | ||||
| msgstr "Tak ada <draw_ops> dengan nama \"%s\" yang didefinisikan" | ||||
| msgstr "Tidak ada <draw_ops> dengan nama \"%s\" yang didefinisikan" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:2974 | ||||
| #, c-format | ||||
| @@ -1335,7 +1511,7 @@ msgid "" | ||||
| "Can't have a two draw_ops for a <piece> element (theme specified a draw_ops " | ||||
| "attribute and also a <draw_ops> element, or specified two elements)" | ||||
| msgstr "" | ||||
| "Tak boleh ada dua draw_ops untuk elemen <piece> (tema menyebutkan atribut " | ||||
| "Tidak boleh ada dua draw_ops untuk elemen <piece> (tema menyebutkan atribut " | ||||
| "draw_ops dan juga elemen <draw_ops> atau meyebutkan dua elemen tersebut " | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3331 | ||||
| @@ -1343,7 +1519,7 @@ msgid "" | ||||
| "Can't have a two draw_ops for a <button> element (theme specified a draw_ops " | ||||
| "attribute and also a <draw_ops> element, or specified two elements)" | ||||
| msgstr "" | ||||
| "Tak boleh ada dua draw_ops untuk elemen <button> (tema menyebutkan atribut " | ||||
| "Tidak boleh ada dua draw_ops untuk elemen <button> (tema menyebutkan atribut " | ||||
| "draw_ops dan juga elemen <draw_ops> atau meyebutkan dua elemen tersebut " | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3369 | ||||
| @@ -1351,7 +1527,7 @@ msgid "" | ||||
| "Can't have a two draw_ops for a <menu_icon> element (theme specified a " | ||||
| "draw_ops attribute and also a <draw_ops> element, or specified two elements)" | ||||
| msgstr "" | ||||
| "Tak boleh ada dua draw_ops untuk elemen <menu_icon> (tema menyebutkan " | ||||
| "Tidak boleh ada dua draw_ops untuk elemen <menu_icon> (tema menyebutkan " | ||||
| "atribut draw_ops dan juga elemen <draw_ops> atau meyebutkan dua elemen " | ||||
| "tersebut " | ||||
|  | ||||
| @@ -1410,16 +1586,16 @@ msgstr "Elemen <%s> tidak boleh ada di dalam elemen <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3898 | ||||
| msgid "No draw_ops provided for frame piece" | ||||
| msgstr "Tak ada draw_ops yang disediakan untuk bagian frame" | ||||
| msgstr "Tidak ada draw_ops yang disediakan untuk bagian frame" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3913 | ||||
| msgid "No draw_ops provided for button" | ||||
| msgstr "Tak ada draw_ops yang disediakan untuk tombol" | ||||
| msgstr "Tidak ada draw_ops yang disediakan untuk tombol" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:3967 | ||||
| #, c-format | ||||
| msgid "No text is allowed inside element <%s>" | ||||
| msgstr "Tak boleh ada teks di dalam elemen <%s>" | ||||
| msgstr "Tidak boleh ada teks di dalam elemen <%s>" | ||||
|  | ||||
| #: ../src/ui/theme-parser.c:4025 ../src/ui/theme-parser.c:4037 | ||||
| #: ../src/ui/theme-parser.c:4049 ../src/ui/theme-parser.c:4061 | ||||
| @@ -1432,159 +1608,3 @@ msgstr "<%s> disebutkan dua kali pada tema ini" | ||||
| #, c-format | ||||
| msgid "Failed to find a valid file for theme %s\n" | ||||
| msgstr "Gagal menemukan berkas yang sah untuk tema %s\n" | ||||
|  | ||||
| #: ../src/x11/session.c:1815 | ||||
| msgid "" | ||||
| "These windows do not support "save current setup" and will have to " | ||||
| "be restarted manually next time you log in." | ||||
| msgstr "" | ||||
| "Jendela ini tidak bisa "menyimpan setelan aktif saat ini" dan bila " | ||||
| "log masuk kali lain Anda harus menjalankannya ulang." | ||||
|  | ||||
| #: ../src/x11/window-props.c:465 | ||||
| #, c-format | ||||
| msgid "%s (on %s)" | ||||
| msgstr "%s (pada %s)" | ||||
|  | ||||
| #~ msgid "Unknown window information request: %d" | ||||
| #~ msgstr "Permintaan informasi jendela tak dikenal: %d" | ||||
|  | ||||
| #~ msgid "Missing %s extension required for compositing" | ||||
| #~ msgstr "Kehilangan ekstensi %s yang diperlukan untuk pengkomposisian" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Some other program is already using the key %s with modifiers %x as a " | ||||
| #~ "binding\n" | ||||
| #~ msgstr "Ada program lain yang menggunakan tombol %s dengan kombinasi %x\n" | ||||
|  | ||||
| #~ msgid "\"%s\" is not a valid accelerator\n" | ||||
| #~ msgstr "\"%s\" bukan akselerator yang valid\n" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Workarounds for broken applications disabled. Some applications may not " | ||||
| #~ "behave properly.\n" | ||||
| #~ msgstr "" | ||||
| #~ "Pencegahan kesalahan bagi aplikasi yang rusak sedang dinonaktifkan. " | ||||
| #~ "Mungkin nanti ada beberapa aplikasi yang akan bertingkah aneh.\n" | ||||
|  | ||||
| #~ msgid "Could not parse font description \"%s\" from GSettings key %s\n" | ||||
| #~ msgstr "Tak dapat mengurai deskripsi fonta \"%s\" dari kunci GSettings %s\n" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "\"%s\" found in configuration database is not a valid value for mouse " | ||||
| #~ "button modifier\n" | ||||
| #~ msgstr "" | ||||
| #~ "\"%s\" yang ada pada database konfigurasi bukanlah nilai yang benar untuk " | ||||
| #~ "tombol mouse.\n" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "\"%s\" found in configuration database is not a valid value for " | ||||
| #~ "keybinding \"%s\"\n" | ||||
| #~ msgstr "" | ||||
| #~ "\"%s\" yang ada pada database konfigurasi bernilai tidak benar untuk " | ||||
| #~ "kombinasi tombol \"%s\"\n" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Could not acquire window manager selection on screen %d display \"%s\"\n" | ||||
| #~ msgstr "" | ||||
| #~ "Tak dapat mendapatkan pilihan pengatur jendela pada layar %d tampilan \"%s" | ||||
| #~ "\"\n" | ||||
|  | ||||
| #~ msgid "Could not release screen %d on display \"%s\"\n" | ||||
| #~ msgstr "Layar %d pada tampilan \"%s\" tidak dapat dilepas\n" | ||||
|  | ||||
| #~ msgid "Could not create directory '%s': %s\n" | ||||
| #~ msgstr "Tak dapat membuat direktori '%s': %s\n" | ||||
|  | ||||
| #~ msgid "Could not open session file '%s' for writing: %s\n" | ||||
| #~ msgstr "Tak dapat menulis ke dalam berkas sesi '%s': %s\n" | ||||
|  | ||||
| #~ msgid "Error writing session file '%s': %s\n" | ||||
| #~ msgstr "Ada error saat menulisi berkas sesi '%s': %s\n" | ||||
|  | ||||
| #~ msgid "Error closing session file '%s': %s\n" | ||||
| #~ msgstr "Ada error saat menutup berkas sesi '%s': %s\n" | ||||
|  | ||||
| #~ msgid "Failed to parse saved session file: %s\n" | ||||
| #~ msgstr "Gagal membaca berkas sesi simpanan: %s\n" | ||||
|  | ||||
| #~ msgid "<mutter_session> attribute seen but we already have the session ID" | ||||
| #~ msgstr "" | ||||
| #~ "Atribut <mutter_session> terlihat tapi kode sesi sudah ada sebelumnya" | ||||
|  | ||||
| #~ msgid "Unknown attribute %s on <%s> element" | ||||
| #~ msgstr "Atribut %s tidak dikenal pada elemen <%s>" | ||||
|  | ||||
| #~ msgid "nested <window> tag" | ||||
| #~ msgstr "Ada tag <window> bersarang" | ||||
|  | ||||
| #~ msgid "Unknown element %s" | ||||
| #~ msgstr "Elemen %s tidak dikenal" | ||||
|  | ||||
| #~ msgid "Failed to open debug log: %s\n" | ||||
| #~ msgstr "Gagal membuka log debug: %s\n" | ||||
|  | ||||
| #~ msgid "Failed to fdopen() log file %s: %s\n" | ||||
| #~ msgstr "Gagal melakukan fdopen pada berkas log %s: %s\n" | ||||
|  | ||||
| #~ msgid "Opened log file %s\n" | ||||
| #~ msgstr "Berkas log yang dibuka %s\n" | ||||
|  | ||||
| #~ msgid "Window manager: " | ||||
| #~ msgstr "Pengatur jendela: " | ||||
|  | ||||
| #~ msgid "Bug in window manager: " | ||||
| #~ msgstr "Bug pada pengatur jendela: " | ||||
|  | ||||
| #~ msgid "Window manager warning: " | ||||
| #~ msgstr "Peringatan pengatur jendela: " | ||||
|  | ||||
| #~ msgid "Window manager error: " | ||||
| #~ msgstr "Eror pengatur jendela: " | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER " | ||||
| #~ "window as specified in the ICCCM.\n" | ||||
| #~ msgstr "" | ||||
| #~ "Jendela %s menyetel SM_CLIENT_ID pada dirinya sendiri, padahal seharusnya " | ||||
| #~ "disetel pada jendela WM_CLIENT_LEADER sesuai aturan ICCCM.\n" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Window %s sets an MWM hint indicating it isn't resizable, but sets min " | ||||
| #~ "size %d x %d and max size %d x %d; this doesn't make much sense.\n" | ||||
| #~ msgstr "" | ||||
| #~ "Jendela %s menyetel hint MWM yang menandakan bahwa ia tidak dapat dirubah " | ||||
| #~ "ukurannya, sedangkan ukuran minimalnya adalah %d x %d dan maksimal %d x " | ||||
| #~ "%d yang tidak masuk di akal.\n" | ||||
|  | ||||
| #~ msgid "Application set a bogus _NET_WM_PID %lu\n" | ||||
| #~ msgstr "Aplikasi telah membuat _NET_WM_PID %lu bohongan\n" | ||||
|  | ||||
| #~ msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n" | ||||
| #~ msgstr "WM_TRANSIENT_FOR salah jendela 0x%lx ditentukan untuk %s.\n" | ||||
|  | ||||
| #~ msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n" | ||||
| #~ msgstr "Jendela WM_TRANSIENT_FOR 0x%lx untuk %s akan membuat loop.\n" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Window 0x%lx has property %s\n" | ||||
| #~ "that was expected to have type %s format %d\n" | ||||
| #~ "and actually has type %s format %d n_items %d.\n" | ||||
| #~ "This is most likely an application bug, not a window manager bug.\n" | ||||
| #~ "The window has title=\"%s\" class=\"%s\" name=\"%s\"\n" | ||||
| #~ msgstr "" | ||||
| #~ "Jendela 0x%lx memiliki properti %s\n" | ||||
| #~ "yang seharusnya memiliki tipe %s format %d.\n" | ||||
| #~ "Sekarang dia memiliki tipe %s format %d n_items %d.\n" | ||||
| #~ "Sepertinya ini adalah bug aplikasinya, bukan bug pengatur jendela.\n" | ||||
| #~ "Judul jendelanya adalah \"%s\" class=\"%s\" dan bernama=\"%s\"\n" | ||||
|  | ||||
| #~ msgid "Property %s on window 0x%lx contained invalid UTF-8\n" | ||||
| #~ msgstr "Properti %s pada jendela 0x%lx berisi karakter UTF-8 yang salah\n" | ||||
|  | ||||
| #~ msgid "" | ||||
| #~ "Property %s on window 0x%lx contained invalid UTF-8 for item %d in the " | ||||
| #~ "list\n" | ||||
| #~ msgstr "" | ||||
| #~ "Properti %s pada jendela 0x%lx di obyek %d berisi karakter UTF-8 yang " | ||||
| #~ "salah\n" | ||||
|   | ||||
| @@ -17,9 +17,6 @@ | ||||
| 	<KeyListEntry name="move-to-workspace-4" | ||||
| 	              _description="Move window to workspace 4" /> | ||||
| 
 | ||||
|         <KeyListEntry name="move-to-workspace-last" | ||||
|                       _description="Move window to last workspace" /> | ||||
| 
 | ||||
| 	<KeyListEntry name="move-to-workspace-left" | ||||
| 	              _description="Move window one workspace to the left" /> | ||||
| 
 | ||||
| @@ -80,9 +77,6 @@ | ||||
| 	<KeyListEntry name="switch-to-workspace-4" | ||||
| 	              _description="Switch to workspace 4" /> | ||||
| 
 | ||||
| 	<KeyListEntry name="switch-to-workspace-last" | ||||
| 	              _description="Switch to last workspace" /> | ||||
| 
 | ||||
| 	<KeyListEntry name="switch-to-workspace-left" | ||||
| 	              _description="Move to workspace left" /> | ||||
| 
 | ||||
							
								
								
									
										283
									
								
								src/Makefile.am
									
									
									
									
									
								
							
							
						
						
									
										283
									
								
								src/Makefile.am
									
									
									
									
									
								
							| @@ -5,80 +5,39 @@ lib_LTLIBRARIES = libmutter.la | ||||
|  | ||||
| SUBDIRS=compositor/plugins | ||||
|  | ||||
| AM_CPPFLAGS = \ | ||||
| 	-DCLUTTER_ENABLE_COMPOSITOR_API					\ | ||||
| INCLUDES=								\ | ||||
| 	-DCLUTTER_ENABLE_EXPERIMENTAL_API				\ | ||||
| 	-DCOGL_ENABLE_EXPERIMENTAL_API					\ | ||||
| 	-DCOGL_ENABLE_EXPERIMENTAL_2_0_API                              \ | ||||
| 	$(MUTTER_CFLAGS)						\ | ||||
| 	$(MUTTER_NATIVE_BACKEND_CFLAGS)					\ | ||||
| 	-I$(builddir)							\ | ||||
| 	-I$(srcdir)							\ | ||||
| 	-I$(srcdir)/backends						\ | ||||
| 	-I$(srcdir)/core						\ | ||||
| 	-I$(srcdir)/ui							\ | ||||
| 	-I$(srcdir)/compositor						\ | ||||
| 	-DMUTTER_LIBEXECDIR=\"$(libexecdir)\"				\ | ||||
| 	-DMUTTER_LOCALEDIR=\"$(localedir)\"				\ | ||||
| 	-DHOST_ALIAS=\"@HOST_ALIAS@\"					\ | ||||
| 	-DMUTTER_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\"		\ | ||||
| 	-DMUTTER_PKGDATADIR=\"$(pkgdatadir)\"				\ | ||||
| 	-DMUTTER_DATADIR=\"$(datadir)\"					\ | ||||
| 	-DG_LOG_DOMAIN=\"mutter\"					\ | ||||
| 	-DSN_API_NOT_YET_FROZEN=1					\ | ||||
| 	-DMUTTER_MAJOR_VERSION=$(MUTTER_MAJOR_VERSION)			\ | ||||
| 	-DMUTTER_MINOR_VERSION=$(MUTTER_MINOR_VERSION)			\ | ||||
| 	-DMUTTER_MICRO_VERSION=$(MUTTER_MICRO_VERSION)			\ | ||||
| 	-DMUTTER_PLUGIN_API_VERSION=$(MUTTER_PLUGIN_API_VERSION)	\ | ||||
| 	-DMUTTER_PKGLIBDIR=\"$(pkglibdir)\"				\ | ||||
| 	-DMUTTER_PLUGIN_DIR=\"$(MUTTER_PLUGIN_DIR)\"			\ | ||||
| 	-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\"			\ | ||||
| 	-DXWAYLAND_PATH=\"$(XWAYLAND_PATH)\" | ||||
| 	-DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\"			\ | ||||
| 	-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" | ||||
|  | ||||
| mutter_built_sources = \ | ||||
| 	$(dbus_idle_built_sources)		\ | ||||
| 	$(dbus_display_config_built_sources)	\ | ||||
| 	$(dbus_login1_built_sources)		\ | ||||
| 	meta/meta-version.h			\ | ||||
| 	mutter-enum-types.h 			\ | ||||
| 	mutter-enum-types.c			\ | ||||
| 	gtk-shell-protocol.c			\ | ||||
| 	gtk-shell-server-protocol.h		\ | ||||
| 	xdg-shell-protocol.c			\ | ||||
| 	xdg-shell-server-protocol.h | ||||
|  | ||||
| wayland_protocols = \ | ||||
| 	wayland/protocol/gtk-shell.xml		\ | ||||
| 	wayland/protocol/xdg-shell.xml | ||||
| 	$(dbus_idle_built_sources)	\ | ||||
| 	$(dbus_xrandr_built_sources)	\ | ||||
| 	mutter-enum-types.h		\ | ||||
| 	mutter-enum-types.c | ||||
|  | ||||
| libmutter_la_SOURCES =				\ | ||||
| 	backends/meta-backend.c			\ | ||||
| 	backends/meta-backend.h			\ | ||||
| 	backends/meta-backend-private.h		\ | ||||
| 	backends/meta-cursor.c			\ | ||||
| 	backends/meta-cursor.h			\ | ||||
| 	backends/meta-cursor-private.h		\ | ||||
| 	backends/meta-cursor-tracker.c		\ | ||||
| 	backends/meta-cursor-tracker-private.h	\ | ||||
| 	backends/meta-cursor-renderer.c		\ | ||||
| 	backends/meta-cursor-renderer.h		\ | ||||
| 	backends/meta-display-config-shared.h	\ | ||||
| 	backends/meta-idle-monitor.c		\ | ||||
| 	backends/meta-idle-monitor-private.h	\ | ||||
| 	backends/meta-idle-monitor-dbus.c	\ | ||||
| 	backends/meta-idle-monitor-dbus.h	\ | ||||
| 	backends/meta-monitor-config.c		\ | ||||
| 	backends/meta-monitor-config.h		\ | ||||
| 	backends/meta-monitor-manager.c		\ | ||||
| 	backends/meta-monitor-manager.h		\ | ||||
| 	backends/meta-monitor-manager-dummy.c	\ | ||||
| 	backends/meta-monitor-manager-dummy.h	\ | ||||
| 	backends/edid-parse.c			\ | ||||
| 	backends/edid.h				\ | ||||
| 	backends/x11/meta-backend-x11.c			\ | ||||
| 	backends/x11/meta-backend-x11.h			\ | ||||
| 	backends/x11/meta-cursor-renderer-x11.c		\ | ||||
| 	backends/x11/meta-cursor-renderer-x11.h		\ | ||||
| 	backends/x11/meta-idle-monitor-xsync.c		\ | ||||
| 	backends/x11/meta-idle-monitor-xsync.h		\ | ||||
| 	backends/x11/meta-monitor-manager-xrandr.c	\ | ||||
| 	backends/x11/meta-monitor-manager-xrandr.h	\ | ||||
| 	core/meta-accel-parse.c			\ | ||||
| 	core/meta-accel-parse.h			\ | ||||
| 	core/async-getprop.c			\ | ||||
| 	core/async-getprop.h			\ | ||||
| 	core/barrier.c				\ | ||||
| 	meta/barrier.h				\ | ||||
| 	core/bell.c				\ | ||||
| @@ -106,15 +65,7 @@ libmutter_la_SOURCES =				\ | ||||
| 	compositor/meta-shadow-factory.c	\ | ||||
| 	compositor/meta-shadow-factory-private.h	\ | ||||
| 	compositor/meta-shaped-texture.c	\ | ||||
| 	compositor/meta-shaped-texture-private.h 	\ | ||||
| 	compositor/meta-surface-actor.c		\ | ||||
| 	compositor/meta-surface-actor.h		\ | ||||
| 	compositor/meta-surface-actor-x11.c	\ | ||||
| 	compositor/meta-surface-actor-x11.h	\ | ||||
| 	compositor/meta-surface-actor-wayland.c	\ | ||||
| 	compositor/meta-surface-actor-wayland.h	\ | ||||
| 	compositor/meta-stage.h			\ | ||||
| 	compositor/meta-stage.c			\ | ||||
| 	compositor/meta-shaped-texture-private.h	\ | ||||
| 	compositor/meta-texture-rectangle.c	\ | ||||
| 	compositor/meta-texture-rectangle.h	\ | ||||
| 	compositor/meta-texture-tower.c		\ | ||||
| @@ -135,6 +86,7 @@ libmutter_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				\ | ||||
| @@ -144,17 +96,34 @@ libmutter_la_SOURCES =				\ | ||||
| 	meta/display.h				\ | ||||
| 	core/edge-resistance.c			\ | ||||
| 	core/edge-resistance.h			\ | ||||
| 	core/events.c				\ | ||||
| 	core/events.h				\ | ||||
| 	core/edid-parse.c			\ | ||||
| 	core/edid.h				\ | ||||
| 	core/errors.c				\ | ||||
| 	meta/errors.h				\ | ||||
| 	core/frame.c				\ | ||||
| 	core/frame.h				\ | ||||
| 	ui/gradient.c				\ | ||||
| 	meta/gradient.h				\ | ||||
| 	core/group-private.h			\ | ||||
| 	core/group-props.c			\ | ||||
| 	core/group-props.h			\ | ||||
| 	core/group.c				\ | ||||
| 	meta/group.h				\ | ||||
| 	core/iconcache.c			\ | ||||
| 	core/iconcache.h			\ | ||||
| 	core/keybindings.c			\ | ||||
| 	core/keybindings-private.h		\ | ||||
| 	core/main.c				\ | ||||
| 	core/meta-cursor-tracker.c		\ | ||||
| 	core/meta-cursor-tracker-private.h	\ | ||||
| 	core/meta-idle-monitor.c		\ | ||||
| 	core/meta-idle-monitor-private.h	\ | ||||
| 	core/meta-xrandr-shared.h		\ | ||||
| 	core/monitor.c				\ | ||||
| 	core/monitor-config.c			\ | ||||
| 	core/monitor-private.h			\ | ||||
| 	core/monitor-xrandr.c			\ | ||||
| 	core/mutter-Xatomtype.h			\ | ||||
| 	core/place.c				\ | ||||
| 	core/place.h				\ | ||||
| 	core/prefs.c				\ | ||||
| @@ -163,6 +132,11 @@ libmutter_la_SOURCES =				\ | ||||
| 	core/screen-private.h			\ | ||||
| 	meta/screen.h				\ | ||||
| 	meta/types.h				\ | ||||
| 	core/restart.c				\ | ||||
| 	core/session.c				\ | ||||
| 	core/session.h				\ | ||||
| 	core/stereo.c				\ | ||||
| 	core/stereo.h				\ | ||||
| 	core/stack.c				\ | ||||
| 	core/stack.h				\ | ||||
| 	core/stack-tracker.c			\ | ||||
| @@ -170,94 +144,41 @@ libmutter_la_SOURCES =				\ | ||||
| 	core/util.c				\ | ||||
| 	meta/util.h				\ | ||||
| 	core/util-private.h			\ | ||||
| 	core/window-props.c			\ | ||||
| 	core/window-props.h			\ | ||||
| 	core/window.c				\ | ||||
| 	core/window-private.h			\ | ||||
| 	meta/window.h				\ | ||||
| 	core/workspace.c			\ | ||||
| 	core/workspace-private.h		\ | ||||
| 	core/xprops.c				\ | ||||
| 	core/xprops.h				\ | ||||
| 	meta/common.h				\ | ||||
| 	core/core.h				\ | ||||
| 	ui/ui.h					\ | ||||
| 	ui/frames.c				\ | ||||
| 	ui/frames.h				\ | ||||
| 	ui/menu.c				\ | ||||
| 	ui/menu.h				\ | ||||
| 	ui/metaaccellabel.c			\ | ||||
| 	ui/metaaccellabel.h			\ | ||||
| 	ui/resizepopup.c			\ | ||||
| 	ui/resizepopup.h			\ | ||||
| 	ui/theme-parser.c			\ | ||||
| 	ui/theme.c				\ | ||||
| 	meta/theme.h				\ | ||||
| 	ui/theme-private.h			\ | ||||
| 	ui/ui.c					\ | ||||
| 	x11/iconcache.c				\ | ||||
| 	x11/iconcache.h				\ | ||||
| 	x11/async-getprop.c			\ | ||||
| 	x11/async-getprop.h			\ | ||||
| 	x11/events.c				\ | ||||
| 	x11/events.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				\ | ||||
| 	x11/mutter-Xatomtype.h			\ | ||||
| 	wayland/meta-wayland.c			\ | ||||
| 	wayland/meta-wayland.h			\ | ||||
| 	wayland/meta-wayland-private.h		\ | ||||
| 	wayland/meta-xwayland.c			\ | ||||
| 	wayland/meta-xwayland.h			\ | ||||
| 	wayland/meta-xwayland-private.h		\ | ||||
| 	wayland/meta-wayland-data-device.c      \ | ||||
| 	wayland/meta-wayland-data-device.h      \ | ||||
| 	wayland/meta-wayland-keyboard.c		\ | ||||
| 	wayland/meta-wayland-keyboard.h		\ | ||||
| 	wayland/meta-wayland-pointer.c		\ | ||||
| 	wayland/meta-wayland-pointer.h		\ | ||||
| 	wayland/meta-wayland-seat.c		\ | ||||
| 	wayland/meta-wayland-seat.h		\ | ||||
| 	wayland/meta-wayland-touch.c		\ | ||||
| 	wayland/meta-wayland-touch.h		\ | ||||
| 	wayland/meta-wayland-surface.c		\ | ||||
| 	wayland/meta-wayland-surface.h		\ | ||||
| 	wayland/meta-wayland-types.h		\ | ||||
| 	wayland/meta-wayland-versions.h		\ | ||||
| 	wayland/meta-wayland-outputs.c		\ | ||||
| 	wayland/meta-wayland-outputs.h		\ | ||||
| 	wayland/window-wayland.c		\ | ||||
| 	wayland/window-wayland.h | ||||
|  | ||||
| if HAVE_NATIVE_BACKEND | ||||
| libmutter_la_SOURCES +=					\ | ||||
| 	backends/native/meta-backend-native.c		\ | ||||
| 	backends/native/meta-backend-native.h		\ | ||||
| 	backends/native/meta-cursor-renderer-native.c	\ | ||||
| 	backends/native/meta-cursor-renderer-native.h	\ | ||||
| 	backends/native/meta-idle-monitor-native.c	\ | ||||
| 	backends/native/meta-idle-monitor-native.h	\ | ||||
| 	backends/native/meta-monitor-manager-kms.c	\ | ||||
| 	backends/native/meta-monitor-manager-kms.h	\ | ||||
| 	backends/native/meta-launcher.c			\ | ||||
| 	backends/native/meta-launcher.h			\ | ||||
| 	backends/native/dbus-utils.c			\ | ||||
| 	backends/native/dbus-utils.h | ||||
| endif | ||||
| 	ui/ui.c | ||||
|  | ||||
| nodist_libmutter_la_SOURCES =			\ | ||||
| 	$(mutter_built_sources) | ||||
|  | ||||
| libmutter_la_LDFLAGS = -no-undefined | ||||
| libmutter_la_LIBADD  = $(MUTTER_LIBS) $(MUTTER_NATIVE_BACKEND_LIBS) | ||||
| libmutter_la_LIBADD  = $(MUTTER_LIBS) | ||||
|  | ||||
| # Headers installed for plugins; introspected information will | ||||
| # be extracted into Mutter-<version>.gir | ||||
| libmutterinclude_headers =			\ | ||||
| libmutterinclude_base_headers =		\ | ||||
| 	meta/barrier.h				\ | ||||
| 	meta/boxes.h				\ | ||||
| 	meta/common.h				\ | ||||
| @@ -286,13 +207,6 @@ libmutterinclude_headers =			\ | ||||
| 	meta/window.h				\ | ||||
| 	meta/workspace.h | ||||
|  | ||||
| libmutterinclude_built_headers =		\ | ||||
| 	meta/meta-version.h | ||||
|  | ||||
| libmutterinclude_base_headers =			\ | ||||
| 	$(libmutterinclude_headers)		\ | ||||
| 	$(libmutterinclude_built_headers) | ||||
|  | ||||
| # Excluded from scanning for introspection but installed | ||||
| # atomnames.h: macros cause problems for scanning process | ||||
| libmutterinclude_extra_headers =		\ | ||||
| @@ -301,17 +215,18 @@ libmutterinclude_extra_headers =		\ | ||||
| libmutterincludedir = $(includedir)/mutter/meta | ||||
|  | ||||
| libmutterinclude_HEADERS =			\ | ||||
| 	$(libmutterinclude_headers)		\ | ||||
| 	$(libmutterinclude_base_headers)	\ | ||||
| 	$(libmutterinclude_extra_headers) | ||||
|  | ||||
| nodist_libmutterinclude_HEADERS =		\ | ||||
| 	$(libmutterinclude_built_headers) | ||||
|  | ||||
| bin_PROGRAMS=mutter | ||||
|  | ||||
| mutter_SOURCES = core/mutter.c | ||||
| mutter_LDADD = $(MUTTER_LIBS) libmutter.la | ||||
|  | ||||
| libexec_PROGRAMS = mutter-restart-helper | ||||
| mutter_restart_helper_SOURCES = core/restart-helper.c | ||||
| mutter_restart_helper_LDADD = $(MUTTER_LIBS) | ||||
|  | ||||
| if HAVE_INTROSPECTION | ||||
| include $(INTROSPECTION_MAKEFILE) | ||||
|  | ||||
| @@ -335,7 +250,7 @@ INTROSPECTION_GIRS = Meta-$(api_version).gir | ||||
| Meta-$(api_version).gir: libmutter.la | ||||
| @META_GIR@_INCLUDES = GObject-2.0 GDesktopEnums-3.0 Gdk-3.0 Gtk-3.0 Clutter-1.0 xlib-2.0 xfixes-4.0 Cogl-1.0 | ||||
| @META_GIR@_EXPORT_PACKAGES = libmutter | ||||
| @META_GIR@_CFLAGS = $(AM_CPPFLAGS) | ||||
| @META_GIR@_CFLAGS = $(INCLUDES) | ||||
| @META_GIR@_LIBS = libmutter.la | ||||
| @META_GIR@_FILES =				\ | ||||
| 	mutter-enum-types.h			\ | ||||
| @@ -347,7 +262,7 @@ endif | ||||
|  | ||||
| testboxes_SOURCES = core/testboxes.c | ||||
| testgradient_SOURCES = ui/testgradient.c | ||||
| testasyncgetprop_SOURCES = x11/testasyncgetprop.c | ||||
| testasyncgetprop_SOURCES = core/testasyncgetprop.c | ||||
|  | ||||
| noinst_PROGRAMS=testboxes testgradient testasyncgetprop | ||||
|  | ||||
| @@ -355,25 +270,59 @@ testboxes_LDADD = $(MUTTER_LIBS) libmutter.la | ||||
| testgradient_LDADD = $(MUTTER_LIBS) libmutter.la | ||||
| testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter.la | ||||
|  | ||||
| dbus_idle_built_sources = meta-dbus-idle-monitor.c meta-dbus-idle-monitor.h | ||||
| @INTLTOOL_DESKTOP_RULE@ | ||||
|  | ||||
| desktopfilesdir=$(datadir)/applications | ||||
| desktopfiles_in_files=mutter.desktop.in | ||||
| desktopfiles_files=$(desktopfiles_in_files:.desktop.in=.desktop) | ||||
| desktopfiles_DATA = $(desktopfiles_files) | ||||
|  | ||||
| wmpropertiesdir=$(datadir)/gnome/wm-properties | ||||
| wmproperties_in_files=mutter-wm.desktop.in | ||||
| wmproperties_files=$(wmproperties_in_files:.desktop.in=.desktop) | ||||
| wmproperties_DATA = $(wmproperties_files) | ||||
|  | ||||
| xmldir       = @GNOME_KEYBINDINGS_KEYSDIR@ | ||||
| xml_in_files = \ | ||||
|         50-mutter-navigation.xml.in	\ | ||||
|         50-mutter-system.xml.in		\ | ||||
|         50-mutter-windows.xml.in | ||||
| xml_DATA     = $(xml_in_files:.xml.in=.xml) | ||||
|  | ||||
| gsettings_SCHEMAS = org.gnome.mutter.gschema.xml | ||||
| @INTLTOOL_XML_NOMERGE_RULE@ | ||||
| @GSETTINGS_RULES@ | ||||
|  | ||||
| convertdir = $(datadir)/GConf/gsettings | ||||
| convert_DATA = mutter-schemas.convert | ||||
|  | ||||
| CLEANFILES =					\ | ||||
| 	mutter.desktop				\ | ||||
| 	mutter-wm.desktop			\ | ||||
| 	org.gnome.mutter.gschema.xml		\ | ||||
| 	$(xml_DATA)				\ | ||||
| 	$(mutter_built_sources)			\ | ||||
| 	$(libmutterinclude_built_headers)	\ | ||||
| 	$(typelib_DATA)				\ | ||||
| 	$(gir_DATA) | ||||
|  | ||||
| pkgconfigdir = $(libdir)/pkgconfig | ||||
| pkgconfig_DATA = libmutter.pc | ||||
|  | ||||
| EXTRA_DIST =				\ | ||||
| 	$(wayland_protocols)		\ | ||||
| pkgconfig_DATA = libmutter.pc mutter-plugins.pc | ||||
|  | ||||
| EXTRA_DIST=$(desktopfiles_files) 	\ | ||||
| 	$(wmproperties_files)		\ | ||||
| 	$(IMAGES) 			\ | ||||
| 	$(desktopfiles_in_files)	\ | ||||
| 	$(wmproperties_in_files)	\ | ||||
| 	$(xml_in_files)			\ | ||||
| 	org.gnome.mutter.gschema.xml.in \ | ||||
| 	idle-monitor.xml \ | ||||
| 	xrandr.xml \ | ||||
| 	mutter-schemas.convert \ | ||||
| 	libmutter.pc.in \ | ||||
| 	mutter-plugins.pc.in  \ | ||||
| 	mutter-enum-types.h.in \ | ||||
| 	mutter-enum-types.c.in \ | ||||
| 	org.freedesktop.login1.xml	\ | ||||
| 	org.gnome.Mutter.DisplayConfig.xml	\ | ||||
| 	org.gnome.Mutter.IdleMonitor.xml | ||||
| 	mutter-enum-types.c.in | ||||
|  | ||||
| BUILT_SOURCES = $(mutter_built_sources) | ||||
| MUTTER_STAMP_FILES = stamp-mutter-enum-types.h | ||||
| @@ -398,33 +347,21 @@ mutter-enum-types.c: stamp-mutter-enum-types.h mutter-enum-types.c.in | ||||
| 	cp xgen-tetc mutter-enum-types.c && \ | ||||
| 	rm -f xgen-tetc | ||||
|  | ||||
| dbus_display_config_built_sources = meta-dbus-display-config.c meta-dbus-display-config.h | ||||
| dbus_xrandr_built_sources = meta-dbus-xrandr.c meta-dbus-xrandr.h | ||||
|  | ||||
| $(dbus_display_config_built_sources) : Makefile.am org.gnome.Mutter.DisplayConfig.xml | ||||
| $(dbus_xrandr_built_sources) : Makefile.am xrandr.xml | ||||
| 	$(AM_V_GEN)gdbus-codegen							\ | ||||
| 		--interface-prefix org.gnome.Mutter					\ | ||||
| 		--c-namespace MetaDBus							\ | ||||
| 		--generate-c-code meta-dbus-display-config				\ | ||||
| 		$(srcdir)/org.gnome.Mutter.DisplayConfig.xml | ||||
| 		--generate-c-code meta-dbus-xrandr					\ | ||||
| 		$(srcdir)/xrandr.xml | ||||
|  | ||||
| $(dbus_idle_built_sources) : Makefile.am org.gnome.Mutter.IdleMonitor.xml | ||||
| dbus_idle_built_sources = meta-dbus-idle-monitor.c meta-dbus-idle-monitor.h | ||||
|  | ||||
| $(dbus_idle_built_sources) : Makefile.am idle-monitor.xml | ||||
| 	$(AM_V_GEN)gdbus-codegen							\ | ||||
| 		--interface-prefix org.gnome.Mutter					\ | ||||
| 		--c-namespace MetaDBus							\ | ||||
| 		--generate-c-code meta-dbus-idle-monitor				\ | ||||
| 		--c-generate-object-manager						\ | ||||
| 		$(srcdir)/org.gnome.Mutter.IdleMonitor.xml | ||||
|  | ||||
| dbus_login1_built_sources = meta-dbus-login1.c meta-dbus-login1.h | ||||
|  | ||||
| $(dbus_login1_built_sources) : Makefile.am org.freedesktop.login1.xml | ||||
| 	$(AM_V_GEN)gdbus-codegen							\ | ||||
| 		--interface-prefix org.freedesktop.login1				\ | ||||
| 		--c-namespace Login1							\ | ||||
| 		--generate-c-code meta-dbus-login1					\ | ||||
| 		$(srcdir)/org.freedesktop.login1.xml | ||||
|  | ||||
| %-protocol.c : $(srcdir)/wayland/protocol/%.xml | ||||
| 	$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@ | ||||
| %-server-protocol.h : $(srcdir)/wayland/protocol/%.xml | ||||
| 	$(AM_V_GEN)$(WAYLAND_SCANNER) server-header < $< > $@ | ||||
| 		$(srcdir)/idle-monitor.xml | ||||
|   | ||||
| @@ -1,71 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2014 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Jasper St. Pierre <jstpierre@mecheye.net> | ||||
|  */ | ||||
|  | ||||
|  | ||||
| #ifndef META_BACKEND_PRIVATE_H | ||||
| #define META_BACKEND_PRIVATE_H | ||||
|  | ||||
| #include <glib-object.h> | ||||
|  | ||||
| #include "meta-backend.h" | ||||
|  | ||||
| #define META_TYPE_BACKEND             (meta_backend_get_type ()) | ||||
| #define META_BACKEND(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BACKEND, MetaBackend)) | ||||
| #define META_BACKEND_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_BACKEND, MetaBackendClass)) | ||||
| #define META_IS_BACKEND(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_BACKEND)) | ||||
| #define META_IS_BACKEND_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_BACKEND)) | ||||
| #define META_BACKEND_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_BACKEND, MetaBackendClass)) | ||||
|  | ||||
| struct _MetaBackend | ||||
| { | ||||
|   GObject parent; | ||||
|  | ||||
|   MetaIdleMonitor *device_monitors[256]; | ||||
|   int device_id_max; | ||||
| }; | ||||
|  | ||||
| struct _MetaBackendClass | ||||
| { | ||||
|   GObjectClass parent_class; | ||||
|  | ||||
|   void (* post_init) (MetaBackend *backend); | ||||
|  | ||||
|   MetaIdleMonitor * (* create_idle_monitor) (MetaBackend *backend, | ||||
|                                              int          device_id); | ||||
|   MetaMonitorManager * (* create_monitor_manager) (MetaBackend *backend); | ||||
|   MetaCursorRenderer * (* create_cursor_renderer) (MetaBackend *backend); | ||||
|  | ||||
|   gboolean (* grab_device) (MetaBackend *backend, | ||||
|                             int          device_id, | ||||
|                             uint32_t     timestamp); | ||||
|   gboolean (* ungrab_device) (MetaBackend *backend, | ||||
|                               int          device_id, | ||||
|                               uint32_t     timestamp); | ||||
|  | ||||
|   void (* warp_pointer) (MetaBackend *backend, | ||||
|                          int          x, | ||||
|                          int          y); | ||||
| }; | ||||
|  | ||||
| #endif /* META_BACKEND_PRIVATE_H */ | ||||
| @@ -1,290 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2014 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Jasper St. Pierre <jstpierre@mecheye.net> | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include "meta-backend.h" | ||||
| #include "meta-backend-private.h" | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| #include "backends/x11/meta-backend-x11.h" | ||||
|  | ||||
| #ifdef HAVE_NATIVE_BACKEND | ||||
| #include "backends/native/meta-backend-native.h" | ||||
| #endif | ||||
|  | ||||
| static MetaBackend *_backend; | ||||
|  | ||||
| MetaBackend * | ||||
| meta_get_backend (void) | ||||
| { | ||||
|   return _backend; | ||||
| } | ||||
|  | ||||
| struct _MetaBackendPrivate | ||||
| { | ||||
|   MetaMonitorManager *monitor_manager; | ||||
|   MetaCursorRenderer *cursor_renderer; | ||||
| }; | ||||
| typedef struct _MetaBackendPrivate MetaBackendPrivate; | ||||
|  | ||||
| G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaBackend, meta_backend, G_TYPE_OBJECT); | ||||
|  | ||||
| static void | ||||
| meta_backend_finalize (GObject *object) | ||||
| { | ||||
|   MetaBackend *backend = META_BACKEND (object); | ||||
|   MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); | ||||
|   int i; | ||||
|  | ||||
|   g_clear_object (&priv->monitor_manager); | ||||
|  | ||||
|   for (i = 0; i <= backend->device_id_max; i++) | ||||
|     { | ||||
|       if (backend->device_monitors[i]) | ||||
|         g_object_unref (backend->device_monitors[i]); | ||||
|     } | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_backend_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_backend_real_post_init (MetaBackend *backend) | ||||
| { | ||||
|   MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); | ||||
|  | ||||
|   priv->monitor_manager = META_BACKEND_GET_CLASS (backend)->create_monitor_manager (backend); | ||||
|   priv->cursor_renderer = META_BACKEND_GET_CLASS (backend)->create_cursor_renderer (backend); | ||||
| } | ||||
|  | ||||
| static MetaCursorRenderer * | ||||
| meta_backend_real_create_cursor_renderer (MetaBackend *backend) | ||||
| { | ||||
|   return meta_cursor_renderer_new (); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_backend_real_grab_device (MetaBackend *backend, | ||||
|                                int          device_id, | ||||
|                                uint32_t     timestamp) | ||||
| { | ||||
|   /* Do nothing */ | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_backend_real_ungrab_device (MetaBackend *backend, | ||||
|                                  int          device_id, | ||||
|                                  uint32_t     timestamp) | ||||
| { | ||||
|   /* Do nothing */ | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_backend_class_init (MetaBackendClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|  | ||||
|   object_class->finalize = meta_backend_finalize; | ||||
|  | ||||
|   klass->post_init = meta_backend_real_post_init; | ||||
|   klass->create_cursor_renderer = meta_backend_real_create_cursor_renderer; | ||||
|   klass->grab_device = meta_backend_real_grab_device; | ||||
|   klass->ungrab_device = meta_backend_real_ungrab_device; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_backend_init (MetaBackend *backend) | ||||
| { | ||||
|   _backend = backend; | ||||
| } | ||||
|  | ||||
| /* FIXME -- destroy device monitors at some point */ | ||||
| G_GNUC_UNUSED static void | ||||
| destroy_device_monitor (MetaBackend *backend, | ||||
|                         int          device_id) | ||||
| { | ||||
|   g_clear_object (&backend->device_monitors[device_id]); | ||||
|   if (device_id == backend->device_id_max) | ||||
|     backend->device_id_max--; | ||||
| } | ||||
|  | ||||
| static MetaIdleMonitor * | ||||
| meta_backend_create_idle_monitor (MetaBackend *backend, | ||||
|                                   int          device_id) | ||||
| { | ||||
|   return META_BACKEND_GET_CLASS (backend)->create_idle_monitor (backend, device_id); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_backend_post_init (MetaBackend *backend) | ||||
| { | ||||
|   META_BACKEND_GET_CLASS (backend)->post_init (backend); | ||||
| } | ||||
|  | ||||
| MetaIdleMonitor * | ||||
| meta_backend_get_idle_monitor (MetaBackend *backend, | ||||
|                                int          device_id) | ||||
| { | ||||
|   g_return_val_if_fail (device_id >= 0 && device_id < 256, NULL); | ||||
|  | ||||
|   if (!backend->device_monitors[device_id]) | ||||
|     { | ||||
|       backend->device_monitors[device_id] = meta_backend_create_idle_monitor (backend, device_id); | ||||
|       backend->device_id_max = MAX (backend->device_id_max, device_id); | ||||
|     } | ||||
|  | ||||
|   return backend->device_monitors[device_id]; | ||||
| } | ||||
|  | ||||
| MetaMonitorManager * | ||||
| meta_backend_get_monitor_manager (MetaBackend *backend) | ||||
| { | ||||
|   MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); | ||||
|  | ||||
|   return priv->monitor_manager; | ||||
| } | ||||
|  | ||||
| MetaCursorRenderer * | ||||
| meta_backend_get_cursor_renderer (MetaBackend *backend) | ||||
| { | ||||
|   MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); | ||||
|  | ||||
|   return priv->cursor_renderer; | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_backend_grab_device (MetaBackend *backend, | ||||
|                           int          device_id, | ||||
|                           uint32_t     timestamp) | ||||
| { | ||||
|   return META_BACKEND_GET_CLASS (backend)->grab_device (backend, device_id, timestamp); | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_backend_ungrab_device (MetaBackend *backend, | ||||
|                             int          device_id, | ||||
|                             uint32_t     timestamp) | ||||
| { | ||||
|   return META_BACKEND_GET_CLASS (backend)->ungrab_device (backend, device_id, timestamp); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_backend_warp_pointer (MetaBackend *backend, | ||||
|                            int          x, | ||||
|                            int          y) | ||||
| { | ||||
|   META_BACKEND_GET_CLASS (backend)->warp_pointer (backend, x, y); | ||||
| } | ||||
|  | ||||
| static GType | ||||
| get_backend_type (void) | ||||
| { | ||||
| #if defined(CLUTTER_WINDOWING_X11) | ||||
|   if (clutter_check_windowing_backend (CLUTTER_WINDOWING_X11)) | ||||
|     return META_TYPE_BACKEND_X11; | ||||
| #endif | ||||
|  | ||||
| #if defined(CLUTTER_WINDOWING_EGL) && defined(HAVE_NATIVE_BACKEND) | ||||
|   if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL)) | ||||
|     return META_TYPE_BACKEND_NATIVE; | ||||
| #endif | ||||
|  | ||||
|   g_assert_not_reached (); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_create_backend (void) | ||||
| { | ||||
|   /* meta_backend_init() above install the backend globally so | ||||
|    * so meta_get_backend() works even during initialization. */ | ||||
|   g_object_new (get_backend_type (), NULL); | ||||
| } | ||||
|  | ||||
| /* Mutter is responsible for pulling events off the X queue, so Clutter | ||||
|  * doesn't need (and shouldn't) run its normal event source which polls | ||||
|  * the X fd, but we do have to deal with dispatching events that accumulate | ||||
|  * in the clutter queue. This happens, for example, when clutter generate | ||||
|  * enter/leave events on mouse motion - several events are queued in the | ||||
|  * clutter queue but only one dispatched. It could also happen because of | ||||
|  * explicit calls to clutter_event_put(). We add a very simple custom | ||||
|  * event loop source which is simply responsible for pulling events off | ||||
|  * of the queue and dispatching them before we block for new events. | ||||
|  */ | ||||
|  | ||||
| static gboolean | ||||
| event_prepare (GSource    *source, | ||||
|                gint       *timeout_) | ||||
| { | ||||
|   *timeout_ = -1; | ||||
|  | ||||
|   return clutter_events_pending (); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| event_check (GSource *source) | ||||
| { | ||||
|   return clutter_events_pending (); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| event_dispatch (GSource    *source, | ||||
|                 GSourceFunc callback, | ||||
|                 gpointer    user_data) | ||||
| { | ||||
|   ClutterEvent *event = clutter_event_get (); | ||||
|  | ||||
|   if (event) | ||||
|     { | ||||
|       clutter_do_event (event); | ||||
|       clutter_event_free (event); | ||||
|     } | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static GSourceFuncs event_funcs = { | ||||
|   event_prepare, | ||||
|   event_check, | ||||
|   event_dispatch | ||||
| }; | ||||
|  | ||||
| void | ||||
| meta_clutter_init (void) | ||||
| { | ||||
|   GSource *source; | ||||
|  | ||||
|   meta_create_backend (); | ||||
|  | ||||
|   if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS) | ||||
|     g_error ("Unable to initialize Clutter.\n"); | ||||
|  | ||||
|   source = g_source_new (&event_funcs, sizeof (GSource)); | ||||
|   g_source_attach (source, NULL); | ||||
|   g_source_unref (source); | ||||
|  | ||||
|   meta_backend_post_init (_backend); | ||||
| } | ||||
| @@ -1,59 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2014 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Jasper St. Pierre <jstpierre@mecheye.net> | ||||
|  */ | ||||
|  | ||||
| #ifndef META_BACKEND_H | ||||
| #define META_BACKEND_H | ||||
|  | ||||
| #include <glib-object.h> | ||||
|  | ||||
| #include <meta/meta-idle-monitor.h> | ||||
| #include "meta-monitor-manager.h" | ||||
| #include "meta-cursor-renderer.h" | ||||
|  | ||||
| typedef struct _MetaBackend        MetaBackend; | ||||
| typedef struct _MetaBackendClass   MetaBackendClass; | ||||
|  | ||||
| GType meta_backend_get_type (void); | ||||
|  | ||||
| MetaBackend * meta_get_backend (void); | ||||
|  | ||||
| MetaIdleMonitor * meta_backend_get_idle_monitor (MetaBackend *backend, | ||||
|                                                  int          device_id); | ||||
| MetaMonitorManager * meta_backend_get_monitor_manager (MetaBackend *backend); | ||||
| MetaCursorRenderer * meta_backend_get_cursor_renderer (MetaBackend *backend); | ||||
|  | ||||
| gboolean meta_backend_grab_device (MetaBackend *backend, | ||||
|                                    int          device_id, | ||||
|                                    uint32_t     timestamp); | ||||
| gboolean meta_backend_ungrab_device (MetaBackend *backend, | ||||
|                                      int          device_id, | ||||
|                                      uint32_t     timestamp); | ||||
|  | ||||
| void meta_backend_warp_pointer (MetaBackend *backend, | ||||
|                                 int          x, | ||||
|                                 int          y); | ||||
|  | ||||
| void meta_clutter_init (void); | ||||
|  | ||||
| #endif /* META_BACKEND_H */ | ||||
| @@ -1,51 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright 2013 Red Hat, Inc. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * Author: Giovanni Campagna <gcampagn@redhat.com> | ||||
|  */ | ||||
|  | ||||
| #ifndef META_CURSOR_PRIVATE_H | ||||
| #define META_CURSOR_PRIVATE_H | ||||
|  | ||||
| #include "meta-cursor.h" | ||||
|  | ||||
| #include <cogl/cogl.h> | ||||
| #include <gbm.h> | ||||
|  | ||||
| typedef struct { | ||||
|   CoglTexture2D *texture; | ||||
|   struct gbm_bo *bo; | ||||
|   int hot_x, hot_y; | ||||
| } MetaCursorImage; | ||||
|  | ||||
| struct _MetaCursorReference { | ||||
|   int ref_count; | ||||
|  | ||||
|   MetaCursor cursor; | ||||
|   MetaCursorImage image; | ||||
| }; | ||||
|  | ||||
| CoglTexture *meta_cursor_reference_get_cogl_texture (MetaCursorReference *cursor, | ||||
|                                                      int                 *hot_x, | ||||
|                                                      int                 *hot_y); | ||||
|  | ||||
| struct gbm_bo *meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor, | ||||
|                                                  int                 *hot_x, | ||||
|                                                  int                 *hot_y); | ||||
|  | ||||
| #endif /* META_CURSOR_PRIVATE_H */ | ||||
| @@ -1,172 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2014 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Jasper St. Pierre <jstpierre@mecheye.net> | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include "meta-cursor-renderer.h" | ||||
| #include "meta-cursor-private.h" | ||||
|  | ||||
| #include <cogl/cogl.h> | ||||
| #include <cogl/cogl-wayland-server.h> | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| #include "meta-stage.h" | ||||
|  | ||||
| #include "wayland/meta-wayland-private.h" | ||||
|  | ||||
| struct _MetaCursorRendererPrivate | ||||
| { | ||||
|   int current_x, current_y; | ||||
|   MetaRectangle current_rect; | ||||
|  | ||||
|   MetaCursorReference *displayed_cursor; | ||||
|   gboolean handled_by_backend; | ||||
| }; | ||||
| typedef struct _MetaCursorRendererPrivate MetaCursorRendererPrivate; | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRenderer, meta_cursor_renderer, G_TYPE_OBJECT); | ||||
|  | ||||
| static void | ||||
| queue_redraw (MetaCursorRenderer *renderer) | ||||
| { | ||||
|   MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); | ||||
|   MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); | ||||
|   ClutterActor *stage = compositor->stage; | ||||
|  | ||||
|   /* During early initialization, we can have no stage */ | ||||
|   if (!stage) | ||||
|     return; | ||||
|  | ||||
|   if (priv->handled_by_backend) | ||||
|     meta_stage_set_cursor (META_STAGE (stage), NULL, &priv->current_rect); | ||||
|   else | ||||
|     meta_stage_set_cursor (META_STAGE (stage), priv->displayed_cursor, &priv->current_rect); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_cursor_renderer_real_update_cursor (MetaCursorRenderer *renderer) | ||||
| { | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_cursor_renderer_class_init (MetaCursorRendererClass *klass) | ||||
| { | ||||
|   klass->update_cursor = meta_cursor_renderer_real_update_cursor; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_cursor_renderer_init (MetaCursorRenderer *renderer) | ||||
| { | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_cursor (MetaCursorRenderer *renderer) | ||||
| { | ||||
|   MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); | ||||
|   gboolean handled_by_backend; | ||||
|   gboolean should_redraw = FALSE; | ||||
|  | ||||
|   if (priv->displayed_cursor) | ||||
|     { | ||||
|       CoglTexture *texture; | ||||
|       int hot_x, hot_y; | ||||
|  | ||||
|       texture = meta_cursor_reference_get_cogl_texture (priv->displayed_cursor, &hot_x, &hot_y); | ||||
|  | ||||
|       priv->current_rect.x = priv->current_x - hot_x; | ||||
|       priv->current_rect.y = priv->current_y - hot_y; | ||||
|       priv->current_rect.width = cogl_texture_get_width (COGL_TEXTURE (texture)); | ||||
|       priv->current_rect.height = cogl_texture_get_height (COGL_TEXTURE (texture)); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       priv->current_rect.x = 0; | ||||
|       priv->current_rect.y = 0; | ||||
|       priv->current_rect.width = 0; | ||||
|       priv->current_rect.height = 0; | ||||
|     } | ||||
|  | ||||
|   handled_by_backend = META_CURSOR_RENDERER_GET_CLASS (renderer)->update_cursor (renderer); | ||||
|   if (handled_by_backend != priv->handled_by_backend) | ||||
|     { | ||||
|       priv->handled_by_backend = handled_by_backend; | ||||
|       should_redraw = TRUE; | ||||
|     } | ||||
|  | ||||
|   if (!handled_by_backend) | ||||
|     should_redraw = TRUE; | ||||
|  | ||||
|   if (should_redraw) | ||||
|     queue_redraw (renderer); | ||||
| } | ||||
|  | ||||
| MetaCursorRenderer * | ||||
| meta_cursor_renderer_new (void) | ||||
| { | ||||
|   return g_object_new (META_TYPE_CURSOR_RENDERER, NULL); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_renderer_set_cursor (MetaCursorRenderer  *renderer, | ||||
|                                  MetaCursorReference *cursor) | ||||
| { | ||||
|   MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); | ||||
|  | ||||
|   if (priv->displayed_cursor == cursor) | ||||
|     return; | ||||
|  | ||||
|   priv->displayed_cursor = cursor; | ||||
|   update_cursor (renderer); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_renderer_set_position (MetaCursorRenderer *renderer, | ||||
|                                    int x, int y) | ||||
| { | ||||
|   MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); | ||||
|  | ||||
|   g_assert (meta_is_wayland_compositor ()); | ||||
|  | ||||
|   priv->current_x = x; | ||||
|   priv->current_y = y; | ||||
|  | ||||
|   update_cursor (renderer); | ||||
| } | ||||
|  | ||||
| MetaCursorReference * | ||||
| meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer) | ||||
| { | ||||
|   MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); | ||||
|  | ||||
|   return priv->displayed_cursor; | ||||
| } | ||||
|  | ||||
| const MetaRectangle * | ||||
| meta_cursor_renderer_get_rect (MetaCursorRenderer *renderer) | ||||
| { | ||||
|   MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); | ||||
|  | ||||
|   return &priv->current_rect; | ||||
| } | ||||
| @@ -1,70 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2014 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Jasper St. Pierre <jstpierre@mecheye.net> | ||||
|  */ | ||||
|  | ||||
| #ifndef META_CURSOR_RENDERER_H | ||||
| #define META_CURSOR_RENDERER_H | ||||
|  | ||||
| #include <glib-object.h> | ||||
|  | ||||
| #include <meta/screen.h> | ||||
| #include "meta-cursor.h" | ||||
|  | ||||
| #include <gbm.h> | ||||
|  | ||||
| #define META_TYPE_CURSOR_RENDERER            (meta_cursor_renderer_get_type ()) | ||||
| #define META_CURSOR_RENDERER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CURSOR_RENDERER, MetaCursorRenderer)) | ||||
| #define META_CURSOR_RENDERER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_CURSOR_RENDERER, MetaCursorRendererClass)) | ||||
| #define META_IS_CURSOR_RENDERER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_CURSOR_RENDERER)) | ||||
| #define META_IS_CURSOR_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_CURSOR_RENDERER)) | ||||
| #define META_CURSOR_RENDERER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_CURSOR_RENDERER, MetaCursorRendererClass)) | ||||
|  | ||||
| typedef struct _MetaCursorRenderer        MetaCursorRenderer; | ||||
| typedef struct _MetaCursorRendererClass   MetaCursorRendererClass; | ||||
|  | ||||
| struct _MetaCursorRenderer | ||||
| { | ||||
|   GObject parent; | ||||
| }; | ||||
|  | ||||
| struct _MetaCursorRendererClass | ||||
| { | ||||
|   GObjectClass parent_class; | ||||
|  | ||||
|   gboolean (* update_cursor) (MetaCursorRenderer *renderer); | ||||
| }; | ||||
|  | ||||
| GType meta_cursor_renderer_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| MetaCursorRenderer * meta_cursor_renderer_new (void); | ||||
|  | ||||
| void meta_cursor_renderer_set_cursor (MetaCursorRenderer  *renderer, | ||||
|                                       MetaCursorReference *cursor); | ||||
|  | ||||
| void meta_cursor_renderer_set_position (MetaCursorRenderer *renderer, | ||||
|                                         int x, int y); | ||||
|  | ||||
| MetaCursorReference * meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer); | ||||
| const MetaRectangle * meta_cursor_renderer_get_rect (MetaCursorRenderer *renderer); | ||||
|  | ||||
| #endif /* META_CURSOR_RENDERER_H */ | ||||
| @@ -1,75 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright 2013 Red Hat, Inc. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * Author: Giovanni Campagna <gcampagn@redhat.com> | ||||
|  */ | ||||
|  | ||||
| #ifndef META_CURSOR_TRACKER_PRIVATE_H | ||||
| #define META_CURSOR_TRACKER_PRIVATE_H | ||||
|  | ||||
| #include <meta/meta-cursor-tracker.h> | ||||
| #include <wayland-server.h> | ||||
| #include <gbm.h> | ||||
|  | ||||
| #include "meta-cursor.h" | ||||
| #include "meta-cursor-renderer.h" | ||||
|  | ||||
| struct _MetaCursorTracker { | ||||
|   GObject parent_instance; | ||||
|  | ||||
|   MetaScreen *screen; | ||||
|   MetaCursorRenderer *renderer; | ||||
|  | ||||
|   gboolean is_showing; | ||||
|  | ||||
|   MetaCursorReference *displayed_cursor; | ||||
|  | ||||
|   /* Wayland clients can set a NULL buffer as their cursor | ||||
|    * explicitly, which means that we shouldn't display anything. | ||||
|    * So, we can't simply store a NULL in window_cursor to | ||||
|    * determine an unset window cursor; we need an extra boolean. | ||||
|    */ | ||||
|   gboolean has_window_cursor; | ||||
|   MetaCursorReference *window_cursor; | ||||
|  | ||||
|   MetaCursorReference *root_cursor; | ||||
|  | ||||
|   /* The cursor from the X11 server. */ | ||||
|   MetaCursorReference *xfixes_cursor; | ||||
| }; | ||||
|  | ||||
| struct _MetaCursorTrackerClass { | ||||
|   GObjectClass parent_class; | ||||
| }; | ||||
|  | ||||
| gboolean meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker, | ||||
| 					    XEvent            *xevent); | ||||
|  | ||||
| void     meta_cursor_tracker_set_window_cursor   (MetaCursorTracker   *tracker, | ||||
|                                                   MetaCursorReference *cursor); | ||||
| void     meta_cursor_tracker_unset_window_cursor (MetaCursorTracker   *tracker); | ||||
| void     meta_cursor_tracker_set_root_cursor     (MetaCursorTracker   *tracker, | ||||
|                                                   MetaCursorReference *cursor); | ||||
|  | ||||
| void     meta_cursor_tracker_update_position (MetaCursorTracker *tracker, | ||||
| 					      int                new_x, | ||||
| 					      int                new_y); | ||||
|  | ||||
| MetaCursorReference * meta_cursor_tracker_get_displayed_cursor (MetaCursorTracker *tracker); | ||||
|  | ||||
| #endif | ||||
| @@ -1,478 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright 2013 Red Hat, Inc. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * Author: Giovanni Campagna <gcampagn@redhat.com> | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * SECTION:cursor-tracker | ||||
|  * @title: MetaCursorTracker | ||||
|  * @short_description: Mutter cursor tracking helper. Originally only | ||||
|  *                     tracking the cursor image, now more of a "core | ||||
|  *                     pointer abstraction" | ||||
|  */ | ||||
|  | ||||
| #include <config.h> | ||||
| #include <string.h> | ||||
| #include <meta/main.h> | ||||
| #include <meta/util.h> | ||||
| #include <meta/errors.h> | ||||
|  | ||||
| #include <cogl/cogl.h> | ||||
| #include <cogl/cogl-wayland-server.h> | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| #include <gdk/gdk.h> | ||||
| #include <gdk/gdkx.h> | ||||
|  | ||||
| #include "meta-backend.h" | ||||
|  | ||||
| #include "meta-cursor-private.h" | ||||
| #include "meta-cursor-tracker-private.h" | ||||
| #include "screen-private.h" | ||||
|  | ||||
| #include "wayland/meta-wayland-private.h" | ||||
|  | ||||
| G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT); | ||||
|  | ||||
| enum { | ||||
|     CURSOR_CHANGED, | ||||
|     LAST_SIGNAL | ||||
| }; | ||||
|  | ||||
| static guint signals[LAST_SIGNAL]; | ||||
|  | ||||
| static MetaCursorReference * | ||||
| get_displayed_cursor (MetaCursorTracker *tracker) | ||||
| { | ||||
|   if (!tracker->is_showing) | ||||
|     return NULL; | ||||
|  | ||||
|   if (tracker->screen->display->grab_op == META_GRAB_OP_NONE) | ||||
|     { | ||||
|       if (tracker->has_window_cursor) | ||||
|         return tracker->window_cursor; | ||||
|     } | ||||
|  | ||||
|   return tracker->root_cursor; | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_displayed_cursor (MetaCursorTracker *tracker) | ||||
| { | ||||
|   meta_cursor_renderer_set_cursor (tracker->renderer, tracker->displayed_cursor); | ||||
| } | ||||
|  | ||||
| static void | ||||
| sync_cursor (MetaCursorTracker *tracker) | ||||
| { | ||||
|   MetaCursorReference *displayed_cursor = get_displayed_cursor (tracker); | ||||
|  | ||||
|   if (tracker->displayed_cursor == displayed_cursor) | ||||
|     return; | ||||
|  | ||||
|   g_clear_pointer (&tracker->displayed_cursor, meta_cursor_reference_unref); | ||||
|   if (displayed_cursor) | ||||
|     tracker->displayed_cursor = meta_cursor_reference_ref (displayed_cursor); | ||||
|  | ||||
|   update_displayed_cursor (tracker); | ||||
|   g_signal_emit (tracker, signals[CURSOR_CHANGED], 0); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_cursor_tracker_init (MetaCursorTracker *self) | ||||
| { | ||||
|   self->is_showing = TRUE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_cursor_tracker_finalize (GObject *object) | ||||
| { | ||||
|   MetaCursorTracker *self = META_CURSOR_TRACKER (object); | ||||
|  | ||||
|   if (self->displayed_cursor) | ||||
|     meta_cursor_reference_unref (self->displayed_cursor); | ||||
|   if (self->root_cursor) | ||||
|     meta_cursor_reference_unref (self->root_cursor); | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_cursor_tracker_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|  | ||||
|   object_class->finalize = meta_cursor_tracker_finalize; | ||||
|  | ||||
|   signals[CURSOR_CHANGED] = g_signal_new ("cursor-changed", | ||||
|                                           G_TYPE_FROM_CLASS (klass), | ||||
|                                           G_SIGNAL_RUN_LAST, | ||||
|                                           0, | ||||
|                                           NULL, NULL, NULL, | ||||
|                                           G_TYPE_NONE, 0); | ||||
| } | ||||
|  | ||||
| static MetaCursorTracker * | ||||
| make_wayland_cursor_tracker (MetaScreen *screen) | ||||
| { | ||||
|   MetaBackend *backend = meta_get_backend (); | ||||
|   MetaWaylandCompositor *compositor; | ||||
|   MetaCursorTracker *self; | ||||
|  | ||||
|   self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL); | ||||
|   self->screen = screen; | ||||
|   self->renderer = meta_backend_get_cursor_renderer (backend); | ||||
|  | ||||
|   compositor = meta_wayland_compositor_get_default (); | ||||
|   compositor->seat->pointer.cursor_tracker = self; | ||||
|   meta_cursor_tracker_update_position (self, 0, 0); | ||||
|  | ||||
|   return self; | ||||
| } | ||||
|  | ||||
| static MetaCursorTracker * | ||||
| make_x11_cursor_tracker (MetaScreen *screen) | ||||
| { | ||||
|   MetaBackend *backend = meta_get_backend (); | ||||
|   MetaCursorTracker *self; | ||||
|  | ||||
|   self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL); | ||||
|   self->screen = screen; | ||||
|   self->renderer = meta_backend_get_cursor_renderer (backend); | ||||
|  | ||||
|   XFixesSelectCursorInput (screen->display->xdisplay, | ||||
|                            screen->xroot, | ||||
|                            XFixesDisplayCursorNotifyMask); | ||||
|  | ||||
|   return self; | ||||
| } | ||||
|  | ||||
| static MetaCursorTracker * | ||||
| meta_cursor_tracker_new (MetaScreen *screen) | ||||
| { | ||||
|   if (meta_is_wayland_compositor ()) | ||||
|     return make_wayland_cursor_tracker (screen); | ||||
|   else | ||||
|     return make_x11_cursor_tracker (screen); | ||||
| } | ||||
|  | ||||
| static MetaCursorTracker *_cursor_tracker; | ||||
|  | ||||
| /** | ||||
|  * meta_cursor_tracker_get_for_screen: | ||||
|  * @screen: the #MetaScreen | ||||
|  * | ||||
|  * Retrieves the cursor tracker object for @screen. | ||||
|  * | ||||
|  * Returns: (transfer none): | ||||
|  */ | ||||
| MetaCursorTracker * | ||||
| meta_cursor_tracker_get_for_screen (MetaScreen *screen) | ||||
| { | ||||
|   if (!_cursor_tracker) | ||||
|     _cursor_tracker = meta_cursor_tracker_new (screen); | ||||
|  | ||||
|   return _cursor_tracker; | ||||
| } | ||||
|  | ||||
| static void | ||||
| set_window_cursor (MetaCursorTracker   *tracker, | ||||
|                    gboolean             has_cursor, | ||||
|                    MetaCursorReference *cursor) | ||||
| { | ||||
|   g_clear_pointer (&tracker->window_cursor, meta_cursor_reference_unref); | ||||
|   if (cursor) | ||||
|     tracker->window_cursor = meta_cursor_reference_ref (cursor); | ||||
|   tracker->has_window_cursor = has_cursor; | ||||
|   sync_cursor (tracker); | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker, | ||||
|                                    XEvent            *xevent) | ||||
| { | ||||
|   XFixesCursorNotifyEvent *notify_event; | ||||
|  | ||||
|   if (meta_is_wayland_compositor ()) | ||||
|     return FALSE; | ||||
|  | ||||
|   if (xevent->xany.type != tracker->screen->display->xfixes_event_base + XFixesCursorNotify) | ||||
|     return FALSE; | ||||
|  | ||||
|   notify_event = (XFixesCursorNotifyEvent *)xevent; | ||||
|   if (notify_event->subtype != XFixesDisplayCursorNotify) | ||||
|     return FALSE; | ||||
|  | ||||
|   g_clear_pointer (&tracker->xfixes_cursor, meta_cursor_reference_unref); | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static MetaCursorReference * | ||||
| meta_cursor_reference_take_texture (CoglTexture2D *texture, | ||||
|                                     int            hot_x, | ||||
|                                     int            hot_y) | ||||
| { | ||||
|   MetaCursorReference *self; | ||||
|  | ||||
|   self = g_slice_new0 (MetaCursorReference); | ||||
|   self->ref_count = 1; | ||||
|   self->image.texture = texture; | ||||
|   self->image.hot_x = hot_x; | ||||
|   self->image.hot_y = hot_y; | ||||
|  | ||||
|   return self; | ||||
| } | ||||
|  | ||||
| static void | ||||
| ensure_xfixes_cursor (MetaCursorTracker *tracker) | ||||
| { | ||||
|   XFixesCursorImage *cursor_image; | ||||
|   CoglTexture2D *sprite; | ||||
|   guint8 *cursor_data; | ||||
|   gboolean free_cursor_data; | ||||
|   CoglContext *ctx; | ||||
|  | ||||
|   if (tracker->xfixes_cursor) | ||||
|     return; | ||||
|  | ||||
|   cursor_image = XFixesGetCursorImage (tracker->screen->display->xdisplay); | ||||
|   if (!cursor_image) | ||||
|     return; | ||||
|  | ||||
|   /* Like all X APIs, XFixesGetCursorImage() returns arrays of 32-bit | ||||
|    * quantities as arrays of long; we need to convert on 64 bit */ | ||||
|   if (sizeof(long) == 4) | ||||
|     { | ||||
|       cursor_data = (guint8 *)cursor_image->pixels; | ||||
|       free_cursor_data = FALSE; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       int i, j; | ||||
|       guint32 *cursor_words; | ||||
|       gulong *p; | ||||
|       guint32 *q; | ||||
|  | ||||
|       cursor_words = g_new (guint32, cursor_image->width * cursor_image->height); | ||||
|       cursor_data = (guint8 *)cursor_words; | ||||
|  | ||||
|       p = cursor_image->pixels; | ||||
|       q = cursor_words; | ||||
|       for (j = 0; j < cursor_image->height; j++) | ||||
|         for (i = 0; i < cursor_image->width; i++) | ||||
|           *(q++) = *(p++); | ||||
|  | ||||
|       free_cursor_data = TRUE; | ||||
|     } | ||||
|  | ||||
|   ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); | ||||
|   sprite = cogl_texture_2d_new_from_data (ctx, | ||||
|                                           cursor_image->width, | ||||
|                                           cursor_image->height, | ||||
|                                           CLUTTER_CAIRO_FORMAT_ARGB32, | ||||
|                                           cursor_image->width * 4, /* stride */ | ||||
|                                           cursor_data, | ||||
|                                           NULL); | ||||
|  | ||||
|   if (free_cursor_data) | ||||
|     g_free (cursor_data); | ||||
|  | ||||
|   if (sprite != NULL) | ||||
|     { | ||||
|       MetaCursorReference *cursor = meta_cursor_reference_take_texture (sprite, | ||||
|                                                                         cursor_image->xhot, | ||||
|                                                                         cursor_image->yhot); | ||||
|       tracker->xfixes_cursor = cursor; | ||||
|     } | ||||
|   XFree (cursor_image); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_cursor_tracker_get_sprite: | ||||
|  * | ||||
|  * Returns: (transfer none): | ||||
|  */ | ||||
| CoglTexture * | ||||
| meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker) | ||||
| { | ||||
|   MetaCursorReference *cursor; | ||||
|  | ||||
|   g_return_val_if_fail (META_IS_CURSOR_TRACKER (tracker), NULL); | ||||
|  | ||||
|   if (meta_is_wayland_compositor ()) | ||||
|     { | ||||
|       cursor = tracker->displayed_cursor; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       ensure_xfixes_cursor (tracker); | ||||
|       cursor = tracker->xfixes_cursor; | ||||
|     } | ||||
|  | ||||
|   if (cursor) | ||||
|     return meta_cursor_reference_get_cogl_texture (cursor, NULL, NULL); | ||||
|   else | ||||
|     return NULL; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_cursor_tracker_get_hot: | ||||
|  * @tracker: | ||||
|  * @x: (out): | ||||
|  * @y: (out): | ||||
|  * | ||||
|  */ | ||||
| void | ||||
| meta_cursor_tracker_get_hot (MetaCursorTracker *tracker, | ||||
|                              int               *x, | ||||
|                              int               *y) | ||||
| { | ||||
|   MetaCursorReference *cursor; | ||||
|  | ||||
|   g_return_if_fail (META_IS_CURSOR_TRACKER (tracker)); | ||||
|  | ||||
|   if (meta_is_wayland_compositor ()) | ||||
|     { | ||||
|       cursor = tracker->displayed_cursor; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       ensure_xfixes_cursor (tracker); | ||||
|       cursor = tracker->xfixes_cursor; | ||||
|     } | ||||
|  | ||||
|   if (cursor) | ||||
|     meta_cursor_reference_get_cogl_texture (cursor, x, y); | ||||
|   else | ||||
|     { | ||||
|       if (x) | ||||
|         *x = 0; | ||||
|       if (y) | ||||
|         *y = 0; | ||||
|     } | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_tracker_set_window_cursor (MetaCursorTracker   *tracker, | ||||
|                                        MetaCursorReference *cursor) | ||||
| { | ||||
|   set_window_cursor (tracker, TRUE, cursor); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker) | ||||
| { | ||||
|   set_window_cursor (tracker, FALSE, NULL); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_tracker_set_root_cursor (MetaCursorTracker   *tracker, | ||||
|                                      MetaCursorReference *cursor) | ||||
| { | ||||
|   g_clear_pointer (&tracker->root_cursor, meta_cursor_reference_unref); | ||||
|   if (cursor) | ||||
|     tracker->root_cursor = meta_cursor_reference_ref (cursor); | ||||
|  | ||||
|   sync_cursor (tracker); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_tracker_update_position (MetaCursorTracker *tracker, | ||||
|                                      int                new_x, | ||||
|                                      int                new_y) | ||||
| { | ||||
|   g_assert (meta_is_wayland_compositor ()); | ||||
|  | ||||
|   meta_cursor_renderer_set_position (tracker->renderer, new_x, new_y); | ||||
| } | ||||
|  | ||||
| static void | ||||
| get_pointer_position_gdk (int         *x, | ||||
|                           int         *y, | ||||
|                           int         *mods) | ||||
| { | ||||
|   GdkDeviceManager *gmanager; | ||||
|   GdkDevice *gdevice; | ||||
|   GdkScreen *gscreen; | ||||
|  | ||||
|   gmanager = gdk_display_get_device_manager (gdk_display_get_default ()); | ||||
|   gdevice = gdk_x11_device_manager_lookup (gmanager, META_VIRTUAL_CORE_POINTER_ID); | ||||
|  | ||||
|   gdk_device_get_position (gdevice, &gscreen, x, y); | ||||
|   if (mods) | ||||
|     gdk_device_get_state (gdevice, | ||||
|                           gdk_screen_get_root_window (gscreen), | ||||
|                           NULL, (GdkModifierType*)mods); | ||||
| } | ||||
|  | ||||
| static void | ||||
| get_pointer_position_clutter (int         *x, | ||||
|                               int         *y, | ||||
|                               int         *mods) | ||||
| { | ||||
|   ClutterDeviceManager *cmanager; | ||||
|   ClutterInputDevice *cdevice; | ||||
|   ClutterPoint point; | ||||
|  | ||||
|   cmanager = clutter_device_manager_get_default (); | ||||
|   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); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_tracker_get_pointer (MetaCursorTracker   *tracker, | ||||
|                                  int                 *x, | ||||
|                                  int                 *y, | ||||
|                                  ClutterModifierType *mods) | ||||
| { | ||||
|   /* We can't use the clutter interface when not running as a wayland compositor, | ||||
|      because we need to query the server, rather than using the last cached value. | ||||
|      OTOH, on wayland we can't use GDK, because that only sees the events | ||||
|      we forward to xwayland. | ||||
|   */ | ||||
|   if (meta_is_wayland_compositor ()) | ||||
|     get_pointer_position_clutter (x, y, (int*)mods); | ||||
|   else | ||||
|     get_pointer_position_gdk (x, y, (int*)mods); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker, | ||||
|                                          gboolean           visible) | ||||
| { | ||||
|   if (visible == tracker->is_showing) | ||||
|     return; | ||||
|   tracker->is_showing = visible; | ||||
|  | ||||
|   sync_cursor (tracker); | ||||
| } | ||||
|  | ||||
| MetaCursorReference * | ||||
| meta_cursor_tracker_get_displayed_cursor (MetaCursorTracker *tracker) | ||||
| { | ||||
|   return tracker->displayed_cursor; | ||||
| } | ||||
| @@ -1,377 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright 2013 Red Hat, Inc. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * Author: Giovanni Campagna <gcampagn@redhat.com> | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include "meta-cursor-private.h" | ||||
|  | ||||
| #include <meta/errors.h> | ||||
|  | ||||
| #include "display-private.h" | ||||
| #include "screen-private.h" | ||||
| #include "meta-backend.h" | ||||
|  | ||||
| #ifdef HAVE_NATIVE_BACKEND | ||||
| #include "backends/native/meta-cursor-renderer-native.h" | ||||
| #endif | ||||
|  | ||||
| #include <string.h> | ||||
|  | ||||
| #include <X11/cursorfont.h> | ||||
| #include <X11/extensions/Xfixes.h> | ||||
| #include <X11/Xcursor/Xcursor.h> | ||||
|  | ||||
| #include <cogl/cogl-wayland-server.h> | ||||
|  | ||||
| MetaCursorReference * | ||||
| meta_cursor_reference_ref (MetaCursorReference *self) | ||||
| { | ||||
|   g_assert (self->ref_count > 0); | ||||
|   self->ref_count++; | ||||
|  | ||||
|   return self; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_cursor_image_free (MetaCursorImage *image) | ||||
| { | ||||
|   cogl_object_unref (image->texture); | ||||
|   if (image->bo) | ||||
|     gbm_bo_destroy (image->bo); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_cursor_reference_free (MetaCursorReference *self) | ||||
| { | ||||
|   meta_cursor_image_free (&self->image); | ||||
|   g_slice_free (MetaCursorReference, self); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_reference_unref (MetaCursorReference *self) | ||||
| { | ||||
|   self->ref_count--; | ||||
|  | ||||
|   if (self->ref_count == 0) | ||||
|     meta_cursor_reference_free (self); | ||||
| } | ||||
|  | ||||
| static const char * | ||||
| translate_meta_cursor (MetaCursor cursor) | ||||
| { | ||||
|   switch (cursor) | ||||
|     { | ||||
|     case META_CURSOR_DEFAULT: | ||||
|       return "left_ptr"; | ||||
|     case META_CURSOR_NORTH_RESIZE: | ||||
|       return "top_side"; | ||||
|     case META_CURSOR_SOUTH_RESIZE: | ||||
|       return "bottom_side"; | ||||
|     case META_CURSOR_WEST_RESIZE: | ||||
|       return "left_side"; | ||||
|     case META_CURSOR_EAST_RESIZE: | ||||
|       return "right_side"; | ||||
|     case META_CURSOR_SE_RESIZE: | ||||
|       return "bottom_right_corner"; | ||||
|     case META_CURSOR_SW_RESIZE: | ||||
|       return "bottom_left_corner"; | ||||
|     case META_CURSOR_NE_RESIZE: | ||||
|       return "top_right_corner"; | ||||
|     case META_CURSOR_NW_RESIZE: | ||||
|       return "top_left_corner"; | ||||
|     case META_CURSOR_MOVE_OR_RESIZE_WINDOW: | ||||
|       return "fleur"; | ||||
|     case META_CURSOR_BUSY: | ||||
|       return "watch"; | ||||
|     case META_CURSOR_DND_IN_DRAG: | ||||
|       return "dnd-none"; | ||||
|     case META_CURSOR_DND_MOVE: | ||||
|       return "dnd-move"; | ||||
|     case META_CURSOR_DND_COPY: | ||||
|       return "dnd-copy"; | ||||
|     case META_CURSOR_DND_UNSUPPORTED_TARGET: | ||||
|       return "dnd-none"; | ||||
|     case META_CURSOR_POINTING_HAND: | ||||
|       return "hand2"; | ||||
|     case META_CURSOR_CROSSHAIR: | ||||
|       return "crosshair"; | ||||
|     case META_CURSOR_IBEAM: | ||||
|       return "xterm"; | ||||
|     default: | ||||
|       break; | ||||
|     } | ||||
|  | ||||
|   g_assert_not_reached (); | ||||
| } | ||||
|  | ||||
| Cursor | ||||
| meta_cursor_create_x_cursor (Display    *xdisplay, | ||||
|                              MetaCursor  cursor) | ||||
| { | ||||
|   return XcursorLibraryLoadCursor (xdisplay, translate_meta_cursor (cursor)); | ||||
| } | ||||
|  | ||||
| static XcursorImage * | ||||
| load_cursor_on_client (MetaCursor cursor) | ||||
| { | ||||
|   return XcursorLibraryLoadImage (translate_meta_cursor (cursor), | ||||
|                                   meta_prefs_get_cursor_theme (), | ||||
|                                   meta_prefs_get_cursor_size ()); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_cursor_image_load_gbm_buffer (struct gbm_device *gbm, | ||||
|                                    MetaCursorImage   *image, | ||||
|                                    uint8_t           *pixels, | ||||
|                                    int                width, | ||||
|                                    int                height, | ||||
|                                    int                rowstride, | ||||
|                                    uint32_t           gbm_format) | ||||
| { | ||||
|   if (width > 64 || height > 64) | ||||
|     { | ||||
|       meta_warning ("Invalid theme cursor size (must be at most 64x64)\n"); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   if (gbm_device_is_format_supported (gbm, gbm_format, | ||||
|                                       GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE)) | ||||
|     { | ||||
|       uint8_t buf[4 * 64 * 64]; | ||||
|       int i; | ||||
|  | ||||
|       image->bo = gbm_bo_create (gbm, 64, 64, | ||||
|                                  gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE); | ||||
|  | ||||
|       memset (buf, 0, sizeof(buf)); | ||||
|       for (i = 0; i < height; i++) | ||||
|         memcpy (buf + i * 4 * 64, pixels + i * rowstride, width * 4); | ||||
|  | ||||
|       gbm_bo_write (image->bo, buf, 64 * 64 * 4); | ||||
|     } | ||||
|   else | ||||
|     meta_warning ("HW cursor for format %d not supported\n", gbm_format); | ||||
| } | ||||
|  | ||||
| static struct gbm_device * | ||||
| get_gbm_device (void) | ||||
| { | ||||
| #ifdef HAVE_NATIVE_BACKEND | ||||
|   MetaBackend *meta_backend = meta_get_backend (); | ||||
|   MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend); | ||||
|  | ||||
|   if (META_IS_CURSOR_RENDERER_NATIVE (renderer)) | ||||
|     return meta_cursor_renderer_native_get_gbm_device (META_CURSOR_RENDERER_NATIVE (renderer)); | ||||
| #endif | ||||
|  | ||||
|   return NULL; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_cursor_image_load_from_xcursor_image (MetaCursorImage   *image, | ||||
|                                            XcursorImage      *xc_image) | ||||
| { | ||||
|   int width, height, rowstride; | ||||
|   CoglPixelFormat cogl_format; | ||||
|   uint32_t gbm_format; | ||||
|   ClutterBackend *clutter_backend; | ||||
|   CoglContext *cogl_context; | ||||
|   struct gbm_device *gbm; | ||||
|  | ||||
|   width           = xc_image->width; | ||||
|   height          = xc_image->height; | ||||
|   rowstride       = width * 4; | ||||
|  | ||||
|   gbm_format = GBM_FORMAT_ARGB8888; | ||||
| #if G_BYTE_ORDER == G_LITTLE_ENDIAN | ||||
|   cogl_format = COGL_PIXEL_FORMAT_BGRA_8888; | ||||
| #else | ||||
|   cogl_format = COGL_PIXEL_FORMAT_ARGB_8888; | ||||
| #endif | ||||
|  | ||||
|   image->hot_x = xc_image->xhot; | ||||
|   image->hot_y = xc_image->yhot; | ||||
|  | ||||
|   clutter_backend = clutter_get_default_backend (); | ||||
|   cogl_context = clutter_backend_get_cogl_context (clutter_backend); | ||||
|   image->texture = cogl_texture_2d_new_from_data (cogl_context, | ||||
|                                                   width, height, | ||||
|                                                   cogl_format, | ||||
|                                                   rowstride, | ||||
|                                                   (uint8_t *) xc_image->pixels, | ||||
|                                                   NULL); | ||||
|  | ||||
|   gbm = get_gbm_device (); | ||||
|   if (gbm) | ||||
|     meta_cursor_image_load_gbm_buffer (gbm, | ||||
|                                        image, | ||||
|                                        (uint8_t *) xc_image->pixels, | ||||
|                                        width, height, rowstride, | ||||
|                                        gbm_format); | ||||
| } | ||||
|  | ||||
| MetaCursorReference * | ||||
| meta_cursor_reference_from_theme (MetaCursor cursor) | ||||
| { | ||||
|   MetaCursorReference *self; | ||||
|   XcursorImage *image; | ||||
|  | ||||
|   image = load_cursor_on_client (cursor); | ||||
|   if (!image) | ||||
|     return NULL; | ||||
|  | ||||
|   self = g_slice_new0 (MetaCursorReference); | ||||
|   self->ref_count = 1; | ||||
|   self->cursor = cursor; | ||||
|   meta_cursor_image_load_from_xcursor_image (&self->image, image); | ||||
|  | ||||
|   XcursorImageDestroy (image); | ||||
|   return self; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_cursor_image_load_from_buffer (MetaCursorImage    *image, | ||||
|                                     struct wl_resource *buffer, | ||||
|                                     int                 hot_x, | ||||
|                                     int                 hot_y) | ||||
| { | ||||
|   struct gbm_device *gbm = get_gbm_device (); | ||||
|  | ||||
|   ClutterBackend *backend; | ||||
|   CoglContext *cogl_context; | ||||
|   struct wl_shm_buffer *shm_buffer; | ||||
|   uint32_t gbm_format; | ||||
|   int width, height; | ||||
|  | ||||
|   image->hot_x = hot_x; | ||||
|   image->hot_y = hot_y; | ||||
|  | ||||
|   backend = clutter_get_default_backend (); | ||||
|   cogl_context = clutter_backend_get_cogl_context (backend); | ||||
|  | ||||
|   image->texture = cogl_wayland_texture_2d_new_from_buffer (cogl_context, buffer, NULL); | ||||
|  | ||||
|   width = cogl_texture_get_width (COGL_TEXTURE (image->texture)); | ||||
|   height = cogl_texture_get_height (COGL_TEXTURE (image->texture)); | ||||
|  | ||||
|   shm_buffer = wl_shm_buffer_get (buffer); | ||||
|   if (shm_buffer) | ||||
|     { | ||||
|       if (gbm) | ||||
|         { | ||||
|           int rowstride = wl_shm_buffer_get_stride (shm_buffer); | ||||
|  | ||||
|           switch (wl_shm_buffer_get_format (shm_buffer)) | ||||
|             { | ||||
| #if G_BYTE_ORDER == G_BIG_ENDIAN | ||||
|             case WL_SHM_FORMAT_ARGB8888: | ||||
|               gbm_format = GBM_FORMAT_ARGB8888; | ||||
|               break; | ||||
|             case WL_SHM_FORMAT_XRGB8888: | ||||
|               gbm_format = GBM_FORMAT_XRGB8888; | ||||
|               break; | ||||
| #else | ||||
|             case WL_SHM_FORMAT_ARGB8888: | ||||
|               gbm_format = GBM_FORMAT_ARGB8888; | ||||
|               break; | ||||
|             case WL_SHM_FORMAT_XRGB8888: | ||||
|               gbm_format = GBM_FORMAT_XRGB8888; | ||||
|               break; | ||||
| #endif | ||||
|             default: | ||||
|               g_warn_if_reached (); | ||||
|               gbm_format = GBM_FORMAT_ARGB8888; | ||||
|             } | ||||
|  | ||||
|           meta_cursor_image_load_gbm_buffer (gbm, | ||||
|                                              image, | ||||
|                                              (uint8_t *) wl_shm_buffer_get_data (shm_buffer), | ||||
|                                              width, height, rowstride, | ||||
|                                              gbm_format); | ||||
|         } | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       /* HW cursors must be 64x64, but 64x64 is huge, and no cursor theme actually uses | ||||
|          that, so themed cursors must be padded with transparent pixels to fill the | ||||
|          overlay. This is trivial if we have CPU access to the data, but it's not | ||||
|          possible if the buffer is in GPU memory (and possibly tiled too), so if we | ||||
|          don't get the right size, we fallback to GL. | ||||
|       */ | ||||
|       if (width != 64 || height != 64) | ||||
|         { | ||||
|           meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n"); | ||||
|           return; | ||||
|         } | ||||
|  | ||||
|       if (gbm) | ||||
|         { | ||||
|           image->bo = gbm_bo_import (gbm, GBM_BO_IMPORT_WL_BUFFER, | ||||
|                                      buffer, GBM_BO_USE_CURSOR_64X64); | ||||
|           if (!image->bo) | ||||
|             meta_warning ("Importing HW cursor from wl_buffer failed\n"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| MetaCursorReference * | ||||
| meta_cursor_reference_from_buffer (struct wl_resource *buffer, | ||||
|                                    int                 hot_x, | ||||
|                                    int                 hot_y) | ||||
| { | ||||
|   MetaCursorReference *self; | ||||
|  | ||||
|   self = g_slice_new0 (MetaCursorReference); | ||||
|   self->ref_count = 1; | ||||
|   meta_cursor_image_load_from_buffer (&self->image, buffer, hot_x, hot_y); | ||||
|  | ||||
|   return self; | ||||
| } | ||||
|  | ||||
| CoglTexture * | ||||
| meta_cursor_reference_get_cogl_texture (MetaCursorReference *cursor, | ||||
|                                         int                 *hot_x, | ||||
|                                         int                 *hot_y) | ||||
| { | ||||
|   if (hot_x) | ||||
|     *hot_x = cursor->image.hot_x; | ||||
|   if (hot_y) | ||||
|     *hot_y = cursor->image.hot_y; | ||||
|   return COGL_TEXTURE (cursor->image.texture); | ||||
| } | ||||
|  | ||||
| struct gbm_bo * | ||||
| meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor, | ||||
|                                   int                 *hot_x, | ||||
|                                   int                 *hot_y) | ||||
| { | ||||
|   if (hot_x) | ||||
|     *hot_x = cursor->image.hot_x; | ||||
|   if (hot_y) | ||||
|     *hot_y = cursor->image.hot_y; | ||||
|   return cursor->image.bo; | ||||
| } | ||||
|  | ||||
| MetaCursor | ||||
| meta_cursor_reference_get_meta_cursor (MetaCursorReference *cursor) | ||||
| { | ||||
|   return cursor->cursor; | ||||
| } | ||||
| @@ -1,44 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright 2013 Red Hat, Inc. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * Author: Giovanni Campagna <gcampagn@redhat.com> | ||||
|  */ | ||||
|  | ||||
| #ifndef META_CURSOR_H | ||||
| #define META_CURSOR_H | ||||
|  | ||||
| typedef struct _MetaCursorReference MetaCursorReference; | ||||
|  | ||||
| MetaCursorReference * meta_cursor_reference_ref (MetaCursorReference *cursor); | ||||
| void meta_cursor_reference_unref (MetaCursorReference *cursor); | ||||
|  | ||||
| #include <meta/common.h> | ||||
| #include <wayland-server.h> | ||||
|  | ||||
| MetaCursorReference * meta_cursor_reference_from_theme  (MetaCursor          cursor); | ||||
|  | ||||
| MetaCursorReference * meta_cursor_reference_from_buffer (struct wl_resource *buffer, | ||||
|                                                          int                 hot_x, | ||||
|                                                          int                 hot_y); | ||||
|  | ||||
| MetaCursor meta_cursor_reference_get_meta_cursor (MetaCursorReference *cursor); | ||||
|  | ||||
| Cursor meta_cursor_create_x_cursor (Display    *xdisplay, | ||||
|                                     MetaCursor  cursor); | ||||
|  | ||||
| #endif /* META_CURSOR_H */ | ||||
| @@ -1,289 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright 2013 Red Hat, Inc. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * Adapted from gnome-session/gnome-session/gs-idle-monitor.c and | ||||
|  *         from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include "meta-idle-monitor-dbus.h" | ||||
| #include <meta/meta-idle-monitor.h> | ||||
| #include "meta-dbus-idle-monitor.h" | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
| #include <meta/util.h> | ||||
| #include <meta/main.h> /* for meta_get_replace_current_wm () */ | ||||
|  | ||||
| static gboolean | ||||
| handle_get_idletime (MetaDBusIdleMonitor   *skeleton, | ||||
|                      GDBusMethodInvocation *invocation, | ||||
|                      MetaIdleMonitor       *monitor) | ||||
| { | ||||
|   guint64 idletime; | ||||
|  | ||||
|   idletime = meta_idle_monitor_get_idletime (monitor); | ||||
|   meta_dbus_idle_monitor_complete_get_idletime (skeleton, invocation, idletime); | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| typedef struct { | ||||
|   MetaDBusIdleMonitor *dbus_monitor; | ||||
|   MetaIdleMonitor *monitor; | ||||
|   char *dbus_name; | ||||
|   guint watch_id; | ||||
|   guint name_watcher_id; | ||||
| } DBusWatch; | ||||
|  | ||||
| static void | ||||
| destroy_dbus_watch (gpointer data) | ||||
| { | ||||
|   DBusWatch *watch = data; | ||||
|  | ||||
|   g_object_unref (watch->dbus_monitor); | ||||
|   g_object_unref (watch->monitor); | ||||
|   g_free (watch->dbus_name); | ||||
|   g_bus_unwatch_name (watch->name_watcher_id); | ||||
|  | ||||
|   g_slice_free (DBusWatch, watch); | ||||
| } | ||||
|  | ||||
| static void | ||||
| dbus_idle_callback (MetaIdleMonitor *monitor, | ||||
|                     guint            watch_id, | ||||
|                     gpointer         user_data) | ||||
| { | ||||
|   DBusWatch *watch = user_data; | ||||
|   GDBusInterfaceSkeleton *skeleton = G_DBUS_INTERFACE_SKELETON (watch->dbus_monitor); | ||||
|  | ||||
|   g_dbus_connection_emit_signal (g_dbus_interface_skeleton_get_connection (skeleton), | ||||
|                                  watch->dbus_name, | ||||
|                                  g_dbus_interface_skeleton_get_object_path (skeleton), | ||||
|                                  "org.gnome.Mutter.IdleMonitor", | ||||
|                                  "WatchFired", | ||||
|                                  g_variant_new ("(u)", watch_id), | ||||
|                                  NULL); | ||||
| } | ||||
|  | ||||
| static void | ||||
| name_vanished_callback (GDBusConnection *connection, | ||||
|                         const char      *name, | ||||
|                         gpointer         user_data) | ||||
| { | ||||
|   DBusWatch *watch = user_data; | ||||
|  | ||||
|   meta_idle_monitor_remove_watch (watch->monitor, watch->watch_id); | ||||
| } | ||||
|  | ||||
| static DBusWatch * | ||||
| make_dbus_watch (MetaDBusIdleMonitor   *skeleton, | ||||
|                  GDBusMethodInvocation *invocation, | ||||
|                  MetaIdleMonitor       *monitor) | ||||
| { | ||||
|   DBusWatch *watch; | ||||
|  | ||||
|   watch = g_slice_new (DBusWatch); | ||||
|   watch->dbus_monitor = g_object_ref (skeleton); | ||||
|   watch->monitor = g_object_ref (monitor); | ||||
|   watch->dbus_name = g_strdup (g_dbus_method_invocation_get_sender (invocation)); | ||||
|   watch->name_watcher_id = g_bus_watch_name_on_connection (g_dbus_method_invocation_get_connection (invocation), | ||||
|                                                            watch->dbus_name, | ||||
|                                                            G_BUS_NAME_WATCHER_FLAGS_NONE, | ||||
|                                                            NULL, /* appeared */ | ||||
|                                                            name_vanished_callback, | ||||
|                                                            watch, NULL); | ||||
|  | ||||
|   return watch; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| handle_add_idle_watch (MetaDBusIdleMonitor   *skeleton, | ||||
|                        GDBusMethodInvocation *invocation, | ||||
|                        guint64                interval, | ||||
|                        MetaIdleMonitor       *monitor) | ||||
| { | ||||
|   DBusWatch *watch; | ||||
|  | ||||
|   watch = make_dbus_watch (skeleton, invocation, monitor); | ||||
|   watch->watch_id = meta_idle_monitor_add_idle_watch (monitor, interval, | ||||
|                                                       dbus_idle_callback, watch, destroy_dbus_watch); | ||||
|  | ||||
|   meta_dbus_idle_monitor_complete_add_idle_watch (skeleton, invocation, watch->watch_id); | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| handle_add_user_active_watch (MetaDBusIdleMonitor   *skeleton, | ||||
|                               GDBusMethodInvocation *invocation, | ||||
|                               MetaIdleMonitor       *monitor) | ||||
| { | ||||
|   DBusWatch *watch; | ||||
|  | ||||
|   watch = make_dbus_watch (skeleton, invocation, monitor); | ||||
|   watch->watch_id = meta_idle_monitor_add_user_active_watch (monitor, | ||||
|                                                              dbus_idle_callback, watch, | ||||
|                                                              destroy_dbus_watch); | ||||
|  | ||||
|   meta_dbus_idle_monitor_complete_add_user_active_watch (skeleton, invocation, watch->watch_id); | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| handle_remove_watch (MetaDBusIdleMonitor   *skeleton, | ||||
|                      GDBusMethodInvocation *invocation, | ||||
|                      guint                  id, | ||||
|                      MetaIdleMonitor       *monitor) | ||||
| { | ||||
|   meta_idle_monitor_remove_watch (monitor, id); | ||||
|   meta_dbus_idle_monitor_complete_remove_watch (skeleton, invocation); | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| create_monitor_skeleton (GDBusObjectManagerServer *manager, | ||||
|                          MetaIdleMonitor          *monitor, | ||||
|                          const char               *path) | ||||
| { | ||||
|   MetaDBusIdleMonitor *skeleton; | ||||
|   MetaDBusObjectSkeleton *object; | ||||
|  | ||||
|   skeleton = meta_dbus_idle_monitor_skeleton_new (); | ||||
|   g_signal_connect_object (skeleton, "handle-add-idle-watch", | ||||
|                            G_CALLBACK (handle_add_idle_watch), monitor, 0); | ||||
|   g_signal_connect_object (skeleton, "handle-add-user-active-watch", | ||||
|                            G_CALLBACK (handle_add_user_active_watch), monitor, 0); | ||||
|   g_signal_connect_object (skeleton, "handle-remove-watch", | ||||
|                            G_CALLBACK (handle_remove_watch), monitor, 0); | ||||
|   g_signal_connect_object (skeleton, "handle-get-idletime", | ||||
|                            G_CALLBACK (handle_get_idletime), monitor, 0); | ||||
|  | ||||
|   object = meta_dbus_object_skeleton_new (path); | ||||
|   meta_dbus_object_skeleton_set_idle_monitor (object, skeleton); | ||||
|  | ||||
|   g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (object)); | ||||
|  | ||||
|   g_object_unref (skeleton); | ||||
|   g_object_unref (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_device_added (ClutterDeviceManager     *device_manager, | ||||
|                  ClutterInputDevice       *device, | ||||
|                  GDBusObjectManagerServer *manager) | ||||
| { | ||||
|  | ||||
|   MetaIdleMonitor *monitor; | ||||
|   int device_id; | ||||
|   char *path; | ||||
|  | ||||
|   device_id = clutter_input_device_get_device_id (device); | ||||
|   monitor = meta_idle_monitor_get_for_device (device_id); | ||||
|   path = g_strdup_printf ("/org/gnome/Mutter/IdleMonitor/Device%d", device_id); | ||||
|  | ||||
|   create_monitor_skeleton (manager, monitor, path); | ||||
|   g_free (path); | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_device_removed (ClutterDeviceManager     *device_manager, | ||||
|                    ClutterInputDevice       *device, | ||||
|                    GDBusObjectManagerServer *manager) | ||||
| { | ||||
|   int device_id; | ||||
|   char *path; | ||||
|  | ||||
|   device_id = clutter_input_device_get_device_id (device); | ||||
|   path = g_strdup_printf ("/org/gnome/Mutter/IdleMonitor/Device%d", device_id); | ||||
|   g_dbus_object_manager_server_unexport (manager, path); | ||||
|   g_free (path); | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_bus_acquired (GDBusConnection *connection, | ||||
|                  const char      *name, | ||||
|                  gpointer         user_data) | ||||
| { | ||||
|   GDBusObjectManagerServer *manager; | ||||
|   ClutterDeviceManager *device_manager; | ||||
|   MetaIdleMonitor *monitor; | ||||
|   GSList *devices, *iter; | ||||
|   char *path; | ||||
|  | ||||
|   manager = g_dbus_object_manager_server_new ("/org/gnome/Mutter/IdleMonitor"); | ||||
|  | ||||
|   /* We never clear the core monitor, as that's supposed to cumulate idle times from | ||||
|      all devices */ | ||||
|   monitor = meta_idle_monitor_get_core (); | ||||
|   path = g_strdup ("/org/gnome/Mutter/IdleMonitor/Core"); | ||||
|   create_monitor_skeleton (manager, monitor, path); | ||||
|   g_free (path); | ||||
|  | ||||
|   device_manager = clutter_device_manager_get_default (); | ||||
|   devices = clutter_device_manager_list_devices (device_manager); | ||||
|  | ||||
|   for (iter = devices; iter; iter = iter->next) | ||||
|     on_device_added (device_manager, iter->data, manager); | ||||
|  | ||||
|   g_slist_free (devices); | ||||
|  | ||||
|   g_signal_connect_object (device_manager, "device-added", | ||||
|                            G_CALLBACK (on_device_added), manager, 0); | ||||
|   g_signal_connect_object (device_manager, "device-removed", | ||||
|                            G_CALLBACK (on_device_removed), manager, 0); | ||||
|  | ||||
|   g_dbus_object_manager_server_set_connection (manager, connection); | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_name_acquired (GDBusConnection *connection, | ||||
|                   const char      *name, | ||||
|                   gpointer         user_data) | ||||
| { | ||||
|   meta_verbose ("Acquired name %s\n", name); | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_name_lost (GDBusConnection *connection, | ||||
|               const char      *name, | ||||
|               gpointer         user_data) | ||||
| { | ||||
|   meta_verbose ("Lost or failed to acquire name %s\n", name); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_idle_monitor_init_dbus (void) | ||||
| { | ||||
|   static int dbus_name_id; | ||||
|  | ||||
|   if (dbus_name_id > 0) | ||||
|     return; | ||||
|  | ||||
|   dbus_name_id = g_bus_own_name (G_BUS_TYPE_SESSION, | ||||
|                                  "org.gnome.Mutter.IdleMonitor", | ||||
|                                  G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | | ||||
|                                  (meta_get_replace_current_wm () ? | ||||
|                                   G_BUS_NAME_OWNER_FLAGS_REPLACE : 0), | ||||
|                                  on_bus_acquired, | ||||
|                                  on_name_acquired, | ||||
|                                  on_name_lost, | ||||
|                                  NULL, NULL); | ||||
| } | ||||
| @@ -1,65 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright 2013 Red Hat, Inc. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * Adapted from gnome-session/gnome-session/gs-idle-monitor.c and | ||||
|  *         from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c | ||||
|  */ | ||||
|  | ||||
| #ifndef META_IDLE_MONITOR_PRIVATE_H | ||||
| #define META_IDLE_MONITOR_PRIVATE_H | ||||
|  | ||||
| #include <meta/meta-idle-monitor.h> | ||||
| #include "display-private.h" | ||||
|  | ||||
| #include <X11/Xlib.h> | ||||
| #include <X11/extensions/sync.h> | ||||
|  | ||||
| typedef struct | ||||
| { | ||||
|   MetaIdleMonitor          *monitor; | ||||
|   guint	                    id; | ||||
|   MetaIdleMonitorWatchFunc  callback; | ||||
|   gpointer		    user_data; | ||||
|   GDestroyNotify            notify; | ||||
|   guint64                   timeout_msec; | ||||
|   int                       idle_source_id; | ||||
| } MetaIdleMonitorWatch; | ||||
|  | ||||
| struct _MetaIdleMonitor | ||||
| { | ||||
|   GObject parent_instance; | ||||
|  | ||||
|   GHashTable *watches; | ||||
|   int device_id; | ||||
| }; | ||||
|  | ||||
| struct _MetaIdleMonitorClass | ||||
| { | ||||
|   GObjectClass parent_class; | ||||
|  | ||||
|   gint64 (*get_idletime) (MetaIdleMonitor *monitor); | ||||
|   MetaIdleMonitorWatch * (*make_watch) (MetaIdleMonitor           *monitor, | ||||
|                                         guint64                    timeout_msec, | ||||
|                                         MetaIdleMonitorWatchFunc   callback, | ||||
|                                         gpointer                   user_data, | ||||
|                                         GDestroyNotify             notify); | ||||
| }; | ||||
|  | ||||
| void _meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch); | ||||
|  | ||||
| #endif /* META_IDLE_MONITOR_PRIVATE_H */ | ||||
| @@ -1,318 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright 2013 Red Hat, Inc. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * Adapted from gnome-session/gnome-session/gs-idle-monitor.c and | ||||
|  *         from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * SECTION:idle-monitor | ||||
|  * @title: MetaIdleMonitor | ||||
|  * @short_description: Mutter idle counter (similar to X's IDLETIME) | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include <string.h> | ||||
| #include <clutter/clutter.h> | ||||
| #include <X11/Xlib.h> | ||||
| #include <X11/extensions/sync.h> | ||||
|  | ||||
| #include <meta/util.h> | ||||
| #include <meta/main.h> | ||||
| #include <meta/meta-idle-monitor.h> | ||||
| #include "meta-idle-monitor-private.h" | ||||
| #include "meta-idle-monitor-dbus.h" | ||||
| #include "meta-backend.h" | ||||
|  | ||||
| G_STATIC_ASSERT(sizeof(unsigned long) == sizeof(gpointer)); | ||||
|  | ||||
| enum | ||||
| { | ||||
|   PROP_0, | ||||
|   PROP_DEVICE_ID, | ||||
|   PROP_LAST, | ||||
| }; | ||||
|  | ||||
| static GParamSpec *obj_props[PROP_LAST]; | ||||
|  | ||||
| G_DEFINE_TYPE (MetaIdleMonitor, meta_idle_monitor, G_TYPE_OBJECT) | ||||
|  | ||||
| void | ||||
| _meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch) | ||||
| { | ||||
|   MetaIdleMonitor *monitor; | ||||
|   guint id; | ||||
|   gboolean is_user_active_watch; | ||||
|  | ||||
|   monitor = watch->monitor; | ||||
|   g_object_ref (monitor); | ||||
|  | ||||
|   if (watch->idle_source_id) | ||||
|     { | ||||
|       g_source_remove (watch->idle_source_id); | ||||
|       watch->idle_source_id = 0; | ||||
|     } | ||||
|  | ||||
|   id = watch->id; | ||||
|   is_user_active_watch = (watch->timeout_msec == 0); | ||||
|  | ||||
|   if (watch->callback) | ||||
|     watch->callback (monitor, id, watch->user_data); | ||||
|  | ||||
|   if (is_user_active_watch) | ||||
|     meta_idle_monitor_remove_watch (monitor, id); | ||||
|  | ||||
|   g_object_unref (monitor); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_idle_monitor_dispose (GObject *object) | ||||
| { | ||||
|   MetaIdleMonitor *monitor = META_IDLE_MONITOR (object); | ||||
|  | ||||
|   g_clear_pointer (&monitor->watches, g_hash_table_destroy); | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_idle_monitor_parent_class)->dispose (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_idle_monitor_get_property (GObject    *object, | ||||
|                                 guint       prop_id, | ||||
|                                 GValue     *value, | ||||
|                                 GParamSpec *pspec) | ||||
| { | ||||
|   MetaIdleMonitor *monitor = META_IDLE_MONITOR (object); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_DEVICE_ID: | ||||
|       g_value_set_int (value, monitor->device_id); | ||||
|       break; | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_idle_monitor_set_property (GObject      *object, | ||||
|                                 guint         prop_id, | ||||
|                                 const GValue *value, | ||||
|                                 GParamSpec   *pspec) | ||||
| { | ||||
|   MetaIdleMonitor *monitor = META_IDLE_MONITOR (object); | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_DEVICE_ID: | ||||
|       monitor->device_id = g_value_get_int (value); | ||||
|       break; | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_idle_monitor_class_init (MetaIdleMonitorClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|  | ||||
|   object_class->dispose = meta_idle_monitor_dispose; | ||||
|   object_class->get_property = meta_idle_monitor_get_property; | ||||
|   object_class->set_property = meta_idle_monitor_set_property; | ||||
|  | ||||
|   /** | ||||
|    * MetaIdleMonitor:device_id: | ||||
|    * | ||||
|    * The device to listen to idletime on. | ||||
|    */ | ||||
|   obj_props[PROP_DEVICE_ID] = | ||||
|     g_param_spec_int ("device-id", | ||||
|                       "Device ID", | ||||
|                       "The device to listen to idletime on", | ||||
|                       0, 255, 0, | ||||
|                       G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); | ||||
|   g_object_class_install_property (object_class, PROP_DEVICE_ID, obj_props[PROP_DEVICE_ID]); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_idle_monitor_init (MetaIdleMonitor *monitor) | ||||
| { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_idle_monitor_get_core: | ||||
|  * | ||||
|  * Returns: (transfer none): the #MetaIdleMonitor that tracks the server-global | ||||
|  * idletime for all devices. To track device-specific idletime, | ||||
|  * use meta_idle_monitor_get_for_device(). | ||||
|  */ | ||||
| MetaIdleMonitor * | ||||
| meta_idle_monitor_get_core (void) | ||||
| { | ||||
|   MetaBackend *backend = meta_get_backend (); | ||||
|   return meta_backend_get_idle_monitor (backend, 0); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_idle_monitor_get_for_device: | ||||
|  * @device_id: the device to get the idle time for. | ||||
|  * | ||||
|  * Returns: (transfer none): a new #MetaIdleMonitor that tracks the | ||||
|  * device-specific idletime for @device. To track server-global idletime | ||||
|  * for all devices, use meta_idle_monitor_get_core(). | ||||
|  */ | ||||
| MetaIdleMonitor * | ||||
| meta_idle_monitor_get_for_device (int device_id) | ||||
| { | ||||
|   MetaBackend *backend = meta_get_backend (); | ||||
|   return meta_backend_get_idle_monitor (backend, device_id); | ||||
| } | ||||
|  | ||||
| static MetaIdleMonitorWatch * | ||||
| make_watch (MetaIdleMonitor           *monitor, | ||||
|             guint64                    timeout_msec, | ||||
|             MetaIdleMonitorWatchFunc   callback, | ||||
|             gpointer                   user_data, | ||||
|             GDestroyNotify             notify) | ||||
| { | ||||
|   MetaIdleMonitorWatch *watch; | ||||
|  | ||||
|   watch = META_IDLE_MONITOR_GET_CLASS (monitor)->make_watch (monitor, | ||||
|                                                              timeout_msec, | ||||
|                                                              callback, | ||||
|                                                              user_data, | ||||
|                                                              notify); | ||||
|  | ||||
|   g_hash_table_insert (monitor->watches, | ||||
|                        GUINT_TO_POINTER (watch->id), | ||||
|                        watch); | ||||
|   return watch; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_idle_monitor_add_idle_watch: | ||||
|  * @monitor: A #MetaIdleMonitor | ||||
|  * @interval_msec: The idletime interval, in milliseconds | ||||
|  * @callback: (nullable): The callback to call when the user has | ||||
|  *     accumulated @interval_msec milliseconds of idle time. | ||||
|  * @user_data: (nullable): The user data to pass to the callback | ||||
|  * @notify: A #GDestroyNotify | ||||
|  * | ||||
|  * Returns: a watch id | ||||
|  * | ||||
|  * Adds a watch for a specific idle time. The callback will be called | ||||
|  * when the user has accumulated @interval_msec milliseconds of idle time. | ||||
|  * This function will return an ID that can either be passed to | ||||
|  * meta_idle_monitor_remove_watch(), or can be used to tell idle time | ||||
|  * watches apart if you have more than one. | ||||
|  * | ||||
|  * Also note that this function will only care about positive transitions | ||||
|  * (user's idle time exceeding a certain time). If you want to know about | ||||
|  * when the user has become active, use | ||||
|  * meta_idle_monitor_add_user_active_watch(). | ||||
|  */ | ||||
| guint | ||||
| meta_idle_monitor_add_idle_watch (MetaIdleMonitor	       *monitor, | ||||
|                                   guint64	                interval_msec, | ||||
|                                   MetaIdleMonitorWatchFunc      callback, | ||||
|                                   gpointer			user_data, | ||||
|                                   GDestroyNotify		notify) | ||||
| { | ||||
|   MetaIdleMonitorWatch *watch; | ||||
|  | ||||
|   g_return_val_if_fail (META_IS_IDLE_MONITOR (monitor), 0); | ||||
|   g_return_val_if_fail (interval_msec > 0, 0); | ||||
|  | ||||
|   watch = make_watch (monitor, | ||||
|                       interval_msec, | ||||
|                       callback, | ||||
|                       user_data, | ||||
|                       notify); | ||||
|  | ||||
|   return watch->id; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_idle_monitor_add_user_active_watch: | ||||
|  * @monitor: A #MetaIdleMonitor | ||||
|  * @callback: (nullable): The callback to call when the user is | ||||
|  *     active again. | ||||
|  * @user_data: (nullable): The user data to pass to the callback | ||||
|  * @notify: A #GDestroyNotify | ||||
|  * | ||||
|  * Returns: a watch id | ||||
|  * | ||||
|  * Add a one-time watch to know when the user is active again. | ||||
|  * Note that this watch is one-time and will de-activate after the | ||||
|  * function is called, for efficiency purposes. It's most convenient | ||||
|  * to call this when an idle watch, as added by | ||||
|  * meta_idle_monitor_add_idle_watch(), has triggered. | ||||
|  */ | ||||
| guint | ||||
| meta_idle_monitor_add_user_active_watch (MetaIdleMonitor          *monitor, | ||||
|                                          MetaIdleMonitorWatchFunc  callback, | ||||
|                                          gpointer		   user_data, | ||||
|                                          GDestroyNotify	           notify) | ||||
| { | ||||
|   MetaIdleMonitorWatch *watch; | ||||
|  | ||||
|   g_return_val_if_fail (META_IS_IDLE_MONITOR (monitor), 0); | ||||
|  | ||||
|   watch = make_watch (monitor, | ||||
|                       0, | ||||
|                       callback, | ||||
|                       user_data, | ||||
|                       notify); | ||||
|  | ||||
|   return watch->id; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_idle_monitor_remove_watch: | ||||
|  * @monitor: A #MetaIdleMonitor | ||||
|  * @id: A watch ID | ||||
|  * | ||||
|  * Removes an idle time watcher, previously added by | ||||
|  * meta_idle_monitor_add_idle_watch() or | ||||
|  * meta_idle_monitor_add_user_active_watch(). | ||||
|  */ | ||||
| void | ||||
| meta_idle_monitor_remove_watch (MetaIdleMonitor *monitor, | ||||
|                                 guint	         id) | ||||
| { | ||||
|   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); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_idle_monitor_get_idletime: | ||||
|  * @monitor: A #MetaIdleMonitor | ||||
|  * | ||||
|  * Returns: The current idle time, in milliseconds, or -1 for not supported | ||||
|  */ | ||||
| gint64 | ||||
| meta_idle_monitor_get_idletime (MetaIdleMonitor *monitor) | ||||
| { | ||||
|   return META_IDLE_MONITOR_GET_CLASS (monitor)->get_idletime (monitor); | ||||
| } | ||||
| @@ -1,55 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2001 Havoc Pennington | ||||
|  * Copyright (C) 2003 Rob Adams | ||||
|  * Copyright (C) 2004-2006 Elijah Newren | ||||
|  * Copyright (C) 2013 Red Hat Inc. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef META_MONITOR_CONFIG_H | ||||
| #define META_MONITOR_CONFIG_H | ||||
|  | ||||
| #include "meta-monitor-manager.h" | ||||
|  | ||||
| #define META_TYPE_MONITOR_CONFIG            (meta_monitor_config_get_type ()) | ||||
| #define META_MONITOR_CONFIG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_CONFIG, MetaMonitorConfig)) | ||||
| #define META_MONITOR_CONFIG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_MONITOR_CONFIG, MetaMonitorConfigClass)) | ||||
| #define META_IS_MONITOR_CONFIG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_CONFIG)) | ||||
| #define META_IS_MONITOR_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_MONITOR_CONFIG)) | ||||
| #define META_MONITOR_CONFIG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_MONITOR_CONFIG, MetaMonitorConfigClass)) | ||||
|  | ||||
| GType meta_monitor_config_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| MetaMonitorConfig *meta_monitor_config_new (void); | ||||
|  | ||||
| gboolean           meta_monitor_config_match_current (MetaMonitorConfig  *config, | ||||
|                                                       MetaMonitorManager *manager); | ||||
|  | ||||
| gboolean           meta_monitor_config_apply_stored (MetaMonitorConfig  *config, | ||||
|                                                      MetaMonitorManager *manager); | ||||
|  | ||||
| void               meta_monitor_config_make_default (MetaMonitorConfig  *config, | ||||
|                                                      MetaMonitorManager *manager); | ||||
|  | ||||
| void               meta_monitor_config_update_current (MetaMonitorConfig  *config, | ||||
|                                                        MetaMonitorManager *manager); | ||||
| void               meta_monitor_config_make_persistent (MetaMonitorConfig *config); | ||||
|  | ||||
| void               meta_monitor_config_restore_previous (MetaMonitorConfig  *config, | ||||
|                                                          MetaMonitorManager *manager); | ||||
|  | ||||
| #endif /* META_MONITOR_CONFIG_H */ | ||||
| @@ -1,227 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2001, 2002 Havoc Pennington | ||||
|  * Copyright (C) 2002, 2003 Red Hat Inc. | ||||
|  * Some ICCCM manager selection code derived from fvwm2, | ||||
|  * Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team | ||||
|  * Copyright (C) 2003 Rob Adams | ||||
|  * Copyright (C) 2004-2006 Elijah Newren | ||||
|  * Copyright (C) 2013 Red Hat Inc. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include "meta-monitor-manager-dummy.h" | ||||
|  | ||||
| #define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1) | ||||
|  | ||||
| struct _MetaMonitorManagerDummy | ||||
| { | ||||
|   MetaMonitorManager parent_instance; | ||||
| }; | ||||
|  | ||||
| struct _MetaMonitorManagerDummyClass | ||||
| { | ||||
|   MetaMonitorManagerClass parent_class; | ||||
| }; | ||||
|  | ||||
| G_DEFINE_TYPE (MetaMonitorManagerDummy, meta_monitor_manager_dummy, META_TYPE_MONITOR_MANAGER); | ||||
|  | ||||
| static void | ||||
| meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager) | ||||
| { | ||||
|   manager->max_screen_width = 65535; | ||||
|   manager->max_screen_height = 65535; | ||||
|   manager->screen_width = 1024; | ||||
|   manager->screen_height = 768; | ||||
|  | ||||
|   manager->modes = g_new0 (MetaMonitorMode, 1); | ||||
|   manager->n_modes = 1; | ||||
|  | ||||
|   manager->modes[0].mode_id = 0; | ||||
|   manager->modes[0].width = 1024; | ||||
|   manager->modes[0].height = 768; | ||||
|   manager->modes[0].refresh_rate = 60.0; | ||||
|  | ||||
|   manager->crtcs = g_new0 (MetaCRTC, 1); | ||||
|   manager->n_crtcs = 1; | ||||
|  | ||||
|   manager->crtcs[0].crtc_id = 1; | ||||
|   manager->crtcs[0].rect.x = 0; | ||||
|   manager->crtcs[0].rect.y = 0; | ||||
|   manager->crtcs[0].rect.width = manager->modes[0].width; | ||||
|   manager->crtcs[0].rect.height = manager->modes[0].height; | ||||
|   manager->crtcs[0].current_mode = &manager->modes[0]; | ||||
|   manager->crtcs[0].transform = WL_OUTPUT_TRANSFORM_NORMAL; | ||||
|   manager->crtcs[0].all_transforms = ALL_WL_TRANSFORMS; | ||||
|   manager->crtcs[0].is_dirty = FALSE; | ||||
|   manager->crtcs[0].logical_monitor = NULL; | ||||
|  | ||||
|   manager->outputs = g_new0 (MetaOutput, 1); | ||||
|   manager->n_outputs = 1; | ||||
|  | ||||
|   manager->outputs[0].crtc = &manager->crtcs[0]; | ||||
|   manager->outputs[0].output_id = 1; | ||||
|   manager->outputs[0].name = g_strdup ("LVDS"); | ||||
|   manager->outputs[0].vendor = g_strdup ("MetaProducts Inc."); | ||||
|   manager->outputs[0].product = g_strdup ("unknown"); | ||||
|   manager->outputs[0].serial = g_strdup ("0xC0FFEE"); | ||||
|   manager->outputs[0].width_mm = 222; | ||||
|   manager->outputs[0].height_mm = 125; | ||||
|   manager->outputs[0].subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN; | ||||
|   manager->outputs[0].preferred_mode = &manager->modes[0]; | ||||
|   manager->outputs[0].n_modes = 1; | ||||
|   manager->outputs[0].modes = g_new0 (MetaMonitorMode *, 1); | ||||
|   manager->outputs[0].modes[0] = &manager->modes[0]; | ||||
|   manager->outputs[0].n_possible_crtcs = 1; | ||||
|   manager->outputs[0].possible_crtcs = g_new0 (MetaCRTC *, 1); | ||||
|   manager->outputs[0].possible_crtcs[0] = &manager->crtcs[0]; | ||||
|   manager->outputs[0].n_possible_clones = 0; | ||||
|   manager->outputs[0].possible_clones = g_new0 (MetaOutput *, 0); | ||||
|   manager->outputs[0].backlight = -1; | ||||
|   manager->outputs[0].backlight_min = 0; | ||||
|   manager->outputs[0].backlight_max = 0; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_monitor_manager_dummy_apply_config (MetaMonitorManager *manager, | ||||
|                                          MetaCRTCInfo       **crtcs, | ||||
|                                          unsigned int         n_crtcs, | ||||
|                                          MetaOutputInfo     **outputs, | ||||
|                                          unsigned int         n_outputs) | ||||
| { | ||||
|     unsigned i; | ||||
|     int screen_width = 0, screen_height = 0; | ||||
|  | ||||
|   for (i = 0; i < n_crtcs; i++) | ||||
|     { | ||||
|       MetaCRTCInfo *crtc_info = crtcs[i]; | ||||
|       MetaCRTC *crtc = crtc_info->crtc; | ||||
|       crtc->is_dirty = TRUE; | ||||
|  | ||||
|       if (crtc_info->mode == NULL) | ||||
|         { | ||||
|           crtc->rect.x = 0; | ||||
|           crtc->rect.y = 0; | ||||
|           crtc->rect.width = 0; | ||||
|           crtc->rect.height = 0; | ||||
|           crtc->current_mode = NULL; | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           MetaMonitorMode *mode; | ||||
|           MetaOutput *output; | ||||
|           int i, n_outputs; | ||||
|           int width, height; | ||||
|  | ||||
|           mode = crtc_info->mode; | ||||
|  | ||||
|           if (meta_monitor_transform_is_rotated (crtc_info->transform)) | ||||
|             { | ||||
|               width = mode->height; | ||||
|               height = mode->width; | ||||
|             } | ||||
|           else | ||||
|             { | ||||
|               width = mode->width; | ||||
|               height = mode->height; | ||||
|             } | ||||
|  | ||||
|           crtc->rect.x = crtc_info->x; | ||||
|           crtc->rect.y = crtc_info->y; | ||||
|           crtc->rect.width = width; | ||||
|           crtc->rect.height = height; | ||||
|           crtc->current_mode = mode; | ||||
|           crtc->transform = crtc_info->transform; | ||||
|  | ||||
|           screen_width = MAX (screen_width, crtc_info->x + width); | ||||
|           screen_height = MAX (screen_height, crtc_info->y + height); | ||||
|  | ||||
|           n_outputs = crtc_info->outputs->len; | ||||
|           for (i = 0; i < n_outputs; i++) | ||||
|             { | ||||
|               output = ((MetaOutput**)crtc_info->outputs->pdata)[i]; | ||||
|  | ||||
|               output->is_dirty = TRUE; | ||||
|               output->crtc = crtc; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   for (i = 0; i < n_outputs; i++) | ||||
|     { | ||||
|       MetaOutputInfo *output_info = outputs[i]; | ||||
|       MetaOutput *output = output_info->output; | ||||
|  | ||||
|       output->is_primary = output_info->is_primary; | ||||
|       output->is_presentation = output_info->is_presentation; | ||||
|     } | ||||
|  | ||||
|   /* Disable CRTCs not mentioned in the list */ | ||||
|   for (i = 0; i < manager->n_crtcs; i++) | ||||
|     { | ||||
|       MetaCRTC *crtc = &manager->crtcs[i]; | ||||
|  | ||||
|       crtc->logical_monitor = NULL; | ||||
|  | ||||
|       if (crtc->is_dirty) | ||||
|         { | ||||
|           crtc->is_dirty = FALSE; | ||||
|           continue; | ||||
|         } | ||||
|  | ||||
|       crtc->rect.x = 0; | ||||
|       crtc->rect.y = 0; | ||||
|       crtc->rect.width = 0; | ||||
|       crtc->rect.height = 0; | ||||
|       crtc->current_mode = NULL; | ||||
|     } | ||||
|  | ||||
|   /* Disable outputs not mentioned in the list */ | ||||
|   for (i = 0; i < manager->n_outputs; i++) | ||||
|     { | ||||
|       MetaOutput *output = &manager->outputs[i]; | ||||
|  | ||||
|       if (output->is_dirty) | ||||
|         { | ||||
|           output->is_dirty = FALSE; | ||||
|           continue; | ||||
|         } | ||||
|  | ||||
|       output->crtc = NULL; | ||||
|       output->is_primary = FALSE; | ||||
|     } | ||||
|  | ||||
|   manager->screen_width = screen_width; | ||||
|   manager->screen_height = screen_height; | ||||
|  | ||||
|   meta_monitor_manager_rebuild_derived (manager); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_monitor_manager_dummy_class_init (MetaMonitorManagerDummyClass *klass) | ||||
| { | ||||
|   MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass); | ||||
|  | ||||
|   manager_class->read_current = meta_monitor_manager_dummy_read_current; | ||||
|   manager_class->apply_configuration = meta_monitor_manager_dummy_apply_config; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_monitor_manager_dummy_init (MetaMonitorManagerDummy *manager) | ||||
| { | ||||
| } | ||||
| @@ -1,40 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2001 Havoc Pennington | ||||
|  * Copyright (C) 2003 Rob Adams | ||||
|  * Copyright (C) 2004-2006 Elijah Newren | ||||
|  * Copyright (C) 2013 Red Hat Inc. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef META_MONITOR_MANAGER_DUMMY_H | ||||
| #define META_MONITOR_MANAGER_DUMMY_H | ||||
|  | ||||
| #include "meta-monitor-manager.h" | ||||
|  | ||||
| #define META_TYPE_MONITOR_MANAGER_DUMMY            (meta_monitor_manager_dummy_get_type ()) | ||||
| #define META_MONITOR_MANAGER_DUMMY(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_DUMMY, MetaMonitorManagerDummy)) | ||||
| #define META_MONITOR_MANAGER_DUMMY_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_MONITOR_MANAGER_DUMMY, MetaMonitorManagerDummyClass)) | ||||
| #define META_IS_MONITOR_MANAGER_DUMMY(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_MANAGER_DUMMY)) | ||||
| #define META_IS_MONITOR_MANAGER_DUMMY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_MONITOR_MANAGER_DUMMY)) | ||||
| #define META_MONITOR_MANAGER_DUMMY_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_MONITOR_MANAGER_DUMMY, MetaMonitorManagerDummyClass)) | ||||
|  | ||||
| typedef struct _MetaMonitorManagerDummyClass    MetaMonitorManagerDummyClass; | ||||
| typedef struct _MetaMonitorManagerDummy         MetaMonitorManagerDummy; | ||||
|  | ||||
| GType meta_monitor_manager_dummy_get_type (void); | ||||
|  | ||||
| #endif /* META_MONITOR_MANAGER_DUMMY_H */ | ||||
| @@ -1,107 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2014 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Jasper St. Pierre <jstpierre@mecheye.net> | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include "dbus-utils.h" | ||||
|  | ||||
| #include <glib.h> | ||||
|  | ||||
| /* Stolen from tp_escape_as_identifier, from tp-glib, | ||||
|  * which follows the same escaping convention as systemd. | ||||
|  */ | ||||
| static inline gboolean | ||||
| _esc_ident_bad (gchar c, gboolean is_first) | ||||
| { | ||||
|   return ((c < 'a' || c > 'z') && | ||||
|           (c < 'A' || c > 'Z') && | ||||
|           (c < '0' || c > '9' || is_first)); | ||||
| } | ||||
|  | ||||
| static gchar * | ||||
| escape_dbus_component (const gchar *name) | ||||
| { | ||||
|   gboolean bad = FALSE; | ||||
|   size_t len = 0; | ||||
|   GString *op; | ||||
|   const gchar *ptr, *first_ok; | ||||
|  | ||||
|   g_return_val_if_fail (name != NULL, NULL); | ||||
|  | ||||
|   /* fast path for empty name */ | ||||
|   if (name[0] == '\0') | ||||
|     return g_strdup ("_"); | ||||
|  | ||||
|   for (ptr = name; *ptr; ptr++) | ||||
|     { | ||||
|       if (_esc_ident_bad (*ptr, ptr == name)) | ||||
|         { | ||||
|           bad = TRUE; | ||||
|           len += 3; | ||||
|         } | ||||
|       else | ||||
|         len++; | ||||
|     } | ||||
|  | ||||
|   /* fast path if it's clean */ | ||||
|   if (!bad) | ||||
|     return g_strdup (name); | ||||
|  | ||||
|   /* If strictly less than ptr, first_ok is the first uncopied safe character. | ||||
|    */ | ||||
|   first_ok = name; | ||||
|   op = g_string_sized_new (len); | ||||
|   for (ptr = name; *ptr; ptr++) | ||||
|     { | ||||
|       if (_esc_ident_bad (*ptr, ptr == name)) | ||||
|         { | ||||
|           /* copy preceding safe characters if any */ | ||||
|           if (first_ok < ptr) | ||||
|             { | ||||
|               g_string_append_len (op, first_ok, ptr - first_ok); | ||||
|             } | ||||
|           /* escape the unsafe character */ | ||||
|           g_string_append_printf (op, "_%02x", (unsigned char)(*ptr)); | ||||
|           /* restart after it */ | ||||
|           first_ok = ptr + 1; | ||||
|         } | ||||
|     } | ||||
|   /* copy trailing safe characters if any */ | ||||
|   if (first_ok < ptr) | ||||
|     { | ||||
|       g_string_append_len (op, first_ok, ptr - first_ok); | ||||
|     } | ||||
|   return g_string_free (op, FALSE); | ||||
| } | ||||
|  | ||||
| char * | ||||
| get_escaped_dbus_path (const char *prefix, | ||||
|                        const char *component) | ||||
| { | ||||
|   char *escaped_component = escape_dbus_component (component); | ||||
|   char *path = g_strconcat (prefix, "/", escaped_component, NULL); | ||||
|  | ||||
|   g_free (escaped_component); | ||||
|   return path; | ||||
| } | ||||
| @@ -1,32 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2014 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Jasper St. Pierre <jstpierre@mecheye.net> | ||||
|  */ | ||||
|  | ||||
| #ifndef DBUS_UTILS_H | ||||
| #define DBUS_UTILS_H | ||||
|  | ||||
| char * | ||||
| get_escaped_dbus_path (const char *prefix, | ||||
|                        const char *component); | ||||
|  | ||||
| #endif /* DBUS_UTILS_H */ | ||||
| @@ -1,251 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2014 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Jasper St. Pierre <jstpierre@mecheye.net> | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include <meta/main.h> | ||||
| #include <clutter/evdev/clutter-evdev.h> | ||||
| #include "meta-backend-native.h" | ||||
|  | ||||
| #include "meta-idle-monitor-native.h" | ||||
| #include "meta-monitor-manager-kms.h" | ||||
| #include "meta-cursor-renderer-native.h" | ||||
| #include "meta-launcher.h" | ||||
|  | ||||
| struct _MetaBackendNativePrivate | ||||
| { | ||||
|   MetaLauncher *launcher; | ||||
| }; | ||||
| typedef struct _MetaBackendNativePrivate MetaBackendNativePrivate; | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_PRIVATE (MetaBackendNative, meta_backend_native, META_TYPE_BACKEND); | ||||
|  | ||||
| /* | ||||
|  * The pointer constrain code is mostly a rip-off of the XRandR code from Xorg. | ||||
|  * (from xserver/randr/rrcrtc.c, RRConstrainCursorHarder) | ||||
|  * | ||||
|  * Copyright © 2006 Keith Packard | ||||
|  * Copyright 2010 Red Hat, Inc | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| static gboolean | ||||
| check_all_screen_monitors(MetaMonitorInfo *monitors, | ||||
| 			  unsigned         n_monitors, | ||||
| 			  float            x, | ||||
| 			  float            y) | ||||
| { | ||||
|   unsigned int i; | ||||
|  | ||||
|   for (i = 0; i < n_monitors; i++) | ||||
|     { | ||||
|       MetaMonitorInfo *monitor = &monitors[i]; | ||||
|       int left, right, top, bottom; | ||||
|  | ||||
|       left = monitor->rect.x; | ||||
|       right = left + monitor->rect.width; | ||||
|       top = monitor->rect.y; | ||||
|       bottom = left + monitor->rect.height; | ||||
|  | ||||
|       if ((x >= left) && (x < right) && (y >= top) && (y < bottom)) | ||||
| 	return TRUE; | ||||
|     } | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| constrain_all_screen_monitors (ClutterInputDevice *device, | ||||
| 			       MetaMonitorInfo    *monitors, | ||||
| 			       unsigned            n_monitors, | ||||
| 			       float              *x, | ||||
| 			       float              *y) | ||||
| { | ||||
|   ClutterPoint current; | ||||
|   unsigned int i; | ||||
|  | ||||
|   clutter_input_device_get_coords (device, NULL, ¤t); | ||||
|  | ||||
|   /* if we're trying to escape, clamp to the CRTC we're coming from */ | ||||
|   for (i = 0; i < n_monitors; i++) | ||||
|     { | ||||
|       MetaMonitorInfo *monitor = &monitors[i]; | ||||
|       int left, right, top, bottom; | ||||
|       float nx, ny; | ||||
|  | ||||
|       left = monitor->rect.x; | ||||
|       right = left + monitor->rect.width; | ||||
|       top = monitor->rect.y; | ||||
|       bottom = left + monitor->rect.height; | ||||
|  | ||||
|       nx = current.x; | ||||
|       ny = current.y; | ||||
|  | ||||
|       if ((nx >= left) && (nx < right) && (ny >= top) && (ny < bottom)) | ||||
| 	{ | ||||
| 	  if (*x < left) | ||||
| 	    *x = left; | ||||
| 	  if (*x >= right) | ||||
| 	    *x = right - 1; | ||||
| 	  if (*y < top) | ||||
| 	    *y = top; | ||||
| 	  if (*y >= bottom) | ||||
| 	    *y = bottom - 1; | ||||
|  | ||||
| 	  return; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| pointer_constrain_callback (ClutterInputDevice *device, | ||||
| 			    guint32             time, | ||||
| 			    float              *new_x, | ||||
| 			    float              *new_y, | ||||
| 			    gpointer            user_data) | ||||
| { | ||||
|   MetaMonitorManager *monitor_manager; | ||||
|   MetaMonitorInfo *monitors; | ||||
|   unsigned int n_monitors; | ||||
|   gboolean ret; | ||||
|  | ||||
|   monitor_manager = meta_monitor_manager_get (); | ||||
|   monitors = meta_monitor_manager_get_monitor_infos (monitor_manager, &n_monitors); | ||||
|  | ||||
|   /* if we're moving inside a monitor, we're fine */ | ||||
|   ret = check_all_screen_monitors(monitors, n_monitors, *new_x, *new_y); | ||||
|   if (ret == TRUE) | ||||
|     return; | ||||
|  | ||||
|   /* if we're trying to escape, clamp to the CRTC we're coming from */ | ||||
|   constrain_all_screen_monitors(device, monitors, n_monitors, new_x, new_y); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_backend_native_post_init (MetaBackend *backend) | ||||
| { | ||||
|   ClutterDeviceManager *manager = clutter_device_manager_get_default (); | ||||
|  | ||||
|   META_BACKEND_CLASS (meta_backend_native_parent_class)->post_init (backend); | ||||
|  | ||||
|   clutter_evdev_set_pointer_constrain_callback (manager, pointer_constrain_callback, | ||||
|                                                 NULL, NULL); | ||||
| } | ||||
|  | ||||
| static MetaIdleMonitor * | ||||
| meta_backend_native_create_idle_monitor (MetaBackend *backend, | ||||
|                                          int          device_id) | ||||
| { | ||||
|   return g_object_new (META_TYPE_IDLE_MONITOR_NATIVE, | ||||
|                        "device-id", device_id, | ||||
|                        NULL); | ||||
| } | ||||
|  | ||||
| static MetaMonitorManager * | ||||
| meta_backend_native_create_monitor_manager (MetaBackend *backend) | ||||
| { | ||||
|   return g_object_new (META_TYPE_MONITOR_MANAGER_KMS, NULL); | ||||
| } | ||||
|  | ||||
| static MetaCursorRenderer * | ||||
| meta_backend_native_create_cursor_renderer (MetaBackend *backend) | ||||
| { | ||||
|   return g_object_new (META_TYPE_CURSOR_RENDERER_NATIVE, NULL); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_backend_native_warp_pointer (MetaBackend *backend, | ||||
|                                   int          x, | ||||
|                                   int          y) | ||||
| { | ||||
|   ClutterDeviceManager *manager = clutter_device_manager_get_default (); | ||||
|   ClutterInputDevice *device = clutter_device_manager_get_core_device (manager, CLUTTER_POINTER_DEVICE); | ||||
|  | ||||
|   /* XXX */ | ||||
|   guint32 time_ = 0; | ||||
|  | ||||
|   clutter_evdev_warp_pointer (device, time_, x, y); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_backend_native_class_init (MetaBackendNativeClass *klass) | ||||
| { | ||||
|   MetaBackendClass *backend_class = META_BACKEND_CLASS (klass); | ||||
|  | ||||
|   backend_class->post_init = meta_backend_native_post_init; | ||||
|   backend_class->create_idle_monitor = meta_backend_native_create_idle_monitor; | ||||
|   backend_class->create_monitor_manager = meta_backend_native_create_monitor_manager; | ||||
|   backend_class->create_cursor_renderer = meta_backend_native_create_cursor_renderer; | ||||
|  | ||||
|   backend_class->warp_pointer = meta_backend_native_warp_pointer; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_backend_native_init (MetaBackendNative *native) | ||||
| { | ||||
|   MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native); | ||||
|  | ||||
|   /* We're a display server, so start talking to weston-launch. */ | ||||
|   priv->launcher = meta_launcher_new (); | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_activate_vt (int vt, GError **error) | ||||
| { | ||||
|   MetaBackend *backend = meta_get_backend (); | ||||
|   MetaBackendNative *native = META_BACKEND_NATIVE (backend); | ||||
|   MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native); | ||||
|  | ||||
|   return meta_launcher_activate_vt (priv->launcher, vt, error); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * 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) | ||||
| { | ||||
|   GError *error = NULL; | ||||
|   MetaBackend *backend = meta_get_backend (); | ||||
|  | ||||
|   /* Do nothing. */ | ||||
|   if (!META_IS_BACKEND_NATIVE (backend)) | ||||
|     return TRUE; | ||||
|  | ||||
|   MetaBackendNative *native = META_BACKEND_NATIVE (backend); | ||||
|   MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native); | ||||
|  | ||||
|   if (!meta_launcher_activate_session (priv->launcher, &error)) | ||||
|     { | ||||
|       g_warning ("Could not activate session: %s\n", error->message); | ||||
|       g_error_free (error); | ||||
|       return FALSE; | ||||
|     } | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
| @@ -1,54 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2014 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Jasper St. Pierre <jstpierre@mecheye.net> | ||||
|  */ | ||||
|  | ||||
| #ifndef META_BACKEND_NATIVE_H | ||||
| #define META_BACKEND_NATIVE_H | ||||
|  | ||||
| #include "backends/meta-backend-private.h" | ||||
|  | ||||
| #define META_TYPE_BACKEND_NATIVE             (meta_backend_native_get_type ()) | ||||
| #define META_BACKEND_NATIVE(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BACKEND_NATIVE, MetaBackendNative)) | ||||
| #define META_BACKEND_NATIVE_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_BACKEND_NATIVE, MetaBackendNativeClass)) | ||||
| #define META_IS_BACKEND_NATIVE(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_BACKEND_NATIVE)) | ||||
| #define META_IS_BACKEND_NATIVE_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_BACKEND_NATIVE)) | ||||
| #define META_BACKEND_NATIVE_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_BACKEND_NATIVE, MetaBackendNativeClass)) | ||||
|  | ||||
| typedef struct _MetaBackendNative        MetaBackendNative; | ||||
| typedef struct _MetaBackendNativeClass   MetaBackendNativeClass; | ||||
|  | ||||
| struct _MetaBackendNative | ||||
| { | ||||
|   MetaBackend parent; | ||||
| }; | ||||
|  | ||||
| struct _MetaBackendNativeClass | ||||
| { | ||||
|   MetaBackendClass parent_class; | ||||
| }; | ||||
|  | ||||
| GType meta_backend_native_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| gboolean meta_activate_vt (int vt, GError **error); | ||||
|  | ||||
| #endif /* META_BACKEND_NATIVE_H */ | ||||
| @@ -1,205 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2014 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Jasper St. Pierre <jstpierre@mecheye.net> | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include "meta-cursor-renderer-native.h" | ||||
|  | ||||
| #include <gbm.h> | ||||
|  | ||||
| #include "meta-cursor-private.h" | ||||
| #include "meta-monitor-manager.h" | ||||
|  | ||||
| struct _MetaCursorRendererNativePrivate | ||||
| { | ||||
|   gboolean has_hw_cursor; | ||||
|  | ||||
|   int drm_fd; | ||||
|   struct gbm_device *gbm; | ||||
| }; | ||||
| typedef struct _MetaCursorRendererNativePrivate MetaCursorRendererNativePrivate; | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRendererNative, meta_cursor_renderer_native, META_TYPE_CURSOR_RENDERER); | ||||
|  | ||||
| static void | ||||
| meta_cursor_renderer_native_finalize (GObject *object) | ||||
| { | ||||
|   MetaCursorRendererNative *renderer = META_CURSOR_RENDERER_NATIVE (object); | ||||
|   MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (renderer); | ||||
|  | ||||
|   if (priv->gbm) | ||||
|     gbm_device_destroy (priv->gbm); | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_cursor_renderer_native_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| set_crtc_cursor (MetaCursorRendererNative *native, | ||||
|                  MetaCRTC                 *crtc, | ||||
|                  MetaCursorReference      *cursor, | ||||
|                  gboolean                  force) | ||||
| { | ||||
|   MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native); | ||||
|  | ||||
|   if (crtc->cursor == cursor && !force) | ||||
|     return; | ||||
|  | ||||
|   crtc->cursor = cursor; | ||||
|  | ||||
|   if (cursor) | ||||
|     { | ||||
|       struct gbm_bo *bo; | ||||
|       union gbm_bo_handle handle; | ||||
|       int width, height; | ||||
|       int hot_x, hot_y; | ||||
|  | ||||
|       bo = meta_cursor_reference_get_gbm_bo (cursor, &hot_x, &hot_y); | ||||
|  | ||||
|       handle = gbm_bo_get_handle (bo); | ||||
|       width = gbm_bo_get_width (bo); | ||||
|       height = gbm_bo_get_height (bo); | ||||
|  | ||||
|       drmModeSetCursor2 (priv->drm_fd, crtc->crtc_id, handle.u32, | ||||
|                          width, height, hot_x, hot_y); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       drmModeSetCursor2 (priv->drm_fd, crtc->crtc_id, 0, 0, 0, 0, 0); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_hw_cursor (MetaCursorRendererNative *native, | ||||
|                   gboolean                  force) | ||||
| { | ||||
|   MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native); | ||||
|   MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native); | ||||
|   const MetaRectangle *cursor_rect = meta_cursor_renderer_get_rect (renderer); | ||||
|   MetaCursorReference *cursor = meta_cursor_renderer_get_cursor (renderer); | ||||
|   MetaMonitorManager *monitors; | ||||
|   MetaCRTC *crtcs; | ||||
|   unsigned int i, n_crtcs; | ||||
|  | ||||
|   monitors = meta_monitor_manager_get (); | ||||
|   meta_monitor_manager_get_resources (monitors, NULL, NULL, &crtcs, &n_crtcs, NULL, NULL); | ||||
|  | ||||
|   for (i = 0; i < n_crtcs; i++) | ||||
|     { | ||||
|       gboolean crtc_should_have_cursor; | ||||
|       MetaCursorReference *crtc_cursor; | ||||
|       MetaRectangle *crtc_rect; | ||||
|  | ||||
|       crtc_rect = &crtcs[i].rect; | ||||
|  | ||||
|       crtc_should_have_cursor = (priv->has_hw_cursor && meta_rectangle_overlap (cursor_rect, crtc_rect)); | ||||
|       if (crtc_should_have_cursor) | ||||
|         crtc_cursor = cursor; | ||||
|       else | ||||
|         crtc_cursor = NULL; | ||||
|  | ||||
|       set_crtc_cursor (native, &crtcs[i], crtc_cursor, force); | ||||
|  | ||||
|       if (crtc_cursor) | ||||
|         { | ||||
|           drmModeMoveCursor (priv->drm_fd, crtcs[i].crtc_id, | ||||
|                              cursor_rect->x - crtc_rect->x, | ||||
|                              cursor_rect->y - crtc_rect->y); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| should_have_hw_cursor (MetaCursorRenderer *renderer) | ||||
| { | ||||
|   MetaCursorReference *cursor = meta_cursor_renderer_get_cursor (renderer); | ||||
|  | ||||
|   if (cursor) | ||||
|     return (meta_cursor_reference_get_gbm_bo (cursor, NULL, NULL) != NULL); | ||||
|   else | ||||
|     return FALSE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer) | ||||
| { | ||||
|   MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer); | ||||
|   MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native); | ||||
|  | ||||
|   priv->has_hw_cursor = should_have_hw_cursor (renderer); | ||||
|   update_hw_cursor (native, FALSE); | ||||
|   return priv->has_hw_cursor; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_cursor_renderer_native_class_init (MetaCursorRendererNativeClass *klass) | ||||
| { | ||||
|   MetaCursorRendererClass *renderer_class = META_CURSOR_RENDERER_CLASS (klass); | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|  | ||||
|   object_class->finalize = meta_cursor_renderer_native_finalize; | ||||
|   renderer_class->update_cursor = meta_cursor_renderer_native_update_cursor; | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_monitors_changed (MetaMonitorManager       *monitors, | ||||
|                      MetaCursorRendererNative *native) | ||||
| { | ||||
|   /* Our tracking is all messed up, so force an update. */ | ||||
|   update_hw_cursor (native, TRUE); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_cursor_renderer_native_init (MetaCursorRendererNative *native) | ||||
| { | ||||
|   MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native); | ||||
|   CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); | ||||
|   MetaMonitorManager *monitors; | ||||
|  | ||||
|   monitors = meta_monitor_manager_get (); | ||||
|   g_signal_connect_object (monitors, "monitors-changed", | ||||
|                            G_CALLBACK (on_monitors_changed), native, 0); | ||||
|  | ||||
| #if defined(CLUTTER_WINDOWING_EGL) | ||||
|   if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL)) | ||||
|     { | ||||
|       CoglRenderer *cogl_renderer = cogl_display_get_renderer (cogl_context_get_display (ctx)); | ||||
|       priv->drm_fd = cogl_kms_renderer_get_kms_fd (cogl_renderer); | ||||
|       priv->gbm = gbm_create_device (priv->drm_fd); | ||||
|     } | ||||
| #endif | ||||
| } | ||||
|  | ||||
| struct gbm_device * | ||||
| meta_cursor_renderer_native_get_gbm_device (MetaCursorRendererNative *native) | ||||
| { | ||||
|   MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native); | ||||
|  | ||||
|   return priv->gbm; | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_cursor_renderer_native_force_update (MetaCursorRendererNative *native) | ||||
| { | ||||
|   update_hw_cursor (native, TRUE); | ||||
| } | ||||
| @@ -1,55 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2014 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Jasper St. Pierre <jstpierre@mecheye.net> | ||||
|  */ | ||||
|  | ||||
| #ifndef META_CURSOR_RENDERER_NATIVE_H | ||||
| #define META_CURSOR_RENDERER_NATIVE_H | ||||
|  | ||||
| #include "meta-cursor-renderer.h" | ||||
|  | ||||
| #define META_TYPE_CURSOR_RENDERER_NATIVE             (meta_cursor_renderer_native_get_type ()) | ||||
| #define META_CURSOR_RENDERER_NATIVE(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CURSOR_RENDERER_NATIVE, MetaCursorRendererNative)) | ||||
| #define META_CURSOR_RENDERER_NATIVE_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_CURSOR_RENDERER_NATIVE, MetaCursorRendererNativeClass)) | ||||
| #define META_IS_CURSOR_RENDERER_NATIVE(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_CURSOR_RENDERER_NATIVE)) | ||||
| #define META_IS_CURSOR_RENDERER_NATIVE_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_CURSOR_RENDERER_NATIVE)) | ||||
| #define META_CURSOR_RENDERER_NATIVE_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_CURSOR_RENDERER_NATIVE, MetaCursorRendererNativeClass)) | ||||
|  | ||||
| typedef struct _MetaCursorRendererNative        MetaCursorRendererNative; | ||||
| typedef struct _MetaCursorRendererNativeClass   MetaCursorRendererNativeClass; | ||||
|  | ||||
| struct _MetaCursorRendererNative | ||||
| { | ||||
|   MetaCursorRenderer parent; | ||||
| }; | ||||
|  | ||||
| struct _MetaCursorRendererNativeClass | ||||
| { | ||||
|   MetaCursorRendererClass parent_class; | ||||
| }; | ||||
|  | ||||
| GType meta_cursor_renderer_native_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| struct gbm_device * meta_cursor_renderer_native_get_gbm_device (MetaCursorRendererNative *renderer); | ||||
| void meta_cursor_renderer_native_force_update (MetaCursorRendererNative *renderer); | ||||
|  | ||||
| #endif /* META_CURSOR_RENDERER_NATIVE_H */ | ||||
| @@ -1,219 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright 2013 Red Hat, Inc. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * Adapted from gnome-session/gnome-session/gs-idle-monitor.c and | ||||
|  *         from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include "meta-idle-monitor-native.h" | ||||
| #include "meta-idle-monitor-private.h" | ||||
|  | ||||
| #include <meta/util.h> | ||||
| #include "display-private.h" | ||||
|  | ||||
| #include <string.h> | ||||
|  | ||||
| struct _MetaIdleMonitorNative | ||||
| { | ||||
|   MetaIdleMonitor parent; | ||||
|  | ||||
|   guint64 last_event_time; | ||||
| }; | ||||
|  | ||||
| struct _MetaIdleMonitorNativeClass | ||||
| { | ||||
|   MetaIdleMonitorClass parent_class; | ||||
| }; | ||||
|  | ||||
| typedef struct { | ||||
|   MetaIdleMonitorWatch base; | ||||
|  | ||||
|   GSource *timeout_source; | ||||
| } MetaIdleMonitorWatchNative; | ||||
|  | ||||
| G_DEFINE_TYPE (MetaIdleMonitorNative, meta_idle_monitor_native, META_TYPE_IDLE_MONITOR) | ||||
|  | ||||
| static gint64 | ||||
| meta_idle_monitor_native_get_idletime (MetaIdleMonitor *monitor) | ||||
| { | ||||
|   MetaIdleMonitorNative *monitor_native = META_IDLE_MONITOR_NATIVE (monitor); | ||||
|  | ||||
|   return (g_get_monotonic_time () - monitor_native->last_event_time) / 1000; | ||||
| } | ||||
|  | ||||
| static guint32 | ||||
| get_next_watch_serial (void) | ||||
| { | ||||
|   static guint32 serial = 0; | ||||
|   g_atomic_int_inc (&serial); | ||||
|   return serial; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| native_dispatch_timeout (GSource     *source, | ||||
|                          GSourceFunc  callback, | ||||
|                          gpointer     user_data) | ||||
| { | ||||
|   MetaIdleMonitorWatchNative *watch_native = user_data; | ||||
|   MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_native; | ||||
|  | ||||
|   _meta_idle_monitor_watch_fire (watch); | ||||
|   g_source_set_ready_time (watch_native->timeout_source, -1); | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static GSourceFuncs native_source_funcs = { | ||||
|   NULL, /* prepare */ | ||||
|   NULL, /* check */ | ||||
|   native_dispatch_timeout, | ||||
|   NULL, /* finalize */ | ||||
| }; | ||||
|  | ||||
| static void | ||||
| free_watch (gpointer data) | ||||
| { | ||||
|   MetaIdleMonitorWatchNative *watch_native = data; | ||||
|   MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_native; | ||||
|   MetaIdleMonitor *monitor = watch->monitor; | ||||
|  | ||||
|   g_object_ref (monitor); | ||||
|  | ||||
|   if (watch->idle_source_id) | ||||
|     { | ||||
|       g_source_remove (watch->idle_source_id); | ||||
|       watch->idle_source_id = 0; | ||||
|     } | ||||
|  | ||||
|   if (watch->notify != NULL) | ||||
|     watch->notify (watch->user_data); | ||||
|  | ||||
|   if (watch_native->timeout_source != NULL) | ||||
|     g_source_destroy (watch_native->timeout_source); | ||||
|  | ||||
|   g_object_unref (monitor); | ||||
|   g_slice_free (MetaIdleMonitorWatchNative, watch_native); | ||||
| } | ||||
|  | ||||
| static MetaIdleMonitorWatch * | ||||
| meta_idle_monitor_native_make_watch (MetaIdleMonitor           *monitor, | ||||
|                                      guint64                    timeout_msec, | ||||
|                                      MetaIdleMonitorWatchFunc   callback, | ||||
|                                      gpointer                   user_data, | ||||
|                                      GDestroyNotify             notify) | ||||
| { | ||||
|   MetaIdleMonitorWatchNative *watch_native; | ||||
|   MetaIdleMonitorWatch *watch; | ||||
|   MetaIdleMonitorNative *monitor_native = META_IDLE_MONITOR_NATIVE (monitor); | ||||
|  | ||||
|   watch_native = g_slice_new0 (MetaIdleMonitorWatchNative); | ||||
|   watch = (MetaIdleMonitorWatch *) watch_native; | ||||
|  | ||||
|   watch->monitor = monitor; | ||||
|   watch->id = get_next_watch_serial (); | ||||
|   watch->callback = callback; | ||||
|   watch->user_data = user_data; | ||||
|   watch->notify = notify; | ||||
|   watch->timeout_msec = timeout_msec; | ||||
|  | ||||
|   if (timeout_msec != 0) | ||||
|     { | ||||
|       GSource *source = g_source_new (&native_source_funcs, sizeof (GSource)); | ||||
|  | ||||
|       g_source_set_callback (source, NULL, watch, NULL); | ||||
|       g_source_set_ready_time (source, monitor_native->last_event_time + timeout_msec * 1000); | ||||
|       g_source_attach (source, NULL); | ||||
|       g_source_unref (source); | ||||
|  | ||||
|       watch_native->timeout_source = source; | ||||
|     } | ||||
|  | ||||
|   return watch; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_idle_monitor_native_class_init (MetaIdleMonitorNativeClass *klass) | ||||
| { | ||||
|   MetaIdleMonitorClass *idle_monitor_class = META_IDLE_MONITOR_CLASS (klass); | ||||
|  | ||||
|   idle_monitor_class->get_idletime = meta_idle_monitor_native_get_idletime; | ||||
|   idle_monitor_class->make_watch = meta_idle_monitor_native_make_watch; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_idle_monitor_native_init (MetaIdleMonitorNative *monitor_native) | ||||
| { | ||||
|   MetaIdleMonitor *monitor = META_IDLE_MONITOR (monitor_native); | ||||
|  | ||||
|   monitor->watches = g_hash_table_new_full (NULL, NULL, NULL, free_watch); | ||||
| } | ||||
|  | ||||
| typedef struct { | ||||
|   MetaIdleMonitorNative *monitor_native; | ||||
|   GList *fired_watches; | ||||
| } CheckNativeClosure; | ||||
|  | ||||
| static gboolean | ||||
| check_native_watch (gpointer key, | ||||
|                     gpointer value, | ||||
|                     gpointer user_data) | ||||
| { | ||||
|   MetaIdleMonitorWatchNative *watch_native = value; | ||||
|   MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_native; | ||||
|   CheckNativeClosure *closure = user_data; | ||||
|   gboolean steal; | ||||
|  | ||||
|   if (watch->timeout_msec == 0) | ||||
|     { | ||||
|       closure->fired_watches = g_list_prepend (closure->fired_watches, watch); | ||||
|       steal = TRUE; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       g_source_set_ready_time (watch_native->timeout_source, | ||||
|                                closure->monitor_native->last_event_time + | ||||
|                                watch->timeout_msec * 1000); | ||||
|       steal = FALSE; | ||||
|     } | ||||
|  | ||||
|   return steal; | ||||
| } | ||||
|  | ||||
| static void | ||||
| fire_native_watch (gpointer watch, | ||||
|                    gpointer data) | ||||
| { | ||||
|   _meta_idle_monitor_watch_fire (watch); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_idle_monitor_native_reset_idletime (MetaIdleMonitor *monitor) | ||||
| { | ||||
|   MetaIdleMonitorNative *monitor_native = META_IDLE_MONITOR_NATIVE (monitor); | ||||
|   CheckNativeClosure closure; | ||||
|  | ||||
|   monitor_native->last_event_time = g_get_monotonic_time (); | ||||
|  | ||||
|   closure.monitor_native = monitor_native; | ||||
|   closure.fired_watches = NULL; | ||||
|   g_hash_table_foreach_steal (monitor->watches, check_native_watch, &closure); | ||||
|  | ||||
|   g_list_foreach (closure.fired_watches, fire_native_watch, NULL); | ||||
|   g_list_free (closure.fired_watches); | ||||
| } | ||||
| @@ -1,43 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright 2013 Red Hat, Inc. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * Adapted from gnome-session/gnome-session/gs-idle-monitor.c and | ||||
|  *         from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c | ||||
|  */ | ||||
|  | ||||
| #ifndef META_IDLE_MONITOR_NATIVE_H | ||||
| #define META_IDLE_MONITOR_NATIVE_H | ||||
|  | ||||
| #include <glib-object.h> | ||||
| #include <meta/meta-idle-monitor.h> | ||||
|  | ||||
| #define META_TYPE_IDLE_MONITOR_NATIVE            (meta_idle_monitor_native_get_type ()) | ||||
| #define META_IDLE_MONITOR_NATIVE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_IDLE_MONITOR_NATIVE, MetaIdleMonitorNative)) | ||||
| #define META_IDLE_MONITOR_NATIVE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_IDLE_MONITOR_NATIVE, MetaIdleMonitorNativeClass)) | ||||
| #define META_IS_IDLE_MONITOR_NATIVE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_IDLE_MONITOR_NATIVE)) | ||||
| #define META_IS_IDLE_MONITOR_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_IDLE_MONITOR_NATIVE)) | ||||
| #define META_IDLE_MONITOR_NATIVE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_IDLE_MONITOR_NATIVE, MetaIdleMonitorNativeClass)) | ||||
|  | ||||
| typedef struct _MetaIdleMonitorNative        MetaIdleMonitorNative; | ||||
| typedef struct _MetaIdleMonitorNativeClass   MetaIdleMonitorNativeClass; | ||||
|  | ||||
| GType meta_idle_monitor_native_get_type (void); | ||||
|  | ||||
| void meta_idle_monitor_native_reset_idletime (MetaIdleMonitor *monitor); | ||||
|  | ||||
| #endif /* META_IDLE_MONITOR_NATIVE_H */ | ||||
| @@ -1,368 +0,0 @@ | ||||
| /* | ||||
|  * Copyright (C) 2013 Red Hat, Inc. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include "meta-launcher.h" | ||||
|  | ||||
| #include <gio/gunixfdlist.h> | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
| #include <clutter/egl/clutter-egl.h> | ||||
| #include <clutter/evdev/clutter-evdev.h> | ||||
|  | ||||
| #include <sys/types.h> | ||||
| #include <sys/stat.h> | ||||
| #include <malloc.h> | ||||
| #include <fcntl.h> | ||||
| #include <errno.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <unistd.h> | ||||
|  | ||||
| #include <systemd/sd-login.h> | ||||
|  | ||||
| #include "dbus-utils.h" | ||||
| #include "meta-dbus-login1.h" | ||||
|  | ||||
| #include "wayland/meta-wayland-private.h" | ||||
| #include "backends/meta-backend.h" | ||||
| #include "meta-cursor-renderer-native.h" | ||||
|  | ||||
| struct _MetaLauncher | ||||
| { | ||||
|   Login1Session *session_proxy; | ||||
|   Login1Seat *seat_proxy; | ||||
|  | ||||
|   gboolean session_active; | ||||
| }; | ||||
|  | ||||
| static Login1Session * | ||||
| get_session_proxy (GCancellable *cancellable) | ||||
| { | ||||
|   char *proxy_path; | ||||
|   char *session_id; | ||||
|   Login1Session *session_proxy; | ||||
|  | ||||
|   if (sd_pid_get_session (getpid (), &session_id) < 0) | ||||
|     return NULL; | ||||
|  | ||||
|   proxy_path = get_escaped_dbus_path ("/org/freedesktop/login1/session", session_id); | ||||
|  | ||||
|   session_proxy = login1_session_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, | ||||
|                                                          G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, | ||||
|                                                          "org.freedesktop.login1", | ||||
|                                                          proxy_path, | ||||
|                                                          cancellable, NULL); | ||||
|   free (proxy_path); | ||||
|  | ||||
|   return session_proxy; | ||||
| } | ||||
|  | ||||
| static Login1Seat * | ||||
| get_seat_proxy (GCancellable *cancellable) | ||||
| { | ||||
|   return login1_seat_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, | ||||
|                                              G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, | ||||
|                                              "org.freedesktop.login1", | ||||
|                                              "/org/freedesktop/login1/seat/self", | ||||
|                                              cancellable, NULL); | ||||
| } | ||||
|  | ||||
| static void | ||||
| session_unpause (void) | ||||
| { | ||||
|   ClutterBackend *backend; | ||||
|   CoglContext *cogl_context; | ||||
|   CoglDisplay *cogl_display; | ||||
|  | ||||
|   backend = clutter_get_default_backend (); | ||||
|   cogl_context = clutter_backend_get_cogl_context (backend); | ||||
|   cogl_display = cogl_context_get_display (cogl_context); | ||||
|   cogl_kms_display_queue_modes_reset (cogl_display); | ||||
|  | ||||
|   clutter_evdev_reclaim_devices (); | ||||
|   clutter_egl_thaw_master_clock (); | ||||
|  | ||||
|   { | ||||
|     MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); | ||||
|     MetaBackend *backend = meta_get_backend (); | ||||
|     MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (backend); | ||||
|  | ||||
|     /* 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_renderer_native_force_update (META_CURSOR_RENDERER_NATIVE (renderer)); | ||||
|   } | ||||
| } | ||||
|  | ||||
| static void | ||||
| session_pause (void) | ||||
| { | ||||
|   clutter_evdev_release_devices (); | ||||
|   clutter_egl_freeze_master_clock (); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| take_device (Login1Session *session_proxy, | ||||
|              int            dev_major, | ||||
|              int            dev_minor, | ||||
|              int           *out_fd, | ||||
|              GCancellable  *cancellable, | ||||
|              GError       **error) | ||||
| { | ||||
|   gboolean ret = FALSE; | ||||
|   GVariant *fd_variant = NULL; | ||||
|   int fd = -1; | ||||
|   GUnixFDList *fd_list; | ||||
|  | ||||
|   if (!login1_session_call_take_device_sync (session_proxy, | ||||
|                                              dev_major, | ||||
|                                              dev_minor, | ||||
|                                              NULL, | ||||
|                                              &fd_variant, | ||||
|                                              NULL, /* paused */ | ||||
|                                              &fd_list, | ||||
|                                              cancellable, | ||||
|                                              error)) | ||||
|     goto out; | ||||
|  | ||||
|   fd = g_unix_fd_list_get (fd_list, g_variant_get_handle (fd_variant), error); | ||||
|   if (fd == -1) | ||||
|     goto out; | ||||
|  | ||||
|   *out_fd = fd; | ||||
|   ret = TRUE; | ||||
|  | ||||
|  out: | ||||
|   if (fd_variant) | ||||
|     g_variant_unref (fd_variant); | ||||
|   if (fd_list) | ||||
|     g_object_unref (fd_list); | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| get_device_info_from_path (const char *path, | ||||
|                            int        *out_major, | ||||
|                            int        *out_minor) | ||||
| { | ||||
|   gboolean ret = FALSE; | ||||
|   int r; | ||||
|   struct stat st; | ||||
|  | ||||
|   r = stat (path, &st); | ||||
|   if (r < 0) | ||||
|     goto out; | ||||
|   if (!S_ISCHR (st.st_mode)) | ||||
|     goto out; | ||||
|  | ||||
|   *out_major = major (st.st_rdev); | ||||
|   *out_minor = minor (st.st_rdev); | ||||
|   ret = TRUE; | ||||
|  | ||||
|  out: | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| get_device_info_from_fd (int  fd, | ||||
|                          int *out_major, | ||||
|                          int *out_minor) | ||||
| { | ||||
|   gboolean ret = FALSE; | ||||
|   int r; | ||||
|   struct stat st; | ||||
|  | ||||
|   r = fstat (fd, &st); | ||||
|   if (r < 0) | ||||
|     goto out; | ||||
|   if (!S_ISCHR (st.st_mode)) | ||||
|     goto out; | ||||
|  | ||||
|   *out_major = major (st.st_rdev); | ||||
|   *out_minor = minor (st.st_rdev); | ||||
|   ret = TRUE; | ||||
|  | ||||
|  out: | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| static int | ||||
| on_evdev_device_open (const char  *path, | ||||
|                       int          flags, | ||||
|                       gpointer     user_data, | ||||
|                       GError     **error) | ||||
| { | ||||
|   MetaLauncher *self = user_data; | ||||
|   int fd; | ||||
|   int major, minor; | ||||
|  | ||||
|   if (!get_device_info_from_path (path, &major, &minor)) | ||||
|     { | ||||
|       g_set_error (error, | ||||
|                    G_IO_ERROR, | ||||
|                    G_IO_ERROR_NOT_FOUND, | ||||
|                    "Could not get device info for path %s: %m", path); | ||||
|       return -1; | ||||
|     } | ||||
|  | ||||
|   if (!take_device (self->session_proxy, major, minor, &fd, NULL, error)) | ||||
|     return -1; | ||||
|  | ||||
|   return fd; | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_evdev_device_close (int      fd, | ||||
|                        gpointer user_data) | ||||
| { | ||||
|   MetaLauncher *self = user_data; | ||||
|   int major, minor; | ||||
|   GError *error = NULL; | ||||
|  | ||||
|   if (!get_device_info_from_fd (fd, &major, &minor)) | ||||
|     { | ||||
|       g_warning ("Could not get device info for fd %d: %m", fd); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   if (!login1_session_call_release_device_sync (self->session_proxy, | ||||
|                                                 major, minor, | ||||
|                                                 NULL, &error)) | ||||
|     { | ||||
|       g_warning ("Could not release device %d,%d: %s", major, minor, error->message); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| sync_active (MetaLauncher *self) | ||||
| { | ||||
|   gboolean active = login1_session_get_active (LOGIN1_SESSION (self->session_proxy)); | ||||
|  | ||||
|   if (active == self->session_active) | ||||
|     return; | ||||
|  | ||||
|   self->session_active = active; | ||||
|  | ||||
|   if (active) | ||||
|     session_unpause (); | ||||
|   else | ||||
|     session_pause (); | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_active_changed (Login1Session *session, | ||||
|                    GParamSpec    *pspec, | ||||
|                    gpointer       user_data) | ||||
| { | ||||
|   MetaLauncher *self = user_data; | ||||
|   sync_active (self); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| get_kms_fd (Login1Session *session_proxy, | ||||
|             int *fd_out) | ||||
| { | ||||
|   int major, minor; | ||||
|   int fd; | ||||
|   GError *error = NULL; | ||||
|  | ||||
|   /* XXX -- use udev to find the DRM master device */ | ||||
|   if (!get_device_info_from_path ("/dev/dri/card0", &major, &minor)) | ||||
|     { | ||||
|       g_warning ("Could not stat /dev/dri/card0: %m"); | ||||
|       return FALSE; | ||||
|     } | ||||
|  | ||||
|   if (!take_device (session_proxy, major, minor, &fd, NULL, &error)) | ||||
|     { | ||||
|       g_warning ("Could not open DRM device: %s\n", error->message); | ||||
|       g_error_free (error); | ||||
|       return FALSE; | ||||
|     } | ||||
|  | ||||
|   *fd_out = fd; | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| MetaLauncher * | ||||
| meta_launcher_new (void) | ||||
| { | ||||
|   MetaLauncher *self; | ||||
|   Login1Session *session_proxy; | ||||
|   GError *error = NULL; | ||||
|   int kms_fd; | ||||
|  | ||||
|   session_proxy = get_session_proxy (NULL); | ||||
|   if (!login1_session_call_take_control_sync (session_proxy, FALSE, NULL, &error)) | ||||
|     { | ||||
|       g_warning ("Could not take control: %s", error->message); | ||||
|       g_error_free (error); | ||||
|       return NULL; | ||||
|     } | ||||
|  | ||||
|   if (!get_kms_fd (session_proxy, &kms_fd)) | ||||
|     return NULL; | ||||
|  | ||||
|   self = g_slice_new0 (MetaLauncher); | ||||
|   self->session_proxy = session_proxy; | ||||
|   self->seat_proxy = get_seat_proxy (NULL); | ||||
|  | ||||
|   self->session_active = TRUE; | ||||
|  | ||||
|   clutter_egl_set_kms_fd (kms_fd); | ||||
|   clutter_evdev_set_device_callbacks (on_evdev_device_open, | ||||
|                                       on_evdev_device_close, | ||||
|                                       self); | ||||
|  | ||||
|   g_signal_connect (self->session_proxy, "notify::active", G_CALLBACK (on_active_changed), self); | ||||
|  | ||||
|   return self; | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_launcher_free (MetaLauncher *self) | ||||
| { | ||||
|   g_object_unref (self->seat_proxy); | ||||
|   g_object_unref (self->session_proxy); | ||||
|   g_slice_free (MetaLauncher, self); | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_launcher_activate_session (MetaLauncher  *launcher, | ||||
|                                 GError       **error) | ||||
| { | ||||
|   if (!login1_session_call_activate_sync (launcher->session_proxy, NULL, error)) | ||||
|     return FALSE; | ||||
|  | ||||
|   sync_active (launcher); | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_launcher_activate_vt (MetaLauncher  *launcher, | ||||
|                            signed char    vt, | ||||
|                            GError       **error) | ||||
| { | ||||
|   return login1_seat_call_switch_to_sync (launcher->seat_proxy, vt, NULL, error); | ||||
| } | ||||
| @@ -1,37 +0,0 @@ | ||||
| /* | ||||
|  * Copyright (C) 2013 Red Hat, Inc. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  */ | ||||
|  | ||||
| #ifndef META_LAUNCHER_H | ||||
| #define META_LAUNCHER_H | ||||
|  | ||||
| #include <glib-object.h> | ||||
|  | ||||
| typedef struct _MetaLauncher MetaLauncher; | ||||
|  | ||||
| MetaLauncher     *meta_launcher_new                     (void); | ||||
| void              meta_launcher_free                    (MetaLauncher  *self); | ||||
|  | ||||
| gboolean          meta_launcher_activate_session        (MetaLauncher  *self, | ||||
| 							 GError       **error); | ||||
|  | ||||
| gboolean          meta_launcher_activate_vt             (MetaLauncher  *self, | ||||
| 							 signed char    vt, | ||||
| 							 GError       **error); | ||||
|  | ||||
| #endif /* META_LAUNCHER_H */ | ||||
| @@ -1,939 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2013 Red Hat Inc. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Author: Giovanni Campagna <gcampagn@redhat.com> | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include "meta-monitor-manager-kms.h" | ||||
|  | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| #include <errno.h> | ||||
| #include <sys/ioctl.h> | ||||
| #include <sys/mman.h> | ||||
| #include <unistd.h> | ||||
| #include <xf86drm.h> | ||||
| #include <xf86drmMode.h> | ||||
|  | ||||
| #include <meta/main.h> | ||||
| #include <meta/errors.h> | ||||
| #include "edid.h" | ||||
|  | ||||
| #define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1) | ||||
|  | ||||
| typedef struct { | ||||
|   drmModeConnector *connector; | ||||
|  | ||||
|   unsigned n_encoders; | ||||
|   drmModeEncoderPtr *encoders; | ||||
|   drmModeEncoderPtr  current_encoder; | ||||
|  | ||||
|   /* bitmasks of encoder position in the resources array */ | ||||
|   uint32_t encoder_mask; | ||||
|   uint32_t enc_clone_mask; | ||||
|  | ||||
|   uint32_t dpms_prop_id; | ||||
|   uint32_t edid_blob_id; | ||||
| } MetaOutputKms; | ||||
|  | ||||
| struct _MetaMonitorManagerKms | ||||
| { | ||||
|   MetaMonitorManager parent_instance; | ||||
|  | ||||
|   int fd; | ||||
|  | ||||
|   drmModeConnector **connectors; | ||||
|   unsigned int       n_connectors; | ||||
|  | ||||
|   drmModeEncoder   **encoders; | ||||
|   unsigned int       n_encoders; | ||||
|  | ||||
|   drmModeEncoder    *current_encoder; | ||||
| }; | ||||
|  | ||||
| struct _MetaMonitorManagerKmsClass | ||||
| { | ||||
|   MetaMonitorManagerClass parent_class; | ||||
| }; | ||||
|  | ||||
| G_DEFINE_TYPE (MetaMonitorManagerKms, meta_monitor_manager_kms, META_TYPE_MONITOR_MANAGER); | ||||
|  | ||||
| static void | ||||
| free_resources (MetaMonitorManagerKms *manager_kms) | ||||
| { | ||||
|   unsigned i; | ||||
|  | ||||
|   for (i = 0; i < manager_kms->n_encoders; i++) | ||||
|     drmModeFreeEncoder (manager_kms->encoders[i]); | ||||
|   for (i = 0; i < manager_kms->n_connectors; i++) | ||||
|     drmModeFreeConnector (manager_kms->connectors[i]); | ||||
|  | ||||
|   g_free (manager_kms->encoders); | ||||
|   g_free (manager_kms->connectors); | ||||
| } | ||||
|  | ||||
| static int | ||||
| compare_outputs (const void *one, | ||||
|                  const void *two) | ||||
| { | ||||
|   const MetaOutput *o_one = one, *o_two = two; | ||||
|  | ||||
|   return strcmp (o_one->name, o_two->name); | ||||
| } | ||||
|  | ||||
| static char * | ||||
| make_output_name (drmModeConnector *connector) | ||||
| { | ||||
|   static const char * const connector_type_names[] = { | ||||
|     "unknown", "VGA", "DVII", "DVID", "DVID", "Composite", | ||||
|     "SVIDEO", "LVDS", "Component", "9PinDIN", "DisplayPort", | ||||
|     "HDMIA", "HDMIB", "TV", "eDP" | ||||
|   }; | ||||
|   const char *connector_type_name; | ||||
|  | ||||
|   if (connector->connector_type < G_N_ELEMENTS (connector_type_names)) | ||||
|     connector_type_name = connector_type_names[connector->connector_type]; | ||||
|   else | ||||
|     connector_type_name = "unknown"; | ||||
|  | ||||
|   return g_strdup_printf ("%s%d", connector_type_name, connector->connector_id); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_output_destroy_notify (MetaOutput *output) | ||||
| { | ||||
|   MetaOutputKms *output_kms; | ||||
|   unsigned i; | ||||
|  | ||||
|   output_kms = output->driver_private; | ||||
|  | ||||
|   for (i = 0; i < output_kms->n_encoders; i++) | ||||
|     drmModeFreeEncoder (output_kms->encoders[i]); | ||||
|   g_free (output_kms->encoders); | ||||
|  | ||||
|   g_slice_free (MetaOutputKms, output_kms); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_monitor_mode_destroy_notify (MetaMonitorMode *output) | ||||
| { | ||||
|   g_slice_free (drmModeModeInfo, output->driver_private); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| drm_mode_equal (gconstpointer one, | ||||
|                 gconstpointer two) | ||||
| { | ||||
|   const drmModeModeInfo *m_one = one; | ||||
|   const drmModeModeInfo *m_two = two; | ||||
|  | ||||
|   return m_one->clock == m_two->clock && | ||||
|     m_one->hdisplay == m_two->hdisplay && | ||||
|     m_one->hsync_start == m_two->hsync_start && | ||||
|     m_one->hsync_end == m_two->hsync_end && | ||||
|     m_one->htotal == m_two->htotal && | ||||
|     m_one->hskew == m_two->hskew && | ||||
|     m_one->vdisplay == m_two->vdisplay && | ||||
|     m_one->vsync_start == m_two->vsync_start && | ||||
|     m_one->vsync_end == m_two->vsync_end && | ||||
|     m_one->vtotal == m_two->vtotal && | ||||
|     m_one->vscan == m_two->vscan && | ||||
|     m_one->vrefresh == m_two->vrefresh && | ||||
|     m_one->flags == m_two->flags && | ||||
|     m_one->type == m_two->type && | ||||
|     strncmp (m_one->name, m_two->name, DRM_DISPLAY_MODE_LEN) == 0; | ||||
| } | ||||
|  | ||||
| static guint | ||||
| drm_mode_hash (gconstpointer ptr) | ||||
| { | ||||
|   const drmModeModeInfo *mode = ptr; | ||||
|   guint hash = 0; | ||||
|  | ||||
|   /* We don't include the name in the hash because it's generally | ||||
|      derived from the other fields (hdisplay, vdisplay and flags) | ||||
|   */ | ||||
|  | ||||
|   hash ^= mode->clock; | ||||
|   hash ^= mode->hdisplay ^ mode->hsync_start ^ mode->hsync_end; | ||||
|   hash ^= mode->vdisplay ^ mode->vsync_start ^ mode->vsync_end; | ||||
|   hash ^= mode->vrefresh; | ||||
|   hash ^= mode->flags ^ mode->type; | ||||
|  | ||||
|   return hash; | ||||
| } | ||||
|  | ||||
| static void | ||||
| find_properties (MetaMonitorManagerKms *manager_kms, | ||||
|                  MetaOutputKms         *output_kms) | ||||
| { | ||||
|   drmModePropertyPtr prop; | ||||
|   int i; | ||||
|  | ||||
|   for (i = 0; i < output_kms->connector->count_props; i++) | ||||
|     { | ||||
|       prop = drmModeGetProperty (manager_kms->fd, output_kms->connector->props[i]); | ||||
|       if (!prop) | ||||
|         continue; | ||||
|  | ||||
|       if ((prop->flags & DRM_MODE_PROP_ENUM) && | ||||
|           strcmp(prop->name, "DPMS") == 0) | ||||
|         output_kms->dpms_prop_id = prop->prop_id; | ||||
|       else if ((prop->flags & DRM_MODE_PROP_BLOB) && | ||||
|                strcmp (prop->name, "EDID") == 0) | ||||
|         output_kms->edid_blob_id = output_kms->connector->prop_values[i]; | ||||
|  | ||||
|       drmModeFreeProperty(prop); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static GBytes * | ||||
| read_output_edid (MetaMonitorManagerKms *manager_kms, | ||||
|                   MetaOutput            *output) | ||||
| { | ||||
|   MetaOutputKms *output_kms = output->driver_private; | ||||
|   drmModePropertyBlobPtr edid_blob = NULL; | ||||
|  | ||||
|   if (output_kms->edid_blob_id == 0) | ||||
|     return NULL; | ||||
|  | ||||
|   edid_blob = drmModeGetPropertyBlob (manager_kms->fd, output_kms->edid_blob_id); | ||||
|   if (!edid_blob) | ||||
|     { | ||||
|       meta_warning ("Failed to read EDID of output %s: %s\n", output->name, strerror(errno)); | ||||
|       return NULL; | ||||
|     } | ||||
|  | ||||
|   if (edid_blob->length > 0) | ||||
|     return g_bytes_new_with_free_func (edid_blob->data, edid_blob->length, | ||||
|                                        (GDestroyNotify)drmModeFreePropertyBlob, edid_blob); | ||||
|   else | ||||
|     { | ||||
|       drmModeFreePropertyBlob (edid_blob); | ||||
|       return NULL; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static MetaMonitorMode * | ||||
| find_meta_mode (MetaMonitorManager    *manager, | ||||
|                 const drmModeModeInfo *drm_mode) | ||||
| { | ||||
|   unsigned k; | ||||
|  | ||||
|   for (k = 0; k < manager->n_modes; k++) | ||||
|     { | ||||
|       if (drm_mode_equal (drm_mode, manager->modes[k].driver_private)) | ||||
|         return &manager->modes[k]; | ||||
|     } | ||||
|  | ||||
|   g_assert_not_reached (); | ||||
|   return NULL; | ||||
| } | ||||
|  | ||||
| static MetaOutput * | ||||
| find_output_by_id (MetaOutput *outputs, | ||||
|                    unsigned    n_outputs, | ||||
|                    glong       id) | ||||
| { | ||||
|   unsigned i; | ||||
|  | ||||
|   for (i = 0; i < n_outputs; i++) | ||||
|     if (outputs[i].output_id == id) | ||||
|       return &outputs[i]; | ||||
|  | ||||
|   return NULL; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_monitor_manager_kms_read_current (MetaMonitorManager *manager) | ||||
| { | ||||
|   MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager); | ||||
|   drmModeRes *resources; | ||||
|   GHashTable *modes; | ||||
|   GHashTableIter iter; | ||||
|   drmModeModeInfo *mode; | ||||
|   unsigned int i, j, k; | ||||
|   unsigned int n_actual_outputs; | ||||
|   int width, height; | ||||
|   MetaOutput *old_outputs; | ||||
|   unsigned int n_old_outputs; | ||||
|  | ||||
|   resources = drmModeGetResources(manager_kms->fd); | ||||
|   modes = g_hash_table_new (drm_mode_hash, drm_mode_equal); | ||||
|  | ||||
|   manager->max_screen_width = resources->max_width; | ||||
|   manager->max_screen_height = resources->max_height; | ||||
|  | ||||
|   manager->power_save_mode = META_POWER_SAVE_ON; | ||||
|  | ||||
|   old_outputs = manager->outputs; | ||||
|   n_old_outputs = manager->n_outputs; | ||||
|  | ||||
|   /* Note: we must not free the public structures (output, crtc, monitor | ||||
|      mode and monitor info) here, they must be kept alive until the API | ||||
|      users are done with them after we emit monitors-changed, and thus | ||||
|      are freed by the platform-independent layer. */ | ||||
|   free_resources (manager_kms); | ||||
|  | ||||
|   manager_kms->n_connectors = resources->count_connectors; | ||||
|   manager_kms->connectors = g_new (drmModeConnector *, manager_kms->n_connectors); | ||||
|   for (i = 0; i < manager_kms->n_connectors; i++) | ||||
|     { | ||||
|       drmModeConnector *connector; | ||||
|  | ||||
|       connector = drmModeGetConnector (manager_kms->fd, resources->connectors[i]); | ||||
|       manager_kms->connectors[i] = connector; | ||||
|  | ||||
|       if (connector->connection == DRM_MODE_CONNECTED) | ||||
|         { | ||||
|           /* Collect all modes for this connector */ | ||||
|           for (j = 0; j < (unsigned)connector->count_modes; j++) | ||||
|             g_hash_table_add (modes, &connector->modes[j]); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   manager_kms->n_encoders = resources->count_encoders; | ||||
|   manager_kms->encoders = g_new (drmModeEncoder *, manager_kms->n_encoders); | ||||
|   for (i = 0; i < manager_kms->n_encoders; i++) | ||||
|     { | ||||
|       manager_kms->encoders[i] = drmModeGetEncoder (manager_kms->fd, | ||||
|                                                     resources->encoders[i]); | ||||
|     } | ||||
|  | ||||
|   manager->n_modes = g_hash_table_size (modes); | ||||
|   manager->modes = g_new0 (MetaMonitorMode, manager->n_modes); | ||||
|   g_hash_table_iter_init (&iter, modes); | ||||
|   i = 0; | ||||
|   while (g_hash_table_iter_next (&iter, NULL, (gpointer)&mode)) | ||||
|     { | ||||
|       MetaMonitorMode *meta_mode; | ||||
|  | ||||
|       meta_mode = &manager->modes[i]; | ||||
|  | ||||
|       meta_mode->mode_id = i; | ||||
|       meta_mode->name = g_strndup (mode->name, DRM_DISPLAY_MODE_LEN); | ||||
|       meta_mode->width = mode->hdisplay; | ||||
|       meta_mode->height = mode->vdisplay; | ||||
|       meta_mode->refresh_rate = (1000 * mode->clock / | ||||
|                                  ((float)mode->htotal * mode->vtotal)); | ||||
|  | ||||
|       meta_mode->driver_private = g_slice_dup (drmModeModeInfo, mode); | ||||
|       meta_mode->driver_notify = (GDestroyNotify)meta_monitor_mode_destroy_notify; | ||||
|  | ||||
|       i++; | ||||
|     } | ||||
|   g_hash_table_destroy (modes); | ||||
|  | ||||
|   manager->n_crtcs = resources->count_crtcs; | ||||
|   manager->crtcs = g_new0 (MetaCRTC, manager->n_crtcs); | ||||
|   width = 0; height = 0; | ||||
|   for (i = 0; i < (unsigned)resources->count_crtcs; i++) | ||||
|     { | ||||
|       drmModeCrtc *crtc; | ||||
|       MetaCRTC *meta_crtc; | ||||
|  | ||||
|       crtc = drmModeGetCrtc (manager_kms->fd, resources->crtcs[i]); | ||||
|  | ||||
|       meta_crtc = &manager->crtcs[i]; | ||||
|  | ||||
|       meta_crtc->crtc_id = crtc->crtc_id; | ||||
|       meta_crtc->rect.x = crtc->x; | ||||
|       meta_crtc->rect.y = crtc->y; | ||||
|       meta_crtc->rect.width = crtc->width; | ||||
|       meta_crtc->rect.height = crtc->height; | ||||
|       meta_crtc->is_dirty = FALSE; | ||||
|       meta_crtc->transform = WL_OUTPUT_TRANSFORM_NORMAL; | ||||
|       /* FIXME: implement! */ | ||||
|       meta_crtc->all_transforms = 1 << WL_OUTPUT_TRANSFORM_NORMAL; | ||||
|  | ||||
|       if (crtc->mode_valid) | ||||
|         { | ||||
|           for (j = 0; j < manager->n_modes; j++) | ||||
|             { | ||||
|               if (drm_mode_equal (&crtc->mode, manager->modes[j].driver_private)) | ||||
|                 { | ||||
|                   meta_crtc->current_mode = &manager->modes[j]; | ||||
|                   break; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|           width = MAX (width, meta_crtc->rect.x + meta_crtc->rect.width); | ||||
|           height = MAX (height, meta_crtc->rect.y + meta_crtc->rect.height); | ||||
|         } | ||||
|  | ||||
|       drmModeFreeCrtc (crtc); | ||||
|     } | ||||
|  | ||||
|   manager->screen_width = width; | ||||
|   manager->screen_height = height; | ||||
|  | ||||
|   manager->outputs = g_new0 (MetaOutput, manager_kms->n_connectors); | ||||
|   n_actual_outputs = 0; | ||||
|  | ||||
|   for (i = 0; i < manager_kms->n_connectors; i++) | ||||
|     { | ||||
|       MetaOutput *meta_output, *old_output; | ||||
|       MetaOutputKms *output_kms; | ||||
|       drmModeConnector *connector; | ||||
|       GArray *crtcs; | ||||
|       unsigned int crtc_mask; | ||||
|       GBytes *edid; | ||||
|  | ||||
|       connector = manager_kms->connectors[i]; | ||||
|       meta_output = &manager->outputs[n_actual_outputs]; | ||||
|  | ||||
|       if (connector->connection == DRM_MODE_CONNECTED) | ||||
| 	{ | ||||
|           meta_output->driver_private = output_kms = g_slice_new0 (MetaOutputKms); | ||||
|           meta_output->driver_notify = (GDestroyNotify)meta_output_destroy_notify; | ||||
|  | ||||
| 	  meta_output->output_id = connector->connector_id; | ||||
| 	  meta_output->name = make_output_name (connector); | ||||
| 	  meta_output->width_mm = connector->mmWidth; | ||||
| 	  meta_output->height_mm = connector->mmHeight; | ||||
|  | ||||
|           switch (connector->subpixel) | ||||
|             { | ||||
|             case DRM_MODE_SUBPIXEL_NONE: | ||||
|               meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_NONE; | ||||
|               break; | ||||
|             case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB: | ||||
|               meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_HORIZONTAL_RGB; | ||||
|               break; | ||||
|             case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR: | ||||
|               meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_HORIZONTAL_BGR; | ||||
|               break; | ||||
|             case DRM_MODE_SUBPIXEL_VERTICAL_RGB: | ||||
|               meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_VERTICAL_RGB; | ||||
|               break; | ||||
|             case DRM_MODE_SUBPIXEL_VERTICAL_BGR: | ||||
|               meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_VERTICAL_BGR; | ||||
|               break; | ||||
|             case DRM_MODE_SUBPIXEL_UNKNOWN: | ||||
|             default: | ||||
|               meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN; | ||||
|               break; | ||||
|             } | ||||
|  | ||||
| 	  meta_output->n_modes = connector->count_modes; | ||||
| 	  meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes); | ||||
| 	  for (j = 0; j < meta_output->n_modes; j++) | ||||
|             meta_output->modes[j] = find_meta_mode (manager, &connector->modes[j]); | ||||
| 	  meta_output->preferred_mode = meta_output->modes[0]; | ||||
|  | ||||
|           output_kms->connector = connector; | ||||
|           output_kms->n_encoders = connector->count_encoders; | ||||
|           output_kms->encoders = g_new0 (drmModeEncoderPtr, output_kms->n_encoders); | ||||
|  | ||||
|           crtc_mask = ~(unsigned int)0; | ||||
| 	  for (j = 0; j < output_kms->n_encoders; j++) | ||||
| 	    { | ||||
|               output_kms->encoders[j] = drmModeGetEncoder (manager_kms->fd, connector->encoders[j]); | ||||
|  | ||||
|               /* We only list CRTCs as supported if they are supported by all encoders | ||||
|                  for this connectors. | ||||
|  | ||||
|                  This is what xf86-video-modesetting does (see drmmode_output_init()) | ||||
|               */ | ||||
|               crtc_mask &= output_kms->encoders[j]->possible_crtcs; | ||||
|  | ||||
|               if (output_kms->encoders[j]->encoder_id == connector->encoder_id) | ||||
|                 output_kms->current_encoder = output_kms->encoders[j]; | ||||
|             } | ||||
|  | ||||
|           crtcs = g_array_new (FALSE, FALSE, sizeof (MetaCRTC*)); | ||||
|  | ||||
|           for (j = 0; j < manager->n_crtcs; j++) | ||||
|             { | ||||
|               if (crtc_mask & (1 << j)) | ||||
|                 { | ||||
|                   MetaCRTC *crtc = &manager->crtcs[j]; | ||||
|                   g_array_append_val (crtcs, crtc); | ||||
| 		} | ||||
| 	    } | ||||
|  | ||||
| 	  meta_output->n_possible_crtcs = crtcs->len; | ||||
| 	  meta_output->possible_crtcs = (void*)g_array_free (crtcs, FALSE); | ||||
|  | ||||
|           if (output_kms->current_encoder && output_kms->current_encoder->crtc_id != 0) | ||||
|             { | ||||
|               for (j = 0; j < manager->n_crtcs; j++) | ||||
|                 { | ||||
|                   if (manager->crtcs[j].crtc_id == output_kms->current_encoder->crtc_id) | ||||
|                     { | ||||
|                       meta_output->crtc = &manager->crtcs[j]; | ||||
|                       break; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|           else | ||||
|             meta_output->crtc = NULL; | ||||
|  | ||||
|           old_output = find_output_by_id (old_outputs, n_old_outputs, | ||||
|                                           meta_output->output_id); | ||||
|           if (old_output) | ||||
|             { | ||||
|               meta_output->is_primary = old_output->is_primary; | ||||
|               meta_output->is_presentation = old_output->is_presentation; | ||||
|             } | ||||
|           else | ||||
|             { | ||||
|               meta_output->is_primary = FALSE; | ||||
|               meta_output->is_presentation = FALSE; | ||||
|             } | ||||
|  | ||||
|           find_properties (manager_kms, output_kms); | ||||
|  | ||||
|           edid = read_output_edid (manager_kms, meta_output); | ||||
|           if (edid) | ||||
|             { | ||||
|               MonitorInfo *parsed_edid; | ||||
|               gsize len; | ||||
|  | ||||
|               parsed_edid = decode_edid (g_bytes_get_data (edid, &len)); | ||||
|               if (parsed_edid) | ||||
|                 { | ||||
|                   meta_output->vendor = g_strndup (parsed_edid->manufacturer_code, 4); | ||||
|                   meta_output->product = g_strndup (parsed_edid->dsc_product_name, 14); | ||||
|                   meta_output->serial = g_strndup (parsed_edid->dsc_serial_number, 14); | ||||
|  | ||||
|                   g_free (parsed_edid); | ||||
|                 } | ||||
|  | ||||
|               g_bytes_unref (edid); | ||||
|             } | ||||
|           if (!meta_output->vendor) | ||||
|             { | ||||
|               meta_output->vendor = g_strdup ("unknown"); | ||||
|               meta_output->product = g_strdup ("unknown"); | ||||
|               meta_output->serial = g_strdup ("unknown"); | ||||
|             } | ||||
|  | ||||
|           /* FIXME: backlight is a very driver specific thing unfortunately, | ||||
|              every DDX does its own thing, and the dumb KMS API does not include it. | ||||
|  | ||||
|              For example, xf86-video-intel has a list of paths to probe in /sys/class/backlight | ||||
|              (one for each major HW maker, and then some). | ||||
|              We can't do the same because we're not root. | ||||
|              It might be best to leave backlight out of the story and rely on the setuid | ||||
|              helper in gnome-settings-daemon. | ||||
|           */ | ||||
| 	  meta_output->backlight_min = 0; | ||||
|           meta_output->backlight_max = 0; | ||||
|           meta_output->backlight = -1; | ||||
|  | ||||
| 	  n_actual_outputs++; | ||||
| 	} | ||||
|     } | ||||
|  | ||||
|   manager->n_outputs = n_actual_outputs; | ||||
|   manager->outputs = g_renew (MetaOutput, manager->outputs, manager->n_outputs); | ||||
|  | ||||
|   /* Sort the outputs for easier handling in MetaMonitorConfig */ | ||||
|   qsort (manager->outputs, manager->n_outputs, sizeof (MetaOutput), compare_outputs); | ||||
|  | ||||
|   /* Now fix the clones. | ||||
|      Code mostly inspired by xf86-video-modesetting. */ | ||||
|  | ||||
|   /* XXX: intel hardware doesn't usually have clones, but I only have laptops with | ||||
|      intel cards, so this code was never tested! */ | ||||
|   for (i = 0; i < manager->n_outputs; i++) | ||||
|     { | ||||
|       MetaOutput *meta_output; | ||||
|       MetaOutputKms *output_kms; | ||||
|  | ||||
|       meta_output = &manager->outputs[i]; | ||||
|       output_kms = meta_output->driver_private; | ||||
|  | ||||
|       output_kms->enc_clone_mask = 0xff; | ||||
|       output_kms->encoder_mask = 0; | ||||
|  | ||||
|       for (j = 0; j < output_kms->n_encoders; j++) | ||||
| 	{ | ||||
| 	  for (k = 0; k < manager_kms->n_encoders; k++) | ||||
| 	    { | ||||
| 	      if (output_kms->encoders[j]->encoder_id == manager_kms->encoders[k]->encoder_id) | ||||
| 		{ | ||||
|                   output_kms->encoder_mask |= (1 << k); | ||||
| 		  break; | ||||
| 		} | ||||
| 	    } | ||||
|  | ||||
|           output_kms->enc_clone_mask &= output_kms->encoders[j]->possible_clones; | ||||
| 	} | ||||
|     } | ||||
|  | ||||
|   for (i = 0; i < manager->n_outputs; i++) | ||||
|     { | ||||
|       MetaOutput *meta_output; | ||||
|       MetaOutputKms *output_kms; | ||||
|  | ||||
|       meta_output = &manager->outputs[i]; | ||||
|       output_kms = meta_output->driver_private; | ||||
|  | ||||
|       if (output_kms->enc_clone_mask == 0) | ||||
|         continue; | ||||
|  | ||||
|       for (j = 0; j < manager->n_outputs; j++) | ||||
|         { | ||||
|           MetaOutput *meta_clone; | ||||
|           MetaOutputKms *clone_kms; | ||||
|  | ||||
|           meta_clone = &manager->outputs[i]; | ||||
|           clone_kms = meta_clone->driver_private; | ||||
|  | ||||
|           if (meta_clone == meta_output) | ||||
|             continue; | ||||
|  | ||||
|           if (clone_kms->encoder_mask == 0) | ||||
|             continue; | ||||
|  | ||||
|           if (clone_kms->encoder_mask == output_kms->enc_clone_mask) | ||||
|             { | ||||
|               meta_output->n_possible_clones++; | ||||
|               meta_output->possible_clones = g_renew (MetaOutput *, | ||||
|                                                       meta_output->possible_clones, | ||||
|                                                       meta_output->n_possible_clones); | ||||
|               meta_output->possible_clones[meta_output->n_possible_clones - 1] = meta_clone; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   drmModeFreeResources (resources); | ||||
| } | ||||
|  | ||||
| static GBytes * | ||||
| meta_monitor_manager_kms_read_edid (MetaMonitorManager *manager, | ||||
|                                     MetaOutput         *output) | ||||
| { | ||||
|   MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager); | ||||
|  | ||||
|   return read_output_edid (manager_kms, output); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager, | ||||
|                                               MetaPowerSave       mode) | ||||
| { | ||||
|   MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager); | ||||
|   uint64_t state; | ||||
|   unsigned i; | ||||
|  | ||||
|   switch (mode) { | ||||
|   case META_POWER_SAVE_ON: | ||||
|     state = DRM_MODE_DPMS_ON; | ||||
|     break; | ||||
|   case META_POWER_SAVE_STANDBY: | ||||
|     state = DRM_MODE_DPMS_STANDBY; | ||||
|     break; | ||||
|   case META_POWER_SAVE_SUSPEND: | ||||
|     state = DRM_MODE_DPMS_SUSPEND; | ||||
|     break; | ||||
|   case META_POWER_SAVE_OFF: | ||||
|     state = DRM_MODE_DPMS_OFF; | ||||
|     break; | ||||
|   default: | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   for (i = 0; i < manager->n_outputs; i++) | ||||
|     { | ||||
|       MetaOutput *meta_output; | ||||
|       MetaOutputKms *output_kms; | ||||
|  | ||||
|       meta_output = &manager->outputs[i]; | ||||
|       output_kms = meta_output->driver_private; | ||||
|  | ||||
|       if (output_kms->dpms_prop_id != 0) | ||||
|         { | ||||
|           int ok = drmModeConnectorSetProperty(manager_kms->fd, meta_output->output_id, | ||||
|                                                output_kms->dpms_prop_id, state); | ||||
|  | ||||
|           if (ok < 0) | ||||
|             meta_warning ("Failed to set power save mode for output %s: %s\n", | ||||
|                           meta_output->name, strerror (errno)); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| crtc_free (CoglKmsCrtc *crtc) | ||||
| { | ||||
|   g_free (crtc->connectors); | ||||
|   g_slice_free (CoglKmsCrtc, crtc); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager, | ||||
|                                               MetaCRTCInfo       **crtcs, | ||||
|                                               unsigned int         n_crtcs, | ||||
|                                               MetaOutputInfo     **outputs, | ||||
|                                               unsigned int         n_outputs) | ||||
| { | ||||
|   ClutterBackend *backend; | ||||
|   CoglContext *cogl_context; | ||||
|   CoglDisplay *cogl_display; | ||||
|   unsigned i; | ||||
|   GPtrArray *cogl_crtcs; | ||||
|   int screen_width, screen_height; | ||||
|   gboolean ok; | ||||
|   GError *error; | ||||
|  | ||||
|   cogl_crtcs = g_ptr_array_new_full (manager->n_crtcs, (GDestroyNotify)crtc_free); | ||||
|   screen_width = 0; screen_height = 0; | ||||
|   for (i = 0; i < n_crtcs; i++) | ||||
|     { | ||||
|       MetaCRTCInfo *crtc_info = crtcs[i]; | ||||
|       MetaCRTC *crtc = crtc_info->crtc; | ||||
|       CoglKmsCrtc *cogl_crtc; | ||||
|  | ||||
|       crtc->is_dirty = TRUE; | ||||
|  | ||||
|       cogl_crtc = g_slice_new0 (CoglKmsCrtc); | ||||
|       g_ptr_array_add (cogl_crtcs, cogl_crtc); | ||||
|  | ||||
|       if (crtc_info->mode == NULL) | ||||
|         { | ||||
|           cogl_crtc->id = crtc->crtc_id; | ||||
|           cogl_crtc->x = 0; | ||||
|           cogl_crtc->y = 0; | ||||
|           cogl_crtc->count = 0; | ||||
|           memset (&cogl_crtc->mode, 0, sizeof (drmModeModeInfo)); | ||||
|           cogl_crtc->connectors = NULL; | ||||
|           cogl_crtc->count = 0; | ||||
|  | ||||
|           crtc->rect.x = 0; | ||||
|           crtc->rect.y = 0; | ||||
|           crtc->rect.width = 0; | ||||
|           crtc->rect.height = 0; | ||||
|           crtc->current_mode = NULL; | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           MetaMonitorMode *mode; | ||||
|           uint32_t *connectors; | ||||
|           unsigned int j, n_connectors; | ||||
|           int width, height; | ||||
|  | ||||
|           mode = crtc_info->mode; | ||||
|  | ||||
|           cogl_crtc->id = crtc->crtc_id; | ||||
|           cogl_crtc->x = crtc_info->x; | ||||
|           cogl_crtc->y = crtc_info->y; | ||||
|           cogl_crtc->count = n_connectors = crtc_info->outputs->len; | ||||
|           cogl_crtc->connectors = connectors = g_new (uint32_t, n_connectors); | ||||
|  | ||||
|           for (j = 0; j < n_connectors; j++) | ||||
|             { | ||||
|               MetaOutput *output = g_ptr_array_index (crtc_info->outputs, j); | ||||
|  | ||||
|               connectors[j] = output->output_id; | ||||
|  | ||||
|               output->is_dirty = TRUE; | ||||
|               output->crtc = crtc; | ||||
|             } | ||||
|  | ||||
|           memcpy (&cogl_crtc->mode, crtc_info->mode->driver_private, | ||||
|                   sizeof (drmModeModeInfo)); | ||||
|  | ||||
|           if (meta_monitor_transform_is_rotated (crtc_info->transform)) | ||||
|             { | ||||
|               width = mode->height; | ||||
|               height = mode->width; | ||||
|             } | ||||
|           else | ||||
|             { | ||||
|               width = mode->width; | ||||
|               height = mode->height; | ||||
|             } | ||||
|  | ||||
|           screen_width = MAX (screen_width, crtc_info->x + width); | ||||
|           screen_height = MAX (screen_height, crtc_info->y + height); | ||||
|  | ||||
|           crtc->rect.x = crtc_info->x; | ||||
|           crtc->rect.y = crtc_info->y; | ||||
|           crtc->rect.width = width; | ||||
|           crtc->rect.height = height; | ||||
|           crtc->current_mode = mode; | ||||
|           crtc->transform = crtc_info->transform; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   /* Disable CRTCs not mentioned in the list (they have is_dirty == FALSE, | ||||
|      because they weren't seen in the first loop) */ | ||||
|   for (i = 0; i < manager->n_crtcs; i++) | ||||
|     { | ||||
|       MetaCRTC *crtc = &manager->crtcs[i]; | ||||
|       CoglKmsCrtc *cogl_crtc; | ||||
|  | ||||
|       crtc->logical_monitor = NULL; | ||||
|  | ||||
|       if (crtc->is_dirty) | ||||
|         { | ||||
|           crtc->is_dirty = FALSE; | ||||
|           continue; | ||||
|         } | ||||
|  | ||||
|       cogl_crtc = g_slice_new0 (CoglKmsCrtc); | ||||
|       g_ptr_array_add (cogl_crtcs, cogl_crtc); | ||||
|  | ||||
|       cogl_crtc->id = crtc->crtc_id; | ||||
|       cogl_crtc->x = 0; | ||||
|       cogl_crtc->y = 0; | ||||
|       cogl_crtc->count = 0; | ||||
|       memset (&cogl_crtc->mode, 0, sizeof (drmModeModeInfo)); | ||||
|       cogl_crtc->connectors = NULL; | ||||
|       cogl_crtc->count = 0; | ||||
|  | ||||
|       crtc->rect.x = 0; | ||||
|       crtc->rect.y = 0; | ||||
|       crtc->rect.width = 0; | ||||
|       crtc->rect.height = 0; | ||||
|       crtc->current_mode = NULL; | ||||
|     } | ||||
|  | ||||
|   backend = clutter_get_default_backend (); | ||||
|   cogl_context = clutter_backend_get_cogl_context (backend); | ||||
|   cogl_display = cogl_context_get_display (cogl_context); | ||||
|  | ||||
|   error = NULL; | ||||
|   ok = cogl_kms_display_set_layout (cogl_display, screen_width, screen_height, | ||||
|                                     (CoglKmsCrtc**)cogl_crtcs->pdata, cogl_crtcs->len, &error); | ||||
|   g_ptr_array_unref (cogl_crtcs); | ||||
|  | ||||
|   if (!ok) | ||||
|     { | ||||
|       meta_warning ("Applying display configuration failed: %s\n", error->message); | ||||
|       g_error_free (error); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   for (i = 0; i < n_outputs; i++) | ||||
|     { | ||||
|       MetaOutputInfo *output_info = outputs[i]; | ||||
|       MetaOutput *output = output_info->output; | ||||
|  | ||||
|       output->is_primary = output_info->is_primary; | ||||
|       output->is_presentation = output_info->is_presentation; | ||||
|     } | ||||
|  | ||||
|   /* Disable outputs not mentioned in the list */ | ||||
|   for (i = 0; i < manager->n_outputs; i++) | ||||
|     { | ||||
|       MetaOutput *output = &manager->outputs[i]; | ||||
|  | ||||
|       if (output->is_dirty) | ||||
|         { | ||||
|           output->is_dirty = FALSE; | ||||
|           continue; | ||||
|         } | ||||
|  | ||||
|       output->crtc = NULL; | ||||
|       output->is_primary = FALSE; | ||||
|     } | ||||
|  | ||||
|   manager->screen_width = screen_width; | ||||
|   manager->screen_height = screen_height; | ||||
|  | ||||
|   meta_monitor_manager_rebuild_derived (manager); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_monitor_manager_kms_get_crtc_gamma (MetaMonitorManager  *manager, | ||||
|                                          MetaCRTC            *crtc, | ||||
|                                          gsize               *size, | ||||
|                                          unsigned short     **red, | ||||
|                                          unsigned short     **green, | ||||
|                                          unsigned short     **blue) | ||||
| { | ||||
|   MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager); | ||||
|   drmModeCrtc *kms_crtc; | ||||
|  | ||||
|   kms_crtc = drmModeGetCrtc (manager_kms->fd, crtc->crtc_id); | ||||
|  | ||||
|   *size = kms_crtc->gamma_size; | ||||
|   *red = g_new (unsigned short, *size); | ||||
|   *green = g_new (unsigned short, *size); | ||||
|   *blue = g_new (unsigned short, *size); | ||||
|  | ||||
|   drmModeCrtcGetGamma (manager_kms->fd, crtc->crtc_id, *size, *red, *green, *blue); | ||||
|  | ||||
|   drmModeFreeCrtc (kms_crtc); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_monitor_manager_kms_set_crtc_gamma (MetaMonitorManager *manager, | ||||
|                                          MetaCRTC           *crtc, | ||||
|                                          gsize               size, | ||||
|                                          unsigned short     *red, | ||||
|                                          unsigned short     *green, | ||||
|                                          unsigned short     *blue) | ||||
| { | ||||
|   MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager); | ||||
|  | ||||
|   drmModeCrtcSetGamma (manager_kms->fd, crtc->crtc_id, size, red, green, blue); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_monitor_manager_kms_init (MetaMonitorManagerKms *manager_kms) | ||||
| { | ||||
|   ClutterBackend *backend; | ||||
|   CoglContext *cogl_context; | ||||
|   CoglDisplay *cogl_display; | ||||
|   CoglRenderer *cogl_renderer; | ||||
|  | ||||
|   backend = clutter_get_default_backend (); | ||||
|   cogl_context = clutter_backend_get_cogl_context (backend); | ||||
|   cogl_display = cogl_context_get_display (cogl_context); | ||||
|   cogl_renderer = cogl_display_get_renderer (cogl_display); | ||||
|  | ||||
|   manager_kms->fd = cogl_kms_renderer_get_kms_fd (cogl_renderer); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_monitor_manager_kms_finalize (GObject *object) | ||||
| { | ||||
|   MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (object); | ||||
|  | ||||
|   free_resources (manager_kms); | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_monitor_manager_kms_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_monitor_manager_kms_class_init (MetaMonitorManagerKmsClass *klass) | ||||
| { | ||||
|   MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass); | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|  | ||||
|   object_class->finalize = meta_monitor_manager_kms_finalize; | ||||
|  | ||||
|   manager_class->read_current = meta_monitor_manager_kms_read_current; | ||||
|   manager_class->read_edid = meta_monitor_manager_kms_read_edid; | ||||
|   manager_class->apply_configuration = meta_monitor_manager_kms_apply_configuration; | ||||
|   manager_class->set_power_save_mode = meta_monitor_manager_kms_set_power_save_mode; | ||||
|   manager_class->get_crtc_gamma = meta_monitor_manager_kms_get_crtc_gamma; | ||||
|   manager_class->set_crtc_gamma = meta_monitor_manager_kms_set_crtc_gamma; | ||||
| } | ||||
|  | ||||
| @@ -1,40 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2001 Havoc Pennington | ||||
|  * Copyright (C) 2003 Rob Adams | ||||
|  * Copyright (C) 2004-2006 Elijah Newren | ||||
|  * Copyright (C) 2013 Red Hat Inc. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef META_MONITOR_MANAGER_KMS_H | ||||
| #define META_MONITOR_MANAGER_KMS_H | ||||
|  | ||||
| #include "meta-monitor-manager.h" | ||||
|  | ||||
| #define META_TYPE_MONITOR_MANAGER_KMS            (meta_monitor_manager_kms_get_type ()) | ||||
| #define META_MONITOR_MANAGER_KMS(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKms)) | ||||
| #define META_MONITOR_MANAGER_KMS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKmsClass)) | ||||
| #define META_IS_MONITOR_MANAGER_KMS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_MANAGER_KMS)) | ||||
| #define META_IS_MONITOR_MANAGER_KMS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_MONITOR_MANAGER_KMS)) | ||||
| #define META_MONITOR_MANAGER_KMS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKmsClass)) | ||||
|  | ||||
| typedef struct _MetaMonitorManagerKmsClass    MetaMonitorManagerKmsClass; | ||||
| typedef struct _MetaMonitorManagerKms         MetaMonitorManagerKms; | ||||
|  | ||||
| GType meta_monitor_manager_kms_get_type (void); | ||||
|  | ||||
| #endif /* META_MONITOR_MANAGER_KMS_H */ | ||||
| @@ -1,406 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2014 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Jasper St. Pierre <jstpierre@mecheye.net> | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include "meta-backend-x11.h" | ||||
|  | ||||
| #include <clutter/x11/clutter-x11.h> | ||||
|  | ||||
| #include <X11/extensions/sync.h> | ||||
|  | ||||
| #include "meta-idle-monitor-xsync.h" | ||||
| #include "meta-monitor-manager-xrandr.h" | ||||
| #include "backends/meta-monitor-manager-dummy.h" | ||||
| #include "meta-cursor-renderer-x11.h" | ||||
|  | ||||
| #include <meta/util.h> | ||||
| #include "display-private.h" | ||||
| #include "compositor/compositor-private.h" | ||||
|  | ||||
| struct _MetaBackendX11Private | ||||
| { | ||||
|   /* The host X11 display */ | ||||
|   Display *xdisplay; | ||||
|   GSource *source; | ||||
|  | ||||
|   int xsync_event_base; | ||||
|   int xsync_error_base; | ||||
|  | ||||
|   int xinput_opcode; | ||||
|   int xinput_event_base; | ||||
|   int xinput_error_base; | ||||
| }; | ||||
| typedef struct _MetaBackendX11Private MetaBackendX11Private; | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_PRIVATE (MetaBackendX11, meta_backend_x11, META_TYPE_BACKEND); | ||||
|  | ||||
| static void | ||||
| handle_alarm_notify (MetaBackend *backend, | ||||
|                      XEvent      *event) | ||||
| { | ||||
|   int i; | ||||
|  | ||||
|   for (i = 0; i <= backend->device_id_max; i++) | ||||
|     if (backend->device_monitors[i]) | ||||
|       meta_idle_monitor_xsync_handle_xevent (backend->device_monitors[i], (XSyncAlarmNotifyEvent*) event); | ||||
| } | ||||
|  | ||||
| static void | ||||
| translate_device_event (MetaBackendX11 *x11, | ||||
|                         XIDeviceEvent  *device_event) | ||||
| { | ||||
|   Window stage_window = meta_backend_x11_get_xwindow (x11); | ||||
|  | ||||
|   if (device_event->event != stage_window) | ||||
|     { | ||||
|       /* This codepath should only ever trigger as an X11 compositor, | ||||
|        * and never under nested, as under nested all backend events | ||||
|        * should be reported with respect to the stage window. */ | ||||
|       g_assert (!meta_is_wayland_compositor ()); | ||||
|  | ||||
|       device_event->event = stage_window; | ||||
|  | ||||
|       /* As an X11 compositor, the stage window is always at 0,0, so | ||||
|        * using root coordinates will give us correct stage coordinates | ||||
|        * as well... */ | ||||
|       device_event->event_x = device_event->root_x; | ||||
|       device_event->event_y = device_event->root_y; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* 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 | ||||
|  * to the a stage that isn't its X window. | ||||
|  * | ||||
|  * When running as an X window manager, we need to respond to | ||||
|  * events from lots of windows. Trick Clutter into translating | ||||
|  * these events by pretending we got an event on the stage window. | ||||
|  */ | ||||
| static void | ||||
| maybe_spoof_event_as_stage_event (MetaBackendX11 *x11, | ||||
|                                   XEvent         *event) | ||||
| { | ||||
|   MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); | ||||
|  | ||||
|   if (event->type == GenericEvent && | ||||
|       event->xcookie.extension == priv->xinput_opcode) | ||||
|     { | ||||
|       XIEvent *input_event = (XIEvent *) event->xcookie.data; | ||||
|  | ||||
|       switch (input_event->evtype) | ||||
|         { | ||||
|         case XI_Motion: | ||||
|         case XI_ButtonPress: | ||||
|         case XI_ButtonRelease: | ||||
|         case XI_KeyPress: | ||||
|         case XI_KeyRelease: | ||||
|           translate_device_event (x11, (XIDeviceEvent *) input_event); | ||||
|           break; | ||||
|         default: | ||||
|           break; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| handle_host_xevent (MetaBackend *backend, | ||||
|                     XEvent      *event) | ||||
| { | ||||
|   MetaBackendX11 *x11 = META_BACKEND_X11 (backend); | ||||
|   MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); | ||||
|   gboolean bypass_clutter = FALSE; | ||||
|  | ||||
|   XGetEventData (priv->xdisplay, &event->xcookie); | ||||
|  | ||||
|   if (event->type == (priv->xsync_event_base + XSyncAlarmNotify)) | ||||
|     handle_alarm_notify (backend, event); | ||||
|  | ||||
|   { | ||||
|     MetaMonitorManager *manager = meta_backend_get_monitor_manager (backend); | ||||
|     if (META_IS_MONITOR_MANAGER_XRANDR (manager) && | ||||
|         meta_monitor_manager_xrandr_handle_xevent (META_MONITOR_MANAGER_XRANDR (manager), event)) | ||||
|       { | ||||
|         bypass_clutter = TRUE; | ||||
|         goto out; | ||||
|       } | ||||
|   } | ||||
|  | ||||
|   maybe_spoof_event_as_stage_event (x11, event); | ||||
|  | ||||
|  out: | ||||
|   if (!bypass_clutter) | ||||
|     clutter_x11_handle_event (event); | ||||
|  | ||||
|   XFreeEventData (priv->xdisplay, &event->xcookie); | ||||
| } | ||||
|  | ||||
| typedef struct { | ||||
|   GSource base; | ||||
|   GPollFD event_poll_fd; | ||||
|   MetaBackend *backend; | ||||
| } XEventSource; | ||||
|  | ||||
| static gboolean | ||||
| x_event_source_prepare (GSource *source, | ||||
|                         int     *timeout) | ||||
| { | ||||
|   XEventSource *x_source = (XEventSource *) source; | ||||
|   MetaBackend *backend = x_source->backend; | ||||
|   MetaBackendX11 *x11 = META_BACKEND_X11 (backend); | ||||
|   MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); | ||||
|  | ||||
|   *timeout = -1; | ||||
|  | ||||
|   return XPending (priv->xdisplay); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| x_event_source_check (GSource *source) | ||||
| { | ||||
|   XEventSource *x_source = (XEventSource *) source; | ||||
|   MetaBackend *backend = x_source->backend; | ||||
|   MetaBackendX11 *x11 = META_BACKEND_X11 (backend); | ||||
|   MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); | ||||
|  | ||||
|   return XPending (priv->xdisplay); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| x_event_source_dispatch (GSource     *source, | ||||
|                          GSourceFunc  callback, | ||||
|                          gpointer     user_data) | ||||
| { | ||||
|   XEventSource *x_source = (XEventSource *) source; | ||||
|   MetaBackend *backend = x_source->backend; | ||||
|   MetaBackendX11 *x11 = META_BACKEND_X11 (backend); | ||||
|   MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); | ||||
|  | ||||
|   while (XPending (priv->xdisplay)) | ||||
|     { | ||||
|       XEvent event; | ||||
|  | ||||
|       XNextEvent (priv->xdisplay, &event); | ||||
|  | ||||
|       handle_host_xevent (backend, &event); | ||||
|     } | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static GSourceFuncs x_event_funcs = { | ||||
|   x_event_source_prepare, | ||||
|   x_event_source_check, | ||||
|   x_event_source_dispatch, | ||||
| }; | ||||
|  | ||||
| static GSource * | ||||
| x_event_source_new (MetaBackend *backend) | ||||
| { | ||||
|   MetaBackendX11 *x11 = META_BACKEND_X11 (backend); | ||||
|   MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); | ||||
|   GSource *source; | ||||
|   XEventSource *x_source; | ||||
|  | ||||
|   source = g_source_new (&x_event_funcs, sizeof (XEventSource)); | ||||
|   x_source = (XEventSource *) source; | ||||
|   x_source->backend = backend; | ||||
|   x_source->event_poll_fd.fd = ConnectionNumber (priv->xdisplay); | ||||
|   x_source->event_poll_fd.events = G_IO_IN; | ||||
|   g_source_add_poll (source, &x_source->event_poll_fd); | ||||
|  | ||||
|   g_source_attach (source, NULL); | ||||
|   return source; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_backend_x11_post_init (MetaBackend *backend) | ||||
| { | ||||
|   MetaBackendX11 *x11 = META_BACKEND_X11 (backend); | ||||
|   MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); | ||||
|   int major, minor; | ||||
|  | ||||
|   priv->xdisplay = clutter_x11_get_default_display (); | ||||
|  | ||||
|   priv->source = x_event_source_new (backend); | ||||
|  | ||||
|   if (!XSyncQueryExtension (priv->xdisplay, &priv->xsync_event_base, &priv->xsync_error_base) || | ||||
|       !XSyncInitialize (priv->xdisplay, &major, &minor)) | ||||
|     meta_fatal ("Could not initialize XSync"); | ||||
|  | ||||
|   { | ||||
|     int major = 2, minor = 3; | ||||
|     gboolean has_xi = FALSE; | ||||
|  | ||||
|     if (XQueryExtension (priv->xdisplay, | ||||
|                          "XInputExtension", | ||||
|                          &priv->xinput_opcode, | ||||
|                          &priv->xinput_error_base, | ||||
|                          &priv->xinput_event_base)) | ||||
|       { | ||||
|         if (XIQueryVersion (priv->xdisplay, &major, &minor) == Success) | ||||
|           { | ||||
|             int version = (major * 10) + minor; | ||||
|             if (version >= 22) | ||||
|               has_xi = TRUE; | ||||
|           } | ||||
|       } | ||||
|  | ||||
|     if (!has_xi) | ||||
|       meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer\n"); | ||||
|   } | ||||
|  | ||||
|   META_BACKEND_CLASS (meta_backend_x11_parent_class)->post_init (backend); | ||||
| } | ||||
|  | ||||
| static MetaIdleMonitor * | ||||
| meta_backend_x11_create_idle_monitor (MetaBackend *backend, | ||||
|                                       int          device_id) | ||||
| { | ||||
|   return g_object_new (META_TYPE_IDLE_MONITOR_XSYNC, | ||||
|                        "device-id", device_id, | ||||
|                        NULL); | ||||
| } | ||||
|  | ||||
| static MetaMonitorManager * | ||||
| meta_backend_x11_create_monitor_manager (MetaBackend *backend) | ||||
| { | ||||
|   /* If we're a Wayland compositor using the X11 backend, | ||||
|    * we're a nested configuration, so return the dummy | ||||
|    * monitor setup. */ | ||||
|   if (meta_is_wayland_compositor ()) | ||||
|     return g_object_new (META_TYPE_MONITOR_MANAGER_DUMMY, NULL); | ||||
|  | ||||
|   return g_object_new (META_TYPE_MONITOR_MANAGER_XRANDR, NULL); | ||||
| } | ||||
|  | ||||
| static MetaCursorRenderer * | ||||
| meta_backend_x11_create_cursor_renderer (MetaBackend *backend) | ||||
| { | ||||
|   return g_object_new (META_TYPE_CURSOR_RENDERER_X11, NULL); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_backend_x11_grab_device (MetaBackend *backend, | ||||
|                               int          device_id, | ||||
|                               uint32_t     timestamp) | ||||
| { | ||||
|   MetaBackendX11 *x11 = META_BACKEND_X11 (backend); | ||||
|   MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); | ||||
|   unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 }; | ||||
|   XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits }; | ||||
|   int ret; | ||||
|  | ||||
|   XISetMask (mask.mask, XI_ButtonPress); | ||||
|   XISetMask (mask.mask, XI_ButtonRelease); | ||||
|   XISetMask (mask.mask, XI_Enter); | ||||
|   XISetMask (mask.mask, XI_Leave); | ||||
|   XISetMask (mask.mask, XI_Motion); | ||||
|   XISetMask (mask.mask, XI_KeyPress); | ||||
|   XISetMask (mask.mask, XI_KeyRelease); | ||||
|  | ||||
|   ret = XIGrabDevice (priv->xdisplay, device_id, | ||||
|                       meta_backend_x11_get_xwindow (x11), | ||||
|                       timestamp, | ||||
|                       None, | ||||
|                       XIGrabModeAsync, XIGrabModeAsync, | ||||
|                       False, /* owner_events */ | ||||
|                       &mask); | ||||
|  | ||||
|   return (ret == Success); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_backend_x11_ungrab_device (MetaBackend *backend, | ||||
|                                 int          device_id, | ||||
|                                 uint32_t     timestamp) | ||||
| { | ||||
|   MetaBackendX11 *x11 = META_BACKEND_X11 (backend); | ||||
|   MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); | ||||
|   int ret; | ||||
|  | ||||
|   ret = XIUngrabDevice (priv->xdisplay, device_id, timestamp); | ||||
|  | ||||
|   return (ret == Success); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_backend_x11_warp_pointer (MetaBackend *backend, | ||||
|                                int          x, | ||||
|                                int          y) | ||||
| { | ||||
|   MetaBackendX11 *x11 = META_BACKEND_X11 (backend); | ||||
|   MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); | ||||
|  | ||||
|   XIWarpPointer (priv->xdisplay, | ||||
|                  META_VIRTUAL_CORE_POINTER_ID, | ||||
|                  None, | ||||
|                  meta_backend_x11_get_xwindow (x11), | ||||
|                  0, 0, 0, 0, | ||||
|                  x, y); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_backend_x11_class_init (MetaBackendX11Class *klass) | ||||
| { | ||||
|   MetaBackendClass *backend_class = META_BACKEND_CLASS (klass); | ||||
|  | ||||
|   backend_class->post_init = meta_backend_x11_post_init; | ||||
|   backend_class->create_idle_monitor = meta_backend_x11_create_idle_monitor; | ||||
|   backend_class->create_monitor_manager = meta_backend_x11_create_monitor_manager; | ||||
|   backend_class->create_cursor_renderer = meta_backend_x11_create_cursor_renderer; | ||||
|  | ||||
|   backend_class->grab_device = meta_backend_x11_grab_device; | ||||
|   backend_class->ungrab_device = meta_backend_x11_ungrab_device; | ||||
|   backend_class->warp_pointer = meta_backend_x11_warp_pointer; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_backend_x11_init (MetaBackendX11 *x11) | ||||
| { | ||||
|   /* We do X11 event retrieval ourselves */ | ||||
|   clutter_x11_disable_event_retrieval (); | ||||
| } | ||||
|  | ||||
| Display * | ||||
| meta_backend_x11_get_xdisplay (MetaBackendX11 *x11) | ||||
| { | ||||
|   MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); | ||||
|  | ||||
|   return priv->xdisplay; | ||||
| } | ||||
|  | ||||
| Window | ||||
| meta_backend_x11_get_xwindow (MetaBackendX11 *x11) | ||||
| { | ||||
|   MetaDisplay *display = meta_get_display (); | ||||
|   MetaCompositor *compositor = display->compositor; | ||||
|  | ||||
|   if (compositor == NULL) | ||||
|     return None; | ||||
|  | ||||
|   ClutterStage *stage = CLUTTER_STAGE (compositor->stage); | ||||
|   return clutter_x11_get_stage_window (stage); | ||||
| } | ||||
| @@ -1,58 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2014 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Jasper St. Pierre <jstpierre@mecheye.net> | ||||
|  */ | ||||
|  | ||||
| #ifndef META_BACKEND_X11_H | ||||
| #define META_BACKEND_X11_H | ||||
|  | ||||
| #include "backends/meta-backend-private.h" | ||||
|  | ||||
| #include <X11/Xlib.h> | ||||
|  | ||||
| #define META_TYPE_BACKEND_X11             (meta_backend_x11_get_type ()) | ||||
| #define META_BACKEND_X11(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BACKEND_X11, MetaBackendX11)) | ||||
| #define META_BACKEND_X11_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_BACKEND_X11, MetaBackendX11Class)) | ||||
| #define META_IS_BACKEND_X11(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_BACKEND_X11)) | ||||
| #define META_IS_BACKEND_X11_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_BACKEND_X11)) | ||||
| #define META_BACKEND_X11_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_BACKEND_X11, MetaBackendX11Class)) | ||||
|  | ||||
| typedef struct _MetaBackendX11        MetaBackendX11; | ||||
| typedef struct _MetaBackendX11Class   MetaBackendX11Class; | ||||
|  | ||||
| struct _MetaBackendX11 | ||||
| { | ||||
|   MetaBackend parent; | ||||
| }; | ||||
|  | ||||
| struct _MetaBackendX11Class | ||||
| { | ||||
|   MetaBackendClass parent_class; | ||||
| }; | ||||
|  | ||||
| GType meta_backend_x11_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| Display * meta_backend_x11_get_xdisplay (MetaBackendX11 *backend); | ||||
|  | ||||
| Window meta_backend_x11_get_xwindow (MetaBackendX11 *backend); | ||||
|  | ||||
| #endif /* META_BACKEND_X11_H */ | ||||
| @@ -1,99 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2014 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Jasper St. Pierre <jstpierre@mecheye.net> | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include "meta-cursor-renderer-x11.h" | ||||
|  | ||||
| #include "meta-backend-x11.h" | ||||
| #include "meta-stage.h" | ||||
|  | ||||
| struct _MetaCursorRendererX11Private | ||||
| { | ||||
|   gboolean server_cursor_visible; | ||||
| }; | ||||
| typedef struct _MetaCursorRendererX11Private MetaCursorRendererX11Private; | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRendererX11, meta_cursor_renderer_x11, META_TYPE_CURSOR_RENDERER); | ||||
|  | ||||
| static gboolean | ||||
| meta_cursor_renderer_x11_update_cursor (MetaCursorRenderer *renderer) | ||||
| { | ||||
|   MetaCursorRendererX11 *x11 = META_CURSOR_RENDERER_X11 (renderer); | ||||
|   MetaCursorRendererX11Private *priv = meta_cursor_renderer_x11_get_instance_private (x11); | ||||
|  | ||||
|   MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ()); | ||||
|   Window xwindow = meta_backend_x11_get_xwindow (backend); | ||||
|  | ||||
|   if (xwindow == None) | ||||
|     return FALSE; | ||||
|  | ||||
|   Display *xdisplay = meta_backend_x11_get_xdisplay (backend); | ||||
|  | ||||
|   MetaCursorReference *cursor_ref = meta_cursor_renderer_get_cursor (renderer); | ||||
|   gboolean has_server_cursor = FALSE; | ||||
|  | ||||
|   if (cursor_ref) | ||||
|     { | ||||
|       MetaCursor cursor = meta_cursor_reference_get_meta_cursor (cursor_ref); | ||||
|       if (cursor != META_CURSOR_NONE) | ||||
|         { | ||||
|           Cursor xcursor = meta_cursor_create_x_cursor (xdisplay, cursor); | ||||
|           XDefineCursor (xdisplay, xwindow, xcursor); | ||||
|           XFlush (xdisplay); | ||||
|           XFreeCursor (xdisplay, xcursor); | ||||
|  | ||||
|           has_server_cursor = TRUE; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   if (has_server_cursor != priv->server_cursor_visible) | ||||
|     { | ||||
|       if (has_server_cursor) | ||||
|         XFixesShowCursor (xdisplay, xwindow); | ||||
|       else | ||||
|         XFixesHideCursor (xdisplay, xwindow); | ||||
|  | ||||
|       priv->server_cursor_visible = has_server_cursor; | ||||
|     } | ||||
|  | ||||
|   return priv->server_cursor_visible; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_cursor_renderer_x11_class_init (MetaCursorRendererX11Class *klass) | ||||
| { | ||||
|   MetaCursorRendererClass *renderer_class = META_CURSOR_RENDERER_CLASS (klass); | ||||
|  | ||||
|   renderer_class->update_cursor = meta_cursor_renderer_x11_update_cursor; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_cursor_renderer_x11_init (MetaCursorRendererX11 *x11) | ||||
| { | ||||
|   MetaCursorRendererX11Private *priv = meta_cursor_renderer_x11_get_instance_private (x11); | ||||
|  | ||||
|   /* XFixes has no way to retrieve the current cursor visibility. */ | ||||
|   priv->server_cursor_visible = TRUE; | ||||
| } | ||||
| @@ -1,52 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2014 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Jasper St. Pierre <jstpierre@mecheye.net> | ||||
|  */ | ||||
|  | ||||
| #ifndef META_CURSOR_RENDERER_X11_H | ||||
| #define META_CURSOR_RENDERER_X11_H | ||||
|  | ||||
| #include "meta-cursor-renderer.h" | ||||
|  | ||||
| #define META_TYPE_CURSOR_RENDERER_X11             (meta_cursor_renderer_x11_get_type ()) | ||||
| #define META_CURSOR_RENDERER_X11(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CURSOR_RENDERER_X11, MetaCursorRendererX11)) | ||||
| #define META_CURSOR_RENDERER_X11_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_CURSOR_RENDERER_X11, MetaCursorRendererX11Class)) | ||||
| #define META_IS_CURSOR_RENDERER_X11(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_CURSOR_RENDERER_X11)) | ||||
| #define META_IS_CURSOR_RENDERER_X11_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_CURSOR_RENDERER_X11)) | ||||
| #define META_CURSOR_RENDERER_X11_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_CURSOR_RENDERER_X11, MetaCursorRendererX11Class)) | ||||
|  | ||||
| typedef struct _MetaCursorRendererX11        MetaCursorRendererX11; | ||||
| typedef struct _MetaCursorRendererX11Class   MetaCursorRendererX11Class; | ||||
|  | ||||
| struct _MetaCursorRendererX11 | ||||
| { | ||||
|   MetaCursorRenderer parent; | ||||
| }; | ||||
|  | ||||
| struct _MetaCursorRendererX11Class | ||||
| { | ||||
|   MetaCursorRendererClass parent_class; | ||||
| }; | ||||
|  | ||||
| GType meta_cursor_renderer_x11_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| #endif /* META_CURSOR_RENDERER_X11_H */ | ||||
| @@ -1,367 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright 2013 Red Hat, Inc. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * Adapted from gnome-session/gnome-session/gs-idle-monitor.c and | ||||
|  *         from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include "meta-idle-monitor-xsync.h" | ||||
| #include "meta-idle-monitor-private.h" | ||||
|  | ||||
| #include "meta-backend-x11.h" | ||||
|  | ||||
| #include <string.h> | ||||
|  | ||||
| struct _MetaIdleMonitorXSync | ||||
| { | ||||
|   MetaIdleMonitor parent; | ||||
|  | ||||
|   GHashTable  *alarms; | ||||
|   Display     *display; | ||||
|   XSyncCounter counter; | ||||
|   XSyncAlarm   user_active_alarm; | ||||
| }; | ||||
|  | ||||
| struct _MetaIdleMonitorXSyncClass | ||||
| { | ||||
|   MetaIdleMonitorClass parent_class; | ||||
| }; | ||||
|  | ||||
| typedef struct { | ||||
|   MetaIdleMonitorWatch base; | ||||
|  | ||||
|   XSyncAlarm xalarm; | ||||
| } MetaIdleMonitorWatchXSync; | ||||
|  | ||||
| G_DEFINE_TYPE (MetaIdleMonitorXSync, meta_idle_monitor_xsync, META_TYPE_IDLE_MONITOR) | ||||
|  | ||||
| static gint64 | ||||
| _xsyncvalue_to_int64 (XSyncValue value) | ||||
| { | ||||
|   return ((guint64) XSyncValueHigh32 (value)) << 32 | ||||
|     | (guint64) XSyncValueLow32 (value); | ||||
| } | ||||
|  | ||||
| #define GUINT64_TO_XSYNCVALUE(value, ret) XSyncIntsToValue (ret, (value) & 0xFFFFFFFF, ((guint64)(value)) >> 32) | ||||
|  | ||||
| static XSyncAlarm | ||||
| _xsync_alarm_set (MetaIdleMonitorXSync	*monitor_xsync, | ||||
| 		  XSyncTestType          test_type, | ||||
| 		  guint64                interval, | ||||
| 		  gboolean               want_events) | ||||
| { | ||||
|   XSyncAlarmAttributes attr; | ||||
|   XSyncValue	     delta; | ||||
|   guint		     flags; | ||||
|  | ||||
|   flags = XSyncCACounter | XSyncCAValueType | XSyncCATestType | | ||||
|     XSyncCAValue | XSyncCADelta | XSyncCAEvents; | ||||
|  | ||||
|   XSyncIntToValue (&delta, 0); | ||||
|   attr.trigger.counter = monitor_xsync->counter; | ||||
|   attr.trigger.value_type = XSyncAbsolute; | ||||
|   attr.delta = delta; | ||||
|   attr.events = want_events; | ||||
|  | ||||
|   GUINT64_TO_XSYNCVALUE (interval, &attr.trigger.wait_value); | ||||
|   attr.trigger.test_type = test_type; | ||||
|   return XSyncCreateAlarm (monitor_xsync->display, flags, &attr); | ||||
| } | ||||
|  | ||||
| static void | ||||
| ensure_alarm_rescheduled (Display    *dpy, | ||||
| 			  XSyncAlarm  alarm) | ||||
| { | ||||
|   XSyncAlarmAttributes attr; | ||||
|  | ||||
|   /* Some versions of Xorg have an issue where alarms aren't | ||||
|    * always rescheduled. Calling XSyncChangeAlarm, even | ||||
|    * without any attributes, will reschedule the alarm. */ | ||||
|   XSyncChangeAlarm (dpy, alarm, 0, &attr); | ||||
| } | ||||
|  | ||||
| static void | ||||
| set_alarm_enabled (Display    *dpy, | ||||
| 		   XSyncAlarm  alarm, | ||||
| 		   gboolean    enabled) | ||||
| { | ||||
|   XSyncAlarmAttributes attr; | ||||
|   attr.events = enabled; | ||||
|   XSyncChangeAlarm (dpy, alarm, XSyncCAEvents, &attr); | ||||
| } | ||||
|  | ||||
| static void | ||||
| check_x11_watch (gpointer data, | ||||
|                  gpointer user_data) | ||||
| { | ||||
|   MetaIdleMonitorWatchXSync *watch_xsync = data; | ||||
|   MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_xsync; | ||||
|   XSyncAlarm alarm = (XSyncAlarm) user_data; | ||||
|  | ||||
|   if (watch_xsync->xalarm != alarm) | ||||
|     return; | ||||
|  | ||||
|   _meta_idle_monitor_watch_fire (watch); | ||||
| } | ||||
|  | ||||
| static char * | ||||
| counter_name_for_device (int device_id) | ||||
| { | ||||
|   if (device_id > 0) | ||||
|     return g_strdup_printf ("DEVICEIDLETIME %d", device_id); | ||||
|  | ||||
|   return g_strdup ("IDLETIME"); | ||||
| } | ||||
|  | ||||
| static XSyncCounter | ||||
| find_idletime_counter (MetaIdleMonitorXSync *monitor_xsync) | ||||
| { | ||||
|   MetaIdleMonitor *monitor = META_IDLE_MONITOR (monitor_xsync); | ||||
|   int		      i; | ||||
|   int		      ncounters; | ||||
|   XSyncSystemCounter *counters; | ||||
|   XSyncCounter        counter = None; | ||||
|   char               *counter_name; | ||||
|  | ||||
|   counter_name = counter_name_for_device (monitor->device_id); | ||||
|   counters = XSyncListSystemCounters (monitor_xsync->display, &ncounters); | ||||
|   for (i = 0; i < ncounters; i++) | ||||
|     { | ||||
|       if (counters[i].name != NULL && strcmp (counters[i].name, counter_name) == 0) | ||||
|         { | ||||
|           counter = counters[i].counter; | ||||
|           break; | ||||
|         } | ||||
|     } | ||||
|   XSyncFreeSystemCounterList (counters); | ||||
|   g_free (counter_name); | ||||
|  | ||||
|   return counter; | ||||
| } | ||||
|  | ||||
| static void | ||||
| init_xsync (MetaIdleMonitorXSync *monitor_xsync) | ||||
| { | ||||
|   monitor_xsync->counter = find_idletime_counter (monitor_xsync); | ||||
|   /* IDLETIME counter not found? */ | ||||
|   if (monitor_xsync->counter == None) | ||||
|     { | ||||
|       g_warning ("IDLETIME counter not found\n"); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   monitor_xsync->user_active_alarm = _xsync_alarm_set (monitor_xsync, XSyncNegativeTransition, 1, FALSE); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_idle_monitor_xsync_dispose (GObject *object) | ||||
| { | ||||
|   MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (object); | ||||
|  | ||||
|   if (monitor_xsync->user_active_alarm != None) | ||||
|     { | ||||
|       XSyncDestroyAlarm (monitor_xsync->display, monitor_xsync->user_active_alarm); | ||||
|       monitor_xsync->user_active_alarm = None; | ||||
|     } | ||||
|  | ||||
|   g_clear_pointer (&monitor_xsync->alarms, g_hash_table_destroy); | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_idle_monitor_xsync_parent_class)->dispose (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_idle_monitor_xsync_constructed (GObject *object) | ||||
| { | ||||
|   MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (object); | ||||
|   MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ()); | ||||
|  | ||||
|   monitor_xsync->display = meta_backend_x11_get_xdisplay (backend); | ||||
|   init_xsync (monitor_xsync); | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_idle_monitor_xsync_parent_class)->constructed (object); | ||||
| } | ||||
|  | ||||
| static gint64 | ||||
| meta_idle_monitor_xsync_get_idletime (MetaIdleMonitor *monitor) | ||||
| { | ||||
|   MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (monitor); | ||||
|   XSyncValue value; | ||||
|  | ||||
|   if (!XSyncQueryCounter (monitor_xsync->display, monitor_xsync->counter, &value)) | ||||
|     return -1; | ||||
|  | ||||
|   return _xsyncvalue_to_int64 (value); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| fire_watch_idle (gpointer data) | ||||
| { | ||||
|   MetaIdleMonitorWatch *watch = data; | ||||
|  | ||||
|   watch->idle_source_id = 0; | ||||
|   _meta_idle_monitor_watch_fire (watch); | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static guint32 | ||||
| get_next_watch_serial (void) | ||||
| { | ||||
|   static guint32 serial = 0; | ||||
|   g_atomic_int_inc (&serial); | ||||
|   return serial; | ||||
| } | ||||
|  | ||||
| static void | ||||
| free_watch (gpointer data) | ||||
| { | ||||
|   MetaIdleMonitorWatchXSync *watch_xsync = data; | ||||
|   MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_xsync; | ||||
|   MetaIdleMonitor *monitor = watch->monitor; | ||||
|   MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (monitor); | ||||
|  | ||||
|   g_object_ref (monitor); | ||||
|  | ||||
|   if (watch->idle_source_id) | ||||
|     { | ||||
|       g_source_remove (watch->idle_source_id); | ||||
|       watch->idle_source_id = 0; | ||||
|     } | ||||
|  | ||||
|   if (watch->notify != NULL) | ||||
|     watch->notify (watch->user_data); | ||||
|  | ||||
|   if (watch_xsync->xalarm != monitor_xsync->user_active_alarm && | ||||
|       watch_xsync->xalarm != None) | ||||
|     { | ||||
|       XSyncDestroyAlarm (monitor_xsync->display, watch_xsync->xalarm); | ||||
|       g_hash_table_remove (monitor_xsync->alarms, (gpointer) watch_xsync->xalarm); | ||||
|     } | ||||
|  | ||||
|   g_object_unref (monitor); | ||||
|   g_slice_free (MetaIdleMonitorWatchXSync, watch_xsync); | ||||
| } | ||||
|  | ||||
| static MetaIdleMonitorWatch * | ||||
| meta_idle_monitor_xsync_make_watch (MetaIdleMonitor           *monitor, | ||||
|                                     guint64                    timeout_msec, | ||||
|                                     MetaIdleMonitorWatchFunc   callback, | ||||
|                                     gpointer                   user_data, | ||||
|                                     GDestroyNotify             notify) | ||||
| { | ||||
|   MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (monitor); | ||||
|   MetaIdleMonitorWatchXSync *watch_xsync; | ||||
|   MetaIdleMonitorWatch *watch; | ||||
|  | ||||
|   watch_xsync = g_slice_new0 (MetaIdleMonitorWatchXSync); | ||||
|   watch = (MetaIdleMonitorWatch *) watch_xsync; | ||||
|  | ||||
|   watch->monitor = monitor; | ||||
|   watch->id = get_next_watch_serial (); | ||||
|   watch->callback = callback; | ||||
|   watch->user_data = user_data; | ||||
|   watch->notify = notify; | ||||
|   watch->timeout_msec = timeout_msec; | ||||
|  | ||||
|   if (monitor_xsync->user_active_alarm != None) | ||||
|     { | ||||
|       if (timeout_msec != 0) | ||||
|         { | ||||
|           watch_xsync->xalarm = _xsync_alarm_set (monitor_xsync, XSyncPositiveTransition, timeout_msec, TRUE); | ||||
|  | ||||
|           g_hash_table_add (monitor_xsync->alarms, (gpointer) watch_xsync->xalarm); | ||||
|  | ||||
|           if (meta_idle_monitor_get_idletime (monitor) > (gint64)timeout_msec) | ||||
|             { | ||||
|               watch->idle_source_id = g_idle_add (fire_watch_idle, watch); | ||||
|               g_source_set_name_by_id (watch->idle_source_id, "[mutter] fire_watch_idle"); | ||||
|             } | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           watch_xsync->xalarm = monitor_xsync->user_active_alarm; | ||||
|  | ||||
|           set_alarm_enabled (monitor_xsync->display, monitor_xsync->user_active_alarm, TRUE); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   return watch; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_idle_monitor_xsync_class_init (MetaIdleMonitorXSyncClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|   MetaIdleMonitorClass *idle_monitor_class = META_IDLE_MONITOR_CLASS (klass); | ||||
|  | ||||
|   object_class->dispose = meta_idle_monitor_xsync_dispose; | ||||
|   object_class->constructed = meta_idle_monitor_xsync_constructed; | ||||
|  | ||||
|   idle_monitor_class->get_idletime = meta_idle_monitor_xsync_get_idletime; | ||||
|   idle_monitor_class->make_watch = meta_idle_monitor_xsync_make_watch; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_idle_monitor_xsync_init (MetaIdleMonitorXSync *monitor_xsync) | ||||
| { | ||||
|   MetaIdleMonitor *monitor = META_IDLE_MONITOR (monitor_xsync); | ||||
|  | ||||
|   monitor->watches = g_hash_table_new_full (NULL, NULL, NULL, free_watch); | ||||
|   monitor_xsync->alarms = g_hash_table_new (NULL, NULL); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_idle_monitor_xsync_handle_xevent (MetaIdleMonitor       *monitor, | ||||
|                                        XSyncAlarmNotifyEvent *alarm_event) | ||||
| { | ||||
|   MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (monitor); | ||||
|   XSyncAlarm alarm; | ||||
|   GList *watches; | ||||
|   gboolean has_alarm; | ||||
|  | ||||
|   if (alarm_event->state != XSyncAlarmActive) | ||||
|     return; | ||||
|  | ||||
|   alarm = alarm_event->alarm; | ||||
|  | ||||
|   has_alarm = FALSE; | ||||
|  | ||||
|   if (alarm == monitor_xsync->user_active_alarm) | ||||
|     { | ||||
|       set_alarm_enabled (monitor_xsync->display, | ||||
|                          alarm, | ||||
|                          FALSE); | ||||
|       has_alarm = TRUE; | ||||
|     } | ||||
|   else if (g_hash_table_contains (monitor_xsync->alarms, (gpointer) alarm)) | ||||
|     { | ||||
|       ensure_alarm_rescheduled (monitor_xsync->display, | ||||
|                                 alarm); | ||||
|       has_alarm = TRUE; | ||||
|     } | ||||
|  | ||||
|   if (has_alarm) | ||||
|     { | ||||
|       watches = g_hash_table_get_values (monitor->watches); | ||||
|  | ||||
|       g_list_foreach (watches, check_x11_watch, (gpointer) alarm); | ||||
|       g_list_free (watches); | ||||
|     } | ||||
| } | ||||
| @@ -1,47 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright 2013 Red Hat, Inc. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * Adapted from gnome-session/gnome-session/gs-idle-monitor.c and | ||||
|  *         from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c | ||||
|  */ | ||||
|  | ||||
| #ifndef META_IDLE_MONITOR_XSYNC_H | ||||
| #define META_IDLE_MONITOR_XSYNC_H | ||||
|  | ||||
| #include <glib-object.h> | ||||
| #include <meta/meta-idle-monitor.h> | ||||
|  | ||||
| #include <X11/Xlib.h> | ||||
| #include <X11/extensions/sync.h> | ||||
|  | ||||
| #define META_TYPE_IDLE_MONITOR_XSYNC            (meta_idle_monitor_xsync_get_type ()) | ||||
| #define META_IDLE_MONITOR_XSYNC(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_IDLE_MONITOR_XSYNC, MetaIdleMonitorXSync)) | ||||
| #define META_IDLE_MONITOR_XSYNC_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_IDLE_MONITOR_XSYNC, MetaIdleMonitorXSyncClass)) | ||||
| #define META_IS_IDLE_MONITOR_XSYNC(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_IDLE_MONITOR_XSYNC)) | ||||
| #define META_IS_IDLE_MONITOR_XSYNC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_IDLE_MONITOR_XSYNC)) | ||||
| #define META_IDLE_MONITOR_XSYNC_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_IDLE_MONITOR_XSYNC, MetaIdleMonitorXSyncClass)) | ||||
|  | ||||
| typedef struct _MetaIdleMonitorXSync        MetaIdleMonitorXSync; | ||||
| typedef struct _MetaIdleMonitorXSyncClass   MetaIdleMonitorXSyncClass; | ||||
|  | ||||
| GType meta_idle_monitor_xsync_get_type (void); | ||||
|  | ||||
| void meta_idle_monitor_xsync_handle_xevent (MetaIdleMonitor       *monitor, | ||||
|                                             XSyncAlarmNotifyEvent *xevent); | ||||
|  | ||||
| #endif /* META_IDLE_MONITOR_XSYNC_H */ | ||||
| @@ -1,43 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2001 Havoc Pennington | ||||
|  * Copyright (C) 2003 Rob Adams | ||||
|  * Copyright (C) 2004-2006 Elijah Newren | ||||
|  * Copyright (C) 2013 Red Hat Inc. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #ifndef META_MONITOR_MANAGER_XRANDR_H | ||||
| #define META_MONITOR_MANAGER_XRANDR_H | ||||
|  | ||||
| #include "meta-monitor-manager.h" | ||||
|  | ||||
| #define META_TYPE_MONITOR_MANAGER_XRANDR            (meta_monitor_manager_xrandr_get_type ()) | ||||
| #define META_MONITOR_MANAGER_XRANDR(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandr)) | ||||
| #define META_MONITOR_MANAGER_XRANDR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandrClass)) | ||||
| #define META_IS_MONITOR_MANAGER_XRANDR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_MANAGER_XRANDR)) | ||||
| #define META_IS_MONITOR_MANAGER_XRANDR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_MONITOR_MANAGER_XRANDR)) | ||||
| #define META_MONITOR_MANAGER_XRANDR_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandrClass)) | ||||
|  | ||||
| typedef struct _MetaMonitorManagerXrandrClass    MetaMonitorManagerXrandrClass; | ||||
| typedef struct _MetaMonitorManagerXrandr         MetaMonitorManagerXrandr; | ||||
|  | ||||
| GType meta_monitor_manager_xrandr_get_type (void); | ||||
|  | ||||
| gboolean meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager, | ||||
|                                                     XEvent                   *event); | ||||
|  | ||||
| #endif /* META_MONITOR_MANAGER_XRANDR_H */ | ||||
| @@ -68,7 +68,7 @@ meta_create_color_texture_4ub (guint8           red, | ||||
|  | ||||
| /** | ||||
|  * meta_create_texture_pipeline: | ||||
|  * @src_texture: (nullable): texture to use initially for the layer | ||||
|  * @src_texture: (allow-none): texture to use initially for the layer | ||||
|  * | ||||
|  * Creates a pipeline with a single layer. Using a common template | ||||
|  * makes it easier for Cogl to share a shader for different uses in | ||||
|   | ||||
| @@ -11,21 +11,37 @@ | ||||
| #include "meta-window-actor-private.h" | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| typedef struct _MetaCompScreen MetaCompScreen; | ||||
|  | ||||
| struct _MetaCompositor | ||||
| { | ||||
|   MetaDisplay    *display; | ||||
|  | ||||
|   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           no_mipmaps  : 1; | ||||
|   int             glx_opcode; | ||||
|  | ||||
|   ClutterActor          *stage, *window_group, *top_window_group; | ||||
|   guint           server_time_is_monotonic_time : 1; | ||||
|   guint           show_redraw : 1; | ||||
|   guint           debug       : 1; | ||||
|   guint           no_mipmaps  : 1; | ||||
| }; | ||||
|  | ||||
| struct _MetaCompScreen | ||||
| { | ||||
|   MetaScreen            *screen; | ||||
|  | ||||
|   ClutterActor          *stage, *window_group, *top_window_group, *overlay_group; | ||||
|   ClutterActor          *background_actor; | ||||
|   GList                 *windows; | ||||
|   GHashTable            *windows_by_xid; | ||||
|   Window                 output; | ||||
|  | ||||
|   CoglOnscreen          *onscreen; | ||||
| @@ -37,23 +53,33 @@ struct _MetaCompositor | ||||
|  | ||||
|   gint                   switch_workspace_in_progress; | ||||
|  | ||||
|   guint                  stereo_tree_ext : 1; | ||||
|   guint                  have_stereo_windows : 1; | ||||
|  | ||||
|   MetaPluginManager *plugin_mgr; | ||||
| }; | ||||
|  | ||||
| /* Wait 2ms after vblank before starting to draw next frame */ | ||||
| #define META_SYNC_DELAY 2 | ||||
|  | ||||
| void meta_switch_workspace_completed (MetaCompositor *compositor); | ||||
| void meta_switch_workspace_completed (MetaScreen    *screen); | ||||
|  | ||||
| gboolean meta_begin_modal_for_plugin (MetaCompositor   *compositor, | ||||
| gboolean meta_begin_modal_for_plugin (MetaScreen       *screen, | ||||
|                                       MetaPlugin       *plugin, | ||||
|                                       MetaModalOptions  options, | ||||
|                                       guint32           timestamp); | ||||
| void     meta_end_modal_for_plugin   (MetaCompositor   *compositor, | ||||
| void     meta_end_modal_for_plugin   (MetaScreen       *screen, | ||||
|                                       MetaPlugin       *plugin, | ||||
|                                       guint32           timestamp); | ||||
|  | ||||
| gint64 meta_compositor_monotonic_time_to_server_time (MetaDisplay *display, | ||||
|                                                       gint64       monotonic_time); | ||||
|  | ||||
| void meta_check_end_modal (MetaScreen *screen); | ||||
|  | ||||
| gboolean meta_compositor_window_is_stereo     (MetaScreen *screen, | ||||
|                                                Window      xwindow); | ||||
| void     meta_compositor_select_stereo_notify (MetaScreen *screen, | ||||
|                                                Window      xwindow); | ||||
|  | ||||
| #endif /* META_COMPOSITOR_PRIVATE_H */ | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -26,6 +26,8 @@ | ||||
|  | ||||
| #include <config.h> | ||||
|  | ||||
| #include <cogl/cogl-texture-pixmap-x11.h> | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| #include "cogl-utils.h" | ||||
| @@ -753,6 +755,88 @@ set_filename (MetaBackground *self, | ||||
|   priv->filename = g_strdup (filename); | ||||
| } | ||||
|  | ||||
| static Pixmap | ||||
| get_still_frame_for_monitor (MetaScreen *screen, | ||||
|                              int         monitor) | ||||
| { | ||||
|   MetaDisplay *display = meta_screen_get_display (screen); | ||||
|   Display *xdisplay = meta_display_get_xdisplay (display); | ||||
|   Window xroot = meta_screen_get_xroot (screen); | ||||
|   Pixmap pixmap; | ||||
|   GC gc; | ||||
|   XGCValues values; | ||||
|   MetaRectangle geometry; | ||||
|   int depth; | ||||
|  | ||||
|   meta_screen_get_monitor_geometry (screen, monitor, &geometry); | ||||
|  | ||||
|   depth = DefaultDepth (xdisplay, meta_screen_get_screen_number (screen)); | ||||
|  | ||||
|   pixmap = XCreatePixmap (xdisplay, | ||||
|                           xroot, | ||||
|                           geometry.width, geometry.height, depth); | ||||
|  | ||||
|   values.function = GXcopy; | ||||
|   values.plane_mask = AllPlanes; | ||||
|   values.fill_style = FillSolid; | ||||
|   values.subwindow_mode = IncludeInferiors; | ||||
|  | ||||
|   gc = XCreateGC (xdisplay, | ||||
|                   xroot, | ||||
|                   GCFunction | GCPlaneMask | GCFillStyle | GCSubwindowMode, | ||||
|                   &values); | ||||
|  | ||||
|   XCopyArea (xdisplay, | ||||
|              xroot, pixmap, gc, | ||||
|              geometry.x, geometry.y, | ||||
|              geometry.width, geometry.height, | ||||
|              0, 0); | ||||
|  | ||||
|   XFreeGC (xdisplay, gc); | ||||
|  | ||||
|   return pixmap; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_background_load_still_frame: | ||||
|  * @self: the #MetaBackground | ||||
|  * | ||||
|  * Takes a screenshot of the desktop and uses it as the background | ||||
|  * source. | ||||
|  */ | ||||
| void | ||||
| meta_background_load_still_frame (MetaBackground *self) | ||||
| { | ||||
|   MetaBackgroundPrivate *priv = self->priv; | ||||
|   MetaDisplay *display = meta_screen_get_display (priv->screen); | ||||
|   Pixmap still_frame; | ||||
|   CoglTexture *texture; | ||||
|   CoglContext *context = clutter_backend_get_cogl_context (clutter_get_default_backend ()); | ||||
|   GError *error = NULL; | ||||
|  | ||||
|   ensure_pipeline (self); | ||||
|  | ||||
|   unset_texture (self); | ||||
|   set_style (self, G_DESKTOP_BACKGROUND_STYLE_STRETCHED); | ||||
|  | ||||
|   still_frame = get_still_frame_for_monitor (priv->screen, priv->monitor); | ||||
|   XSync (meta_display_get_xdisplay (display), False); | ||||
|  | ||||
|   meta_error_trap_push (display); | ||||
|   texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (context, still_frame, FALSE, &error)); | ||||
|   meta_error_trap_pop (display); | ||||
|  | ||||
|   if (error != NULL) | ||||
|     { | ||||
|       g_warning ("Failed to create background texture from pixmap: %s", | ||||
|                  error->message); | ||||
|       g_error_free (error); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   set_texture (self, texture); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_background_load_gradient: | ||||
|  * @self: the #MetaBackground | ||||
|   | ||||
| @@ -20,7 +20,6 @@ | ||||
|  */ | ||||
|  | ||||
| #include <meta/meta-plugin.h> | ||||
| #include <meta/meta-version.h> | ||||
| #include "meta-module.h" | ||||
|  | ||||
| #include <gmodule.h> | ||||
| @@ -69,7 +68,7 @@ meta_module_load (GTypeModule *gmodule) | ||||
| 		       (gpointer *)(void *)®ister_type) && | ||||
|       info && register_type) | ||||
|     { | ||||
|       if (info->version_api != META_PLUGIN_API_VERSION) | ||||
|       if (info->version_api != MUTTER_PLUGIN_API_VERSION) | ||||
| 	g_warning ("Plugin API mismatch for [%s]", priv->path); | ||||
|       else | ||||
|         { | ||||
|   | ||||
| @@ -37,7 +37,7 @@ static GType plugin_type = G_TYPE_NONE; | ||||
|  | ||||
| struct MetaPluginManager | ||||
| { | ||||
|   MetaCompositor *compositor; | ||||
|   MetaScreen *screen; | ||||
|   MetaPlugin *plugin; | ||||
| }; | ||||
|  | ||||
| @@ -91,7 +91,7 @@ on_confirm_display_change (MetaMonitorManager *monitors, | ||||
| } | ||||
|  | ||||
| MetaPluginManager * | ||||
| meta_plugin_manager_new (MetaCompositor *compositor) | ||||
| meta_plugin_manager_new (MetaScreen *screen) | ||||
| { | ||||
|   MetaPluginManager *plugin_mgr; | ||||
|   MetaPluginClass *klass; | ||||
| @@ -99,10 +99,8 @@ meta_plugin_manager_new (MetaCompositor *compositor) | ||||
|   MetaMonitorManager *monitors; | ||||
|  | ||||
|   plugin_mgr = g_new0 (MetaPluginManager, 1); | ||||
|   plugin_mgr->compositor = compositor; | ||||
|   plugin_mgr->plugin = plugin = g_object_new (plugin_type, NULL); | ||||
|  | ||||
|   _meta_plugin_set_compositor (plugin, compositor); | ||||
|   plugin_mgr->screen = screen; | ||||
|   plugin_mgr->plugin = plugin = g_object_new (plugin_type, "screen", screen, NULL); | ||||
|  | ||||
|   klass = META_PLUGIN_GET_CLASS (plugin); | ||||
|  | ||||
| @@ -153,7 +151,7 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr, | ||||
| { | ||||
|   MetaPlugin *plugin = plugin_mgr->plugin; | ||||
|   MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); | ||||
|   MetaDisplay *display = plugin_mgr->compositor->display; | ||||
|   MetaDisplay *display  = meta_screen_get_display (plugin_mgr->screen); | ||||
|   gboolean retval = FALSE; | ||||
|  | ||||
|   if (display->display_opening) | ||||
| @@ -167,6 +165,8 @@ 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,6 +176,8 @@ 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; | ||||
| @@ -183,6 +185,7 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr, | ||||
|       if (klass->destroy) | ||||
|         { | ||||
|           retval = TRUE; | ||||
|           _meta_plugin_effect_started (plugin); | ||||
|           klass->destroy (plugin, actor); | ||||
|         } | ||||
|       break; | ||||
| @@ -213,7 +216,7 @@ meta_plugin_manager_event_maximize (MetaPluginManager *plugin_mgr, | ||||
| { | ||||
|   MetaPlugin *plugin = plugin_mgr->plugin; | ||||
|   MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); | ||||
|   MetaDisplay *display = plugin_mgr->compositor->display; | ||||
|   MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen); | ||||
|   gboolean retval = FALSE; | ||||
|  | ||||
|   if (display->display_opening) | ||||
| @@ -227,6 +230,8 @@ 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); | ||||
| @@ -238,6 +243,8 @@ 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); | ||||
| @@ -266,7 +273,7 @@ meta_plugin_manager_switch_workspace (MetaPluginManager   *plugin_mgr, | ||||
| { | ||||
|   MetaPlugin *plugin = plugin_mgr->plugin; | ||||
|   MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); | ||||
|   MetaDisplay *display = plugin_mgr->compositor->display; | ||||
|   MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen); | ||||
|   gboolean retval = FALSE; | ||||
|  | ||||
|   if (display->display_opening) | ||||
| @@ -276,6 +283,8 @@ 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,7 +333,7 @@ meta_plugin_manager_show_tile_preview (MetaPluginManager *plugin_mgr, | ||||
| { | ||||
|   MetaPlugin *plugin = plugin_mgr->plugin; | ||||
|   MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); | ||||
|   MetaDisplay *display = plugin_mgr->compositor->display; | ||||
|   MetaDisplay *display  = meta_screen_get_display (plugin_mgr->screen); | ||||
|  | ||||
|   if (display->display_opening) | ||||
|     return FALSE; | ||||
| @@ -343,7 +352,7 @@ meta_plugin_manager_hide_tile_preview (MetaPluginManager *plugin_mgr) | ||||
| { | ||||
|   MetaPlugin *plugin = plugin_mgr->plugin; | ||||
|   MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); | ||||
|   MetaDisplay *display = plugin_mgr->compositor->display; | ||||
|   MetaDisplay *display  = meta_screen_get_display (plugin_mgr->screen); | ||||
|  | ||||
|   if (display->display_opening) | ||||
|     return FALSE; | ||||
| @@ -356,38 +365,3 @@ meta_plugin_manager_hide_tile_preview (MetaPluginManager *plugin_mgr) | ||||
|  | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_plugin_manager_show_window_menu (MetaPluginManager  *plugin_mgr, | ||||
|                                       MetaWindow         *window, | ||||
|                                       MetaWindowMenuType  menu, | ||||
|                                       int                 x, | ||||
|                                       int                 y) | ||||
| { | ||||
|   MetaPlugin *plugin = plugin_mgr->plugin; | ||||
|   MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); | ||||
|   MetaDisplay *display = plugin_mgr->compositor->display; | ||||
|  | ||||
|   if (display->display_opening) | ||||
|     return; | ||||
|  | ||||
|   if (klass->show_window_menu) | ||||
|     klass->show_window_menu (plugin, window, menu, x, y); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_plugin_manager_show_window_menu_for_rect (MetaPluginManager  *plugin_mgr, | ||||
|                                                MetaWindow         *window, | ||||
|                                                MetaWindowMenuType  menu, | ||||
| 					       MetaRectangle      *rect) | ||||
| { | ||||
|   MetaPlugin *plugin = plugin_mgr->plugin; | ||||
|   MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); | ||||
|   MetaDisplay *display = plugin_mgr->compositor->display; | ||||
|  | ||||
|   if (display->display_opening) | ||||
|     return; | ||||
|  | ||||
|   if (klass->show_window_menu_for_rect) | ||||
|     klass->show_window_menu_for_rect (plugin, window, menu, rect); | ||||
| } | ||||
|   | ||||
| @@ -44,7 +44,7 @@ | ||||
|  */ | ||||
| typedef struct MetaPluginManager MetaPluginManager; | ||||
|  | ||||
| MetaPluginManager * meta_plugin_manager_new (MetaCompositor *compositor); | ||||
| MetaPluginManager * meta_plugin_manager_new (MetaScreen *screen); | ||||
|  | ||||
| void     meta_plugin_manager_load         (const gchar       *plugin_name); | ||||
|  | ||||
| @@ -80,17 +80,4 @@ gboolean meta_plugin_manager_show_tile_preview (MetaPluginManager *mgr, | ||||
|                                                 MetaRectangle     *tile_rect, | ||||
|                                                 int                tile_monitor_number); | ||||
| gboolean meta_plugin_manager_hide_tile_preview (MetaPluginManager *mgr); | ||||
|  | ||||
| void meta_plugin_manager_show_window_menu (MetaPluginManager  *mgr, | ||||
|                                            MetaWindow         *window, | ||||
|                                            MetaWindowMenuType  menu, | ||||
|                                            int                 x, | ||||
|                                            int                 y); | ||||
|  | ||||
| void meta_plugin_manager_show_window_menu_for_rect (MetaPluginManager  *mgr, | ||||
| 		                                    MetaWindow         *window, | ||||
| 						    MetaWindowMenuType  menu, | ||||
| 						    MetaRectangle      *rect); | ||||
|  | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -30,7 +30,6 @@ | ||||
| #include "meta-plugin-manager.h" | ||||
| #include <meta/screen.h> | ||||
| #include <meta/display.h> | ||||
| #include <meta/util.h> | ||||
|  | ||||
| #include <string.h> | ||||
| #include <X11/Xlib.h> | ||||
| @@ -40,22 +39,98 @@ | ||||
|  | ||||
| #include "compositor-private.h" | ||||
| #include "meta-window-actor-private.h" | ||||
| #include "meta-monitor-manager.h" | ||||
| #include "monitor-private.h" | ||||
|  | ||||
| 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 | ||||
| { | ||||
|   MetaCompositor *compositor; | ||||
|   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) | ||||
| { | ||||
|   g_type_class_add_private (klass, sizeof (MetaPluginPrivate)); | ||||
|   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)); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -64,6 +139,22 @@ 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) | ||||
| { | ||||
| @@ -75,16 +166,31 @@ 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) | ||||
| { | ||||
|   MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); | ||||
|  | ||||
|   if (klass->xevent_filter) | ||||
|     return klass->xevent_filter (plugin, xev); | ||||
|   if (klass->xevent_filter && klass->xevent_filter (plugin, xev)) | ||||
|     return TRUE; | ||||
|   else | ||||
|     return FALSE; | ||||
|     return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE; | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -92,7 +198,15 @@ meta_plugin_switch_workspace_completed (MetaPlugin *plugin) | ||||
| { | ||||
|   MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv; | ||||
|  | ||||
|   meta_switch_workspace_completed (priv->compositor); | ||||
|   MetaScreen *screen = priv->screen; | ||||
|  | ||||
|   if (priv->running-- < 0) | ||||
|     { | ||||
|       g_warning ("Error in running effect accounting, adjusting."); | ||||
|       priv->running = 0; | ||||
|     } | ||||
|  | ||||
|   meta_switch_workspace_completed (screen); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -100,6 +214,26 @@ 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); | ||||
| } | ||||
|  | ||||
| @@ -166,7 +300,7 @@ meta_plugin_begin_modal (MetaPlugin       *plugin, | ||||
| { | ||||
|   MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv; | ||||
|  | ||||
|   return meta_begin_modal_for_plugin (priv->compositor, plugin, | ||||
|   return meta_begin_modal_for_plugin (priv->screen, plugin, | ||||
|                                       options, timestamp); | ||||
| } | ||||
|  | ||||
| @@ -187,14 +321,16 @@ meta_plugin_end_modal (MetaPlugin *plugin, | ||||
| { | ||||
|   MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv; | ||||
|  | ||||
|   meta_end_modal_for_plugin (priv->compositor, plugin, timestamp); | ||||
|   meta_end_modal_for_plugin (priv->screen, plugin, timestamp); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_plugin_get_screen: | ||||
|  * @plugin: a #MetaPlugin | ||||
|  * | ||||
|  * Gets the #MetaScreen corresponding to a plugin. | ||||
|  * 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. | ||||
|  * | ||||
|  * Return value: (transfer none): the #MetaScreen for the plugin | ||||
|  */ | ||||
| @@ -203,15 +339,7 @@ meta_plugin_get_screen (MetaPlugin *plugin) | ||||
| { | ||||
|   MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv; | ||||
|  | ||||
|   return priv->compositor->display->screen; | ||||
| } | ||||
|  | ||||
| void | ||||
| _meta_plugin_set_compositor (MetaPlugin *plugin, MetaCompositor *compositor) | ||||
| { | ||||
|   MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv; | ||||
|  | ||||
|   priv->compositor = compositor; | ||||
|   return priv->screen; | ||||
| } | ||||
|  | ||||
| void | ||||
|   | ||||
| @@ -121,17 +121,17 @@ static guint signals[LAST_SIGNAL] = { 0 }; | ||||
| /* The first element in this array also defines the default parameters | ||||
|  * for newly created classes */ | ||||
| MetaShadowClassInfo default_shadow_classes[] = { | ||||
|   { "normal",       { 3, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } }, | ||||
|   { "dialog",       { 3, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } }, | ||||
|   { "modal_dialog", { 3, -1, 0, 1, 128 }, { 3, -1, 0, 3, 32 } }, | ||||
|   { "normal",       { 6, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } }, | ||||
|   { "dialog",       { 6, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } }, | ||||
|   { "modal_dialog", { 6, -1, 0, 1, 128 }, { 3, -1, 0, 3, 32 } }, | ||||
|   { "utility",      { 3, -1, 0, 1, 128 }, { 3, -1, 0, 1, 32 } }, | ||||
|   { "border",       { 3, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } }, | ||||
|   { "menu",         { 3, -1, 0, 3, 128 }, { 3, -1, 0, 0, 32 } }, | ||||
|   { "border",       { 6, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } }, | ||||
|   { "menu",         { 6, -1, 0, 3, 128 }, { 3, -1, 0, 0, 32 } }, | ||||
|  | ||||
|   { "popup-menu",    { 1, 0, 0, 1, 128 }, { 1, -1, 0, 1, 128 } }, | ||||
|   { "popup-menu",    { 1, -1, 0, 1, 128 }, { 1, -1, 0, 1, 128 } }, | ||||
|  | ||||
|   { "dropdown-menu", { 1, 10, 0, 1, 128 }, { 1, 10, 0, 1, 128 } }, | ||||
|   { "attached",      { 1, 0, 0, 1, 128 }, { 1, -1, 0, 1, 128 } } | ||||
|   { "attached",      { 1, -1, 0, 1, 128 }, { 1, -1, 0, 1, 128 } } | ||||
| }; | ||||
|  | ||||
| G_DEFINE_TYPE (MetaShadowFactory, meta_shadow_factory, G_TYPE_OBJECT); | ||||
| @@ -189,7 +189,7 @@ meta_shadow_unref (MetaShadow *shadow) | ||||
|  * @window_y: y position of the region to paint a shadow for | ||||
|  * @window_width: actual width of the region to paint a shadow for | ||||
|  * @window_height: actual height of the region to paint a shadow for | ||||
|  * @clip: (nullable): if non-%NULL specifies the visible portion | ||||
|  * @clip: (allow-none): if non-%NULL specifies the visible portion | ||||
|  *   of the shadow. | ||||
|  * @clip_strictly: if %TRUE, drawing will be clipped strictly | ||||
|  *   to @clip, otherwise, it will be only used to optimize | ||||
| @@ -496,12 +496,7 @@ get_box_filter_size (int radius) | ||||
| static int | ||||
| get_shadow_spread (int radius) | ||||
| { | ||||
|   int d; | ||||
|  | ||||
|   if (radius == 0) | ||||
|     return 0; | ||||
|  | ||||
|   d = get_box_filter_size (radius); | ||||
|   int d = get_box_filter_size (radius); | ||||
|  | ||||
|   if (d % 2 == 1) | ||||
|     return 3 * (d / 2); | ||||
|   | ||||
| @@ -31,7 +31,8 @@ | ||||
|  | ||||
| ClutterActor *meta_shaped_texture_new (void); | ||||
| void meta_shaped_texture_set_texture (MetaShapedTexture *stex, | ||||
|                                       CoglTexture       *texture); | ||||
|                                       CoglTexture       *texture, | ||||
| 				      gboolean           stereo); | ||||
| gboolean meta_shaped_texture_get_unobscured_bounds (MetaShapedTexture     *stex, | ||||
|                                                     cairo_rectangle_int_t *unobscured_bounds); | ||||
| gboolean meta_shaped_texture_is_obscured (MetaShapedTexture *self); | ||||
|   | ||||
| @@ -28,7 +28,6 @@ | ||||
| #include <config.h> | ||||
|  | ||||
| #include <meta/meta-shaped-texture.h> | ||||
| #include <meta/util.h> | ||||
| #include "clutter-utils.h" | ||||
| #include "meta-texture-tower.h" | ||||
|  | ||||
| @@ -37,12 +36,15 @@ | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
| #include <cogl/cogl.h> | ||||
| #include <cogl/cogl-texture-pixmap-x11.h> | ||||
| #include <gdk/gdk.h> /* for gdk_rectangle_intersect() */ | ||||
| #include "meta-cullable.h" | ||||
|  | ||||
| static void meta_shaped_texture_dispose  (GObject    *object); | ||||
|  | ||||
| static void meta_shaped_texture_paint (ClutterActor       *actor); | ||||
| static void meta_shaped_texture_pick  (ClutterActor       *actor, | ||||
| 				       const ClutterColor *color); | ||||
|  | ||||
| static void meta_shaped_texture_get_preferred_width (ClutterActor *self, | ||||
|                                                      gfloat        for_height, | ||||
| @@ -68,10 +70,14 @@ G_DEFINE_TYPE_WITH_CODE (MetaShapedTexture, meta_shaped_texture, CLUTTER_TYPE_AC | ||||
| struct _MetaShapedTexturePrivate | ||||
| { | ||||
|   MetaTextureTower *paint_tower; | ||||
|   MetaTextureTower *paint_tower_right; | ||||
|  | ||||
|   CoglTexture *texture; | ||||
|   CoglTexture *texture_right; | ||||
|   CoglTexture *mask_texture; | ||||
|  | ||||
|   cairo_region_t *input_shape_region; | ||||
|  | ||||
|   /* The region containing only fully opaque pixels */ | ||||
|   cairo_region_t *opaque_region; | ||||
|  | ||||
| @@ -81,6 +87,7 @@ struct _MetaShapedTexturePrivate | ||||
|  | ||||
|   guint tex_width, tex_height; | ||||
|  | ||||
|   guint stereo : 1; | ||||
|   guint create_mipmaps : 1; | ||||
| }; | ||||
|  | ||||
| @@ -95,6 +102,7 @@ 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)); | ||||
| @@ -108,8 +116,10 @@ meta_shaped_texture_init (MetaShapedTexture *self) | ||||
|   priv = self->priv = META_SHAPED_TEXTURE_GET_PRIVATE (self); | ||||
|  | ||||
|   priv->paint_tower = meta_texture_tower_new (); | ||||
|   priv->paint_tower_right = NULL; /* demand create */ | ||||
|  | ||||
|   priv->texture = NULL; | ||||
|   priv->texture_right = NULL; | ||||
|   priv->mask_texture = NULL; | ||||
|   priv->create_mipmaps = TRUE; | ||||
| } | ||||
| @@ -146,11 +156,10 @@ meta_shaped_texture_dispose (GObject *object) | ||||
|   MetaShapedTexture *self = (MetaShapedTexture *) object; | ||||
|   MetaShapedTexturePrivate *priv = self->priv; | ||||
|  | ||||
|   if (priv->paint_tower) | ||||
|     meta_texture_tower_free (priv->paint_tower); | ||||
|   priv->paint_tower = NULL; | ||||
|  | ||||
|   g_clear_pointer (&priv->paint_tower, meta_texture_tower_free); | ||||
|   g_clear_pointer (&priv->paint_tower_right, meta_texture_tower_free); | ||||
|   g_clear_pointer (&priv->texture, cogl_object_unref); | ||||
|   g_clear_pointer (&priv->texture_right, cogl_object_unref); | ||||
|   g_clear_pointer (&priv->opaque_region, cairo_region_destroy); | ||||
|  | ||||
|   meta_shaped_texture_set_mask_texture (self, NULL); | ||||
| @@ -229,97 +238,20 @@ paint_clipped_rectangle (CoglFramebuffer       *fb, | ||||
| } | ||||
|  | ||||
| static void | ||||
| set_cogl_texture (MetaShapedTexture *stex, | ||||
|                   CoglTexture       *cogl_tex) | ||||
| paint_texture (MetaShapedTexture *stex, | ||||
| 	       CoglTexture       *paint_tex) | ||||
| { | ||||
|   MetaShapedTexturePrivate *priv; | ||||
|   guint width, height; | ||||
|  | ||||
|   g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); | ||||
|  | ||||
|   priv = stex->priv; | ||||
|  | ||||
|   if (priv->texture) | ||||
|     cogl_object_unref (priv->texture); | ||||
|  | ||||
|   priv->texture = cogl_tex; | ||||
|  | ||||
|   if (cogl_tex != NULL) | ||||
|     { | ||||
|       cogl_object_ref (cogl_tex); | ||||
|       width = cogl_texture_get_width (COGL_TEXTURE (cogl_tex)); | ||||
|       height = cogl_texture_get_height (COGL_TEXTURE (cogl_tex)); | ||||
|  | ||||
|       if (width != priv->tex_width || | ||||
|           height != priv->tex_height) | ||||
|         { | ||||
|           priv->tex_width = width; | ||||
|           priv->tex_height = height; | ||||
|  | ||||
|           clutter_actor_queue_relayout (CLUTTER_ACTOR (stex)); | ||||
|         } | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       /* size changed to 0 going to an invalid handle */ | ||||
|       priv->tex_width = 0; | ||||
|       priv->tex_height = 0; | ||||
|       clutter_actor_queue_relayout (CLUTTER_ACTOR (stex)); | ||||
|     } | ||||
|  | ||||
|   /* NB: We don't queue a redraw of the actor here because we don't | ||||
|    * know how much of the buffer has changed with respect to the | ||||
|    * previous buffer. We only queue a redraw in response to surface | ||||
|    * damage. */ | ||||
|  | ||||
|   if (priv->create_mipmaps) | ||||
|     meta_texture_tower_set_base_texture (priv->paint_tower, cogl_tex); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_shaped_texture_paint (ClutterActor *actor) | ||||
| { | ||||
|   MetaShapedTexture *stex = (MetaShapedTexture *) actor; | ||||
|   ClutterActor *actor = CLUTTER_ACTOR (stex); | ||||
|   MetaShapedTexturePrivate *priv = stex->priv; | ||||
|   guint tex_width, tex_height; | ||||
|   guchar opacity; | ||||
|   CoglContext *ctx; | ||||
|   CoglFramebuffer *fb; | ||||
|   CoglPipeline *pipeline = NULL; | ||||
|   CoglTexture *paint_tex; | ||||
|   ClutterActorBox alloc; | ||||
|   cairo_region_t *blended_region = NULL; | ||||
|   CoglPipelineFilter filter; | ||||
|  | ||||
|   if (priv->clip_region && cairo_region_is_empty (priv->clip_region)) | ||||
|     return; | ||||
|  | ||||
|   if (!CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (stex))) | ||||
|     clutter_actor_realize (CLUTTER_ACTOR (stex)); | ||||
|  | ||||
|   /* The GL EXT_texture_from_pixmap extension does allow for it to be | ||||
|    * used together with SGIS_generate_mipmap, however this is very | ||||
|    * rarely supported. Also, even when it is supported there | ||||
|    * are distinct performance implications from: | ||||
|    * | ||||
|    *  - Updating mipmaps that we don't need | ||||
|    *  - Having to reallocate pixmaps on the server into larger buffers | ||||
|    * | ||||
|    * So, we just unconditionally use our mipmap emulation code. If we | ||||
|    * wanted to use SGIS_generate_mipmap, we'd have to  query COGL to | ||||
|    * see if it was supported (no API currently), and then if and only | ||||
|    * if that was the case, set the clutter texture quality to HIGH. | ||||
|    * Setting the texture quality to high without SGIS_generate_mipmap | ||||
|    * support for TFP textures will result in fallbacks to XGetImage. | ||||
|    */ | ||||
|   if (priv->create_mipmaps) | ||||
|     paint_tex = meta_texture_tower_get_paint_texture (priv->paint_tower); | ||||
|   else | ||||
|     paint_tex = COGL_TEXTURE (priv->texture); | ||||
|  | ||||
|   if (paint_tex == NULL) | ||||
|     return; | ||||
|  | ||||
|   tex_width = priv->tex_width; | ||||
|   tex_height = priv->tex_height; | ||||
|  | ||||
| @@ -335,8 +267,8 @@ meta_shaped_texture_paint (ClutterActor *actor) | ||||
|   if (!clutter_actor_is_in_clone_paint (actor) && meta_actor_is_untransformed (actor, NULL, NULL)) | ||||
|     filter = COGL_PIPELINE_FILTER_NEAREST; | ||||
|  | ||||
|   ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); | ||||
|   fb = cogl_get_draw_framebuffer (); | ||||
|   ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); | ||||
|  | ||||
|   opacity = clutter_actor_get_paint_opacity (actor); | ||||
|   clutter_actor_get_allocation_box (actor, &alloc); | ||||
| @@ -459,6 +391,139 @@ meta_shaped_texture_paint (ClutterActor *actor) | ||||
|     cairo_region_destroy (blended_region); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_shaped_texture_paint (ClutterActor *actor) | ||||
| { | ||||
|   MetaShapedTexture *stex = (MetaShapedTexture *) actor; | ||||
|   MetaShapedTexturePrivate *priv = stex->priv; | ||||
|   CoglFramebuffer *fb; | ||||
|   gboolean stereo; | ||||
|   CoglTexture *paint_tex; | ||||
|   CoglTexture *paint_tex_right; | ||||
|  | ||||
|   if (priv->clip_region && cairo_region_is_empty (priv->clip_region)) | ||||
|     return; | ||||
|  | ||||
|   if (!CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (stex))) | ||||
|     clutter_actor_realize (CLUTTER_ACTOR (stex)); | ||||
|  | ||||
|   /* The GL EXT_texture_from_pixmap extension does allow for it to be | ||||
|    * used together with SGIS_generate_mipmap, however this is very | ||||
|    * rarely supported. Also, even when it is supported there | ||||
|    * are distinct performance implications from: | ||||
|    * | ||||
|    *  - Updating mipmaps that we don't need | ||||
|    *  - Having to reallocate pixmaps on the server into larger buffers | ||||
|    * | ||||
|    * So, we just unconditionally use our mipmap emulation code. If we | ||||
|    * wanted to use SGIS_generate_mipmap, we'd have to  query COGL to | ||||
|    * see if it was supported (no API currently), and then if and only | ||||
|    * if that was the case, set the clutter texture quality to HIGH. | ||||
|    * Setting the texture quality to high without SGIS_generate_mipmap | ||||
|    * support for TFP textures will result in fallbacks to XGetImage. | ||||
|    */ | ||||
|   if (priv->create_mipmaps) | ||||
|     paint_tex = meta_texture_tower_get_paint_texture (priv->paint_tower); | ||||
|   else | ||||
|     paint_tex = COGL_TEXTURE (priv->texture); | ||||
|  | ||||
|   fb = cogl_get_draw_framebuffer (); | ||||
|  | ||||
|   stereo = priv->stereo && cogl_framebuffer_get_is_stereo (fb); | ||||
|  | ||||
|   if (stereo) | ||||
|     { | ||||
|       if (priv->create_mipmaps) | ||||
| 	paint_tex_right = meta_texture_tower_get_paint_texture (priv->paint_tower_right); | ||||
|       else | ||||
| 	paint_tex_right = COGL_TEXTURE (priv->texture_right); | ||||
|     } | ||||
|   else | ||||
|     paint_tex_right = NULL; | ||||
|  | ||||
|   if (paint_tex != NULL) | ||||
|     { | ||||
|       if (stereo) | ||||
| 	cogl_framebuffer_set_stereo_mode (fb, COGL_STEREO_LEFT); | ||||
|       else | ||||
| 	cogl_framebuffer_set_stereo_mode (fb, COGL_STEREO_BOTH); | ||||
|  | ||||
|       paint_texture (stex, paint_tex); | ||||
|     } | ||||
|  | ||||
|   if (paint_tex_right != NULL) | ||||
|     { | ||||
|       cogl_framebuffer_set_stereo_mode (fb, COGL_STEREO_RIGHT); | ||||
|       paint_texture (stex, paint_tex_right); | ||||
|       cogl_framebuffer_set_stereo_mode (fb, COGL_STEREO_BOTH); | ||||
|     } | ||||
| } | ||||
|  | ||||
| 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, | ||||
| @@ -549,6 +614,12 @@ meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex, | ||||
|       priv->create_mipmaps = create_mipmaps; | ||||
|       base_texture = create_mipmaps ? priv->texture : NULL; | ||||
|       meta_texture_tower_set_base_texture (priv->paint_tower, base_texture); | ||||
|  | ||||
|       if (priv->stereo) | ||||
| 	{ | ||||
| 	  base_texture = create_mipmaps ? priv->texture_right : NULL; | ||||
| 	  meta_texture_tower_set_base_texture (priv->paint_tower_right, base_texture); | ||||
| 	} | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -647,6 +718,8 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex, | ||||
|     return FALSE; | ||||
|  | ||||
|   meta_texture_tower_update_area (priv->paint_tower, x, y, width, height); | ||||
|   if (priv->stereo) | ||||
|     meta_texture_tower_update_area (priv->paint_tower_right, x, y, width, height); | ||||
|  | ||||
|   unobscured_region = effective_unobscured_region (stex); | ||||
|   if (unobscured_region) | ||||
| @@ -678,6 +751,73 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex, | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| set_cogl_texture (MetaShapedTexture *stex, | ||||
|                   CoglTexture       *cogl_tex, | ||||
| 		  gboolean           stereo) | ||||
| { | ||||
|   MetaShapedTexturePrivate *priv; | ||||
|   guint width, height; | ||||
|  | ||||
|   g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); | ||||
|  | ||||
|   priv = stex->priv; | ||||
|  | ||||
|   if (priv->texture != NULL) | ||||
|     cogl_object_unref (priv->texture); | ||||
|   if (priv->texture_right != NULL) | ||||
|     cogl_object_unref (priv->texture_right); | ||||
|  | ||||
|   priv->stereo = stereo; | ||||
|  | ||||
|   priv->texture = cogl_tex; | ||||
|   if (priv->stereo) | ||||
|     { | ||||
|       priv->texture_right = cogl_texture_pixmap_x11_new_right ((CoglTexturePixmapX11 *)cogl_tex); | ||||
|       if (priv->paint_tower_right == NULL) | ||||
| 	priv->paint_tower_right = meta_texture_tower_new (); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       priv->texture_right = NULL; | ||||
|       g_clear_pointer (&priv->paint_tower_right, meta_texture_tower_free); | ||||
|     } | ||||
|  | ||||
|   if (cogl_tex != NULL) | ||||
|     { | ||||
|       width = cogl_texture_get_width (COGL_TEXTURE (cogl_tex)); | ||||
|       height = cogl_texture_get_height (COGL_TEXTURE (cogl_tex)); | ||||
|  | ||||
|       if (width != priv->tex_width || | ||||
|           height != priv->tex_height) | ||||
|         { | ||||
|           priv->tex_width = width; | ||||
|           priv->tex_height = height; | ||||
|  | ||||
|           clutter_actor_queue_relayout (CLUTTER_ACTOR (stex)); | ||||
|         } | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       /* size changed to 0 going to an invalid texture */ | ||||
|       priv->tex_width = 0; | ||||
|       priv->tex_height = 0; | ||||
|       clutter_actor_queue_relayout (CLUTTER_ACTOR (stex)); | ||||
|     } | ||||
|  | ||||
|   /* NB: We don't queue a redraw of the actor here because we don't | ||||
|    * know how much of the buffer has changed with respect to the | ||||
|    * previous buffer. We only queue a redraw in response to surface | ||||
|    * damage. */ | ||||
|  | ||||
|   if (priv->create_mipmaps) | ||||
|     { | ||||
|       meta_texture_tower_set_base_texture (priv->paint_tower, cogl_tex); | ||||
|       if (priv->stereo) | ||||
| 	meta_texture_tower_set_base_texture (priv->paint_tower_right, priv->texture_right); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_shaped_texture_set_texture: | ||||
|  * @stex: The #MetaShapedTexture | ||||
| @@ -685,11 +825,12 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex, | ||||
|  */ | ||||
| void | ||||
| meta_shaped_texture_set_texture (MetaShapedTexture *stex, | ||||
|                                  CoglTexture       *texture) | ||||
|                                  CoglTexture       *texture, | ||||
| 				 gboolean           stereo) | ||||
| { | ||||
|   g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); | ||||
|  | ||||
|   set_cogl_texture (stex, texture); | ||||
|   set_cogl_texture (stex, texture, stereo); | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -705,6 +846,41 @@ 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 | ||||
|   | ||||
| @@ -1,176 +0,0 @@ | ||||
| /* | ||||
|  * Copyright (C) 2014 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Jasper St. Pierre <jstpierre@mecheye.net> | ||||
|  */ | ||||
|  | ||||
| #include <config.h> | ||||
|  | ||||
| #include "meta-stage.h" | ||||
|  | ||||
| #include "meta-cursor-private.h" | ||||
| #include "meta-backend.h" | ||||
| #include <meta/util.h> | ||||
|  | ||||
| struct _MetaStagePrivate { | ||||
|   CoglPipeline *pipeline; | ||||
|   gboolean should_paint_cursor; | ||||
|  | ||||
|   MetaCursorReference *cursor; | ||||
|  | ||||
|   MetaRectangle current_rect; | ||||
|   MetaRectangle previous_rect; | ||||
|   gboolean previous_is_valid; | ||||
| }; | ||||
| typedef struct _MetaStagePrivate MetaStagePrivate; | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_PRIVATE (MetaStage, meta_stage, CLUTTER_TYPE_STAGE); | ||||
|  | ||||
| static void | ||||
| update_pipeline (MetaStage *stage) | ||||
| { | ||||
|   MetaStagePrivate *priv = meta_stage_get_instance_private (stage); | ||||
|  | ||||
|   if (priv->cursor) | ||||
|     { | ||||
|       CoglTexture *texture = meta_cursor_reference_get_cogl_texture (priv->cursor, NULL, NULL); | ||||
|       cogl_pipeline_set_layer_texture (priv->pipeline, 0, texture); | ||||
|     } | ||||
|   else | ||||
|     cogl_pipeline_set_layer_texture (priv->pipeline, 0, NULL); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_stage_finalize (GObject *object) | ||||
| { | ||||
|   MetaStage *stage = META_STAGE (object); | ||||
|   MetaStagePrivate *priv = meta_stage_get_instance_private (stage); | ||||
|  | ||||
|   if (priv->pipeline) | ||||
|     cogl_object_unref (priv->pipeline); | ||||
| } | ||||
|  | ||||
| static void | ||||
| paint_cursor (MetaStage *stage) | ||||
| { | ||||
|   MetaStagePrivate *priv = meta_stage_get_instance_private (stage); | ||||
|  | ||||
|   g_assert (meta_is_wayland_compositor ()); | ||||
|  | ||||
|   if (!priv->cursor) | ||||
|     return; | ||||
|  | ||||
|   cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (), | ||||
|                                    priv->pipeline, | ||||
|                                    priv->current_rect.x, | ||||
|                                    priv->current_rect.y, | ||||
|                                    priv->current_rect.x + | ||||
|                                    priv->current_rect.width, | ||||
|                                    priv->current_rect.y + | ||||
|                                    priv->current_rect.height); | ||||
|  | ||||
|   priv->previous_rect = priv->current_rect; | ||||
|   priv->previous_is_valid = TRUE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_stage_paint (ClutterActor *actor) | ||||
| { | ||||
|   MetaStage *stage = META_STAGE (actor); | ||||
|  | ||||
|   CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor); | ||||
|  | ||||
|   if (meta_is_wayland_compositor ()) | ||||
|     paint_cursor (stage); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_stage_class_init (MetaStageClass *klass) | ||||
| { | ||||
|   ClutterActorClass *actor_class = (ClutterActorClass *) klass; | ||||
|   GObjectClass *object_class = (GObjectClass *) klass; | ||||
|  | ||||
|   object_class->finalize = meta_stage_finalize; | ||||
|  | ||||
|   actor_class->paint = meta_stage_paint; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_stage_init (MetaStage *stage) | ||||
| { | ||||
|   CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); | ||||
|   MetaStagePrivate *priv = meta_stage_get_instance_private (stage); | ||||
|  | ||||
|   priv->pipeline = cogl_pipeline_new (ctx); | ||||
|  | ||||
|   clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), FALSE); | ||||
| } | ||||
|  | ||||
| ClutterActor * | ||||
| meta_stage_new (void) | ||||
| { | ||||
|   return g_object_new (META_TYPE_STAGE, | ||||
|                        "cursor-visible", FALSE, | ||||
|                        NULL); | ||||
| } | ||||
|  | ||||
| static void | ||||
| queue_redraw (MetaStage *stage) | ||||
| { | ||||
|   MetaStagePrivate *priv = meta_stage_get_instance_private (stage); | ||||
|   cairo_rectangle_int_t clip; | ||||
|  | ||||
|   /* Clear the location the cursor was at before, if we need to. */ | ||||
|   if (priv->previous_is_valid) | ||||
|     { | ||||
|       clip.x = priv->previous_rect.x; | ||||
|       clip.y = priv->previous_rect.y; | ||||
|       clip.width = priv->previous_rect.width; | ||||
|       clip.height = priv->previous_rect.height; | ||||
|       clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &clip); | ||||
|       priv->previous_is_valid = FALSE; | ||||
|     } | ||||
|  | ||||
|   /* And queue a redraw for the current cursor location. */ | ||||
|   if (priv->cursor) | ||||
|     { | ||||
|       clip.x = priv->current_rect.x; | ||||
|       clip.y = priv->current_rect.y; | ||||
|       clip.width = priv->current_rect.width; | ||||
|       clip.height = priv->current_rect.height; | ||||
|       clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &clip); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_stage_set_cursor (MetaStage           *stage, | ||||
|                        MetaCursorReference *cursor, | ||||
|                        MetaRectangle       *rect) | ||||
| { | ||||
|   MetaStagePrivate *priv = meta_stage_get_instance_private (stage); | ||||
|  | ||||
|   if (priv->cursor != cursor) | ||||
|     { | ||||
|       priv->cursor = cursor; | ||||
|       update_pipeline (stage); | ||||
|     } | ||||
|  | ||||
|   priv->current_rect = *rect; | ||||
|   queue_redraw (stage); | ||||
| } | ||||
| @@ -1,59 +0,0 @@ | ||||
| /* | ||||
|  * Copyright (C) 2012 Intel Corporation | ||||
|  * | ||||
|  * 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. | ||||
|  */ | ||||
|  | ||||
| #ifndef META_STAGE_H | ||||
| #define META_STAGE_H | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| #include "meta-cursor.h" | ||||
| #include <meta/boxes.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define META_TYPE_STAGE            (meta_stage_get_type ()) | ||||
| #define META_STAGE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_STAGE, MetaStage)) | ||||
| #define META_STAGE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_STAGE, MetaStageClass)) | ||||
| #define META_IS_STAGE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_STAGE)) | ||||
| #define META_IS_STAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_STAGE)) | ||||
| #define META_STAGE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_STAGE, MetaStageClass)) | ||||
|  | ||||
| typedef struct _MetaStage      MetaStage; | ||||
| typedef struct _MetaStageClass MetaStageClass; | ||||
|  | ||||
| struct _MetaStageClass | ||||
| { | ||||
|   ClutterStageClass parent_class; | ||||
| }; | ||||
|  | ||||
| struct _MetaStage | ||||
| { | ||||
|   ClutterStage parent; | ||||
| }; | ||||
|  | ||||
| GType             meta_stage_get_type                (void) G_GNUC_CONST; | ||||
|  | ||||
| ClutterActor     *meta_stage_new                     (void); | ||||
|  | ||||
| void meta_stage_set_cursor (MetaStage           *stage, | ||||
|                             MetaCursorReference *cursor, | ||||
|                             MetaRectangle       *rect); | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* META_STAGE_H */ | ||||
| @@ -1,291 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (C) 2013 Red Hat | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, but | ||||
|  * WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||||
|  * 02111-1307, USA. | ||||
|  * | ||||
|  * Written by: | ||||
|  *     Jasper St. Pierre <jstpierre@mecheye.net> | ||||
|  */ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #include "meta-surface-actor-wayland.h" | ||||
|  | ||||
| #include <cogl/cogl-wayland-server.h> | ||||
| #include "meta-shaped-texture-private.h" | ||||
|  | ||||
| #include "wayland/meta-wayland-private.h" | ||||
|  | ||||
| struct _MetaSurfaceActorWaylandPrivate | ||||
| { | ||||
|   MetaWaylandSurface *surface; | ||||
|   MetaWaylandBuffer *buffer; | ||||
|   struct wl_listener buffer_destroy_listener; | ||||
| }; | ||||
| typedef struct _MetaSurfaceActorWaylandPrivate MetaSurfaceActorWaylandPrivate; | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_PRIVATE (MetaSurfaceActorWayland, meta_surface_actor_wayland, META_TYPE_SURFACE_ACTOR) | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_handle_buffer_destroy (struct wl_listener *listener, void *data) | ||||
| { | ||||
|   MetaSurfaceActorWaylandPrivate *priv = wl_container_of (listener, priv, buffer_destroy_listener); | ||||
|  | ||||
|   /* If the buffer is destroyed while we're attached to it, | ||||
|    * we want to unset priv->buffer so we don't access freed | ||||
|    * memory. Keep the texture set however so the user doesn't | ||||
|    * see the window disappear. */ | ||||
|   priv->buffer = NULL; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_wayland_process_damage (MetaSurfaceActor *actor, | ||||
|                                            int x, int y, int width, int height) | ||||
| { | ||||
|   MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor); | ||||
|   MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self); | ||||
|  | ||||
|   if (priv->buffer) | ||||
|     { | ||||
|       struct wl_resource *resource = priv->buffer->resource; | ||||
|       struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (resource); | ||||
|  | ||||
|       if (shm_buffer) | ||||
|         { | ||||
|           CoglTexture2D *texture = COGL_TEXTURE_2D (priv->buffer->texture); | ||||
|           cogl_wayland_texture_set_region_from_shm_buffer (texture, x, y, width, height, shm_buffer, x, y, 0, NULL); | ||||
|         } | ||||
|  | ||||
|       meta_surface_actor_update_area (META_SURFACE_ACTOR (self), x, y, width, height); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_wayland_pre_paint (MetaSurfaceActor *actor) | ||||
| { | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_surface_actor_wayland_is_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 int | ||||
| get_output_scale (int output_id) | ||||
| { | ||||
|   MetaMonitorManager *monitor_manager = meta_monitor_manager_get (); | ||||
|   MetaOutput *outputs; | ||||
|   guint n_outputs, i; | ||||
|   int output_scale = 1; | ||||
|  | ||||
|   outputs = meta_monitor_manager_get_outputs (monitor_manager, &n_outputs); | ||||
|  | ||||
|   for (i = 0; i < n_outputs; i++) | ||||
|     { | ||||
|       if (outputs[i].output_id == output_id) | ||||
|         { | ||||
|           output_scale = outputs[i].scale; | ||||
|           break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   return output_scale; | ||||
| } | ||||
|  | ||||
| double | ||||
| meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *actor) | ||||
| { | ||||
|    MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (actor); | ||||
|    MetaWaylandSurface *surface = priv->surface; | ||||
|    MetaWindow *window = surface->window; | ||||
|    int output_scale = 1; | ||||
|  | ||||
|    while (surface) | ||||
|     { | ||||
|       if (surface->window) | ||||
|         { | ||||
|           window = surface->window; | ||||
|           break; | ||||
|         } | ||||
|       surface = surface->sub.parent; | ||||
|     } | ||||
|  | ||||
|    /* XXX: We do not handle x11 clients yet */ | ||||
|    if (window && window->client_type != META_WINDOW_CLIENT_TYPE_X11) | ||||
|      output_scale = get_output_scale (window->monitor->output_id); | ||||
|  | ||||
|    return (double)output_scale / (double)priv->surface->scale; | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_surface_actor_wayland_scale_texture (MetaSurfaceActorWayland *actor) | ||||
| { | ||||
|   MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (actor)); | ||||
|   double output_scale = meta_surface_actor_wayland_get_scale (actor); | ||||
|  | ||||
|   clutter_actor_set_scale (CLUTTER_ACTOR (stex), output_scale, output_scale); | ||||
| } | ||||
|  | ||||
| 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_get_preferred_width  (ClutterActor *self, | ||||
|                                                  gfloat        for_height, | ||||
|                                                  gfloat       *min_width_p, | ||||
|                                                  gfloat       *natural_width_p) | ||||
| { | ||||
|   MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); | ||||
|   double scale = meta_surface_actor_wayland_get_scale (META_SURFACE_ACTOR_WAYLAND (self)); | ||||
|  | ||||
|   clutter_actor_get_preferred_width (CLUTTER_ACTOR (stex), for_height, min_width_p, natural_width_p); | ||||
|  | ||||
|   if (min_width_p) | ||||
|      *min_width_p *= scale; | ||||
|  | ||||
|   if (natural_width_p) | ||||
|     *natural_width_p *= scale; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_wayland_get_preferred_height  (ClutterActor *self, | ||||
|                                                   gfloat        for_width, | ||||
|                                                   gfloat       *min_height_p, | ||||
|                                                   gfloat       *natural_height_p) | ||||
| { | ||||
|   MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); | ||||
|   double scale = meta_surface_actor_wayland_get_scale (META_SURFACE_ACTOR_WAYLAND (self)); | ||||
|  | ||||
|   clutter_actor_get_preferred_height (CLUTTER_ACTOR (stex), for_width, min_height_p, natural_height_p); | ||||
|  | ||||
|   if (min_height_p) | ||||
|      *min_height_p *= scale; | ||||
|  | ||||
|   if (natural_height_p) | ||||
|     *natural_height_p *= scale; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_wayland_dispose (GObject *object) | ||||
| { | ||||
|   MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (object); | ||||
|  | ||||
|   meta_surface_actor_wayland_set_buffer (self, NULL); | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_surface_actor_wayland_parent_class)->dispose (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass) | ||||
| { | ||||
|   MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass); | ||||
|   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|  | ||||
|   actor_class->get_preferred_width = meta_surface_actor_wayland_get_preferred_width; | ||||
|   actor_class->get_preferred_height = meta_surface_actor_wayland_get_preferred_height; | ||||
|  | ||||
|   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_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; | ||||
|  | ||||
|   object_class->dispose = meta_surface_actor_wayland_dispose; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_wayland_init (MetaSurfaceActorWayland *self) | ||||
| { | ||||
|   MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self); | ||||
|  | ||||
|   priv->buffer_destroy_listener.notify = meta_surface_actor_handle_buffer_destroy; | ||||
| } | ||||
|  | ||||
| MetaSurfaceActor * | ||||
| meta_surface_actor_wayland_new (MetaWaylandSurface *surface) | ||||
| { | ||||
|   MetaSurfaceActorWayland *self = g_object_new (META_TYPE_SURFACE_ACTOR_WAYLAND, NULL); | ||||
|   MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self); | ||||
|  | ||||
|   g_assert (meta_is_wayland_compositor ()); | ||||
|  | ||||
|   priv->surface = surface; | ||||
|  | ||||
|   return META_SURFACE_ACTOR (self); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self, | ||||
|                                        MetaWaylandBuffer       *buffer) | ||||
| { | ||||
|   MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self); | ||||
|   MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); | ||||
|  | ||||
|   if (priv->buffer) | ||||
|     wl_list_remove (&priv->buffer_destroy_listener.link); | ||||
|  | ||||
|   priv->buffer = buffer; | ||||
|  | ||||
|   if (priv->buffer) | ||||
|     { | ||||
|       wl_signal_add (&priv->buffer->destroy_signal, &priv->buffer_destroy_listener); | ||||
|       meta_shaped_texture_set_texture (stex, priv->buffer->texture); | ||||
|     } | ||||
|   else | ||||
|     meta_shaped_texture_set_texture (stex, NULL); | ||||
| } | ||||
|  | ||||
| MetaWaylandSurface * | ||||
| meta_surface_actor_wayland_get_surface (MetaSurfaceActorWayland *self) | ||||
| { | ||||
|   MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self); | ||||
|   return priv->surface; | ||||
| } | ||||
| @@ -1,69 +0,0 @@ | ||||
| /* -*- 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); | ||||
|  | ||||
| double meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *actor); | ||||
|  | ||||
| void meta_surface_actor_wayland_scale_texture (MetaSurfaceActorWayland *actor); | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __META_SURFACE_ACTOR_WAYLAND_H__ */ | ||||
| @@ -1,460 +0,0 @@ | ||||
| /* -*- 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 <cogl/cogl-texture-pixmap-x11.h> | ||||
|  | ||||
| #include <meta/errors.h> | ||||
| #include "window-private.h" | ||||
| #include "meta-shaped-texture-private.h" | ||||
| #include "meta-cullable.h" | ||||
| #include "x11/window-x11.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 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_x11_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 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 (meta_surface_actor_is_argb32 (actor) && !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_x11_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_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_x11_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); | ||||
|  | ||||
|   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; | ||||
| } | ||||
| @@ -1,69 +0,0 @@ | ||||
| /* -*- 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__ */ | ||||
| @@ -1,338 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /** | ||||
|  * SECTION:meta-surface-actor | ||||
|  * @title: MetaSurfaceActor | ||||
|  * @short_description: An actor representing a surface in the scene graph | ||||
|  * | ||||
|  * A surface can be either a shaped texture, or a group of shaped texture, | ||||
|  * used to draw the content of a window. | ||||
|  */ | ||||
|  | ||||
| #include <config.h> | ||||
|  | ||||
| #include "meta-surface-actor.h" | ||||
|  | ||||
| #include <clutter/clutter.h> | ||||
| #include <meta/meta-shaped-texture.h> | ||||
| #include "meta-cullable.h" | ||||
| #include "meta-shaped-texture-private.h" | ||||
|  | ||||
| struct _MetaSurfaceActorPrivate | ||||
| { | ||||
|   MetaShapedTexture *texture; | ||||
|  | ||||
|   cairo_region_t *input_region; | ||||
|  | ||||
|   /* Freeze/thaw accounting */ | ||||
|   guint needs_damage_all : 1; | ||||
|   guint frozen : 1; | ||||
| }; | ||||
|  | ||||
| static void cullable_iface_init (MetaCullableInterface *iface); | ||||
|  | ||||
| G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaSurfaceActor, meta_surface_actor, CLUTTER_TYPE_ACTOR, | ||||
|                                   G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init)); | ||||
|  | ||||
| enum { | ||||
|   REPAINT_SCHEDULED, | ||||
|  | ||||
|   LAST_SIGNAL, | ||||
| }; | ||||
|  | ||||
| static guint signals[LAST_SIGNAL]; | ||||
|  | ||||
| gboolean | ||||
| meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor      *self, | ||||
|                                           cairo_rectangle_int_t *unobscured_bounds) | ||||
| { | ||||
|   MetaSurfaceActorPrivate *priv = self->priv; | ||||
|   return meta_shaped_texture_get_unobscured_bounds (priv->texture, unobscured_bounds); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_pick (ClutterActor       *actor, | ||||
|                          const ClutterColor *color) | ||||
| { | ||||
|   MetaSurfaceActor *self = META_SURFACE_ACTOR (actor); | ||||
|   MetaSurfaceActorPrivate *priv = self->priv; | ||||
|  | ||||
|   if (!clutter_actor_should_pick_paint (actor)) | ||||
|     return; | ||||
|  | ||||
|   /* If there is no region then use the regular pick */ | ||||
|   if (priv->input_region == NULL) | ||||
|     CLUTTER_ACTOR_CLASS (meta_surface_actor_parent_class)->pick (actor, color); | ||||
|   else | ||||
|     { | ||||
|       int n_rects; | ||||
|       float *rectangles; | ||||
|       int i; | ||||
|       CoglPipeline *pipeline; | ||||
|       CoglContext *ctx; | ||||
|       CoglFramebuffer *fb; | ||||
|       CoglColor cogl_color; | ||||
|  | ||||
|       n_rects = cairo_region_num_rectangles (priv->input_region); | ||||
|       rectangles = g_alloca (sizeof (float) * 4 * n_rects); | ||||
|  | ||||
|       for (i = 0; i < n_rects; i++) | ||||
|         { | ||||
|           cairo_rectangle_int_t rect; | ||||
|           int pos = i * 4; | ||||
|  | ||||
|           cairo_region_get_rectangle (priv->input_region, i, &rect); | ||||
|  | ||||
|           rectangles[pos + 0] = rect.x; | ||||
|           rectangles[pos + 1] = rect.y; | ||||
|           rectangles[pos + 2] = rect.x + rect.width; | ||||
|           rectangles[pos + 3] = rect.y + rect.height; | ||||
|         } | ||||
|  | ||||
|       ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); | ||||
|       fb = cogl_get_draw_framebuffer (); | ||||
|  | ||||
|       cogl_color_init_from_4ub (&cogl_color, color->red, color->green, color->blue, color->alpha); | ||||
|  | ||||
|       pipeline = cogl_pipeline_new (ctx); | ||||
|       cogl_pipeline_set_color (pipeline, &cogl_color); | ||||
|       cogl_framebuffer_draw_rectangles (fb, pipeline, rectangles, n_rects); | ||||
|       cogl_object_unref (pipeline); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_dispose (GObject *object) | ||||
| { | ||||
|   MetaSurfaceActor *self = META_SURFACE_ACTOR (object); | ||||
|   MetaSurfaceActorPrivate *priv = self->priv; | ||||
|  | ||||
|   g_clear_pointer (&priv->input_region, cairo_region_destroy); | ||||
|  | ||||
|   G_OBJECT_CLASS (meta_surface_actor_parent_class)->dispose (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_class_init (MetaSurfaceActorClass *klass) | ||||
| { | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); | ||||
|  | ||||
|   object_class->dispose = meta_surface_actor_dispose; | ||||
|   actor_class->pick = meta_surface_actor_pick; | ||||
|  | ||||
|   signals[REPAINT_SCHEDULED] = g_signal_new ("repaint-scheduled", | ||||
|                                              G_TYPE_FROM_CLASS (object_class), | ||||
|                                              G_SIGNAL_RUN_LAST, | ||||
|                                              0, | ||||
|                                              NULL, NULL, NULL, | ||||
|                                              G_TYPE_NONE, 0); | ||||
|  | ||||
|   g_type_class_add_private (klass, sizeof (MetaSurfaceActorPrivate)); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_cull_out (MetaCullable   *cullable, | ||||
|                              cairo_region_t *unobscured_region, | ||||
|                              cairo_region_t *clip_region) | ||||
| { | ||||
|   meta_cullable_cull_out_children (cullable, unobscured_region, clip_region); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_reset_culling (MetaCullable *cullable) | ||||
| { | ||||
|   meta_cullable_reset_culling_children (cullable); | ||||
| } | ||||
|  | ||||
| static void | ||||
| cullable_iface_init (MetaCullableInterface *iface) | ||||
| { | ||||
|   iface->cull_out = meta_surface_actor_cull_out; | ||||
|   iface->reset_culling = meta_surface_actor_reset_culling; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_init (MetaSurfaceActor *self) | ||||
| { | ||||
|   MetaSurfaceActorPrivate *priv; | ||||
|  | ||||
|   priv = self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, | ||||
|                                                    META_TYPE_SURFACE_ACTOR, | ||||
|                                                    MetaSurfaceActorPrivate); | ||||
|  | ||||
|   priv->texture = META_SHAPED_TEXTURE (meta_shaped_texture_new ()); | ||||
|   clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->texture)); | ||||
| } | ||||
|  | ||||
| cairo_surface_t * | ||||
| meta_surface_actor_get_image (MetaSurfaceActor      *self, | ||||
|                               cairo_rectangle_int_t *clip) | ||||
| { | ||||
|   return meta_shaped_texture_get_image (self->priv->texture, clip); | ||||
| } | ||||
|  | ||||
| MetaShapedTexture * | ||||
| meta_surface_actor_get_texture (MetaSurfaceActor *self) | ||||
| { | ||||
|   return self->priv->texture; | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_surface_actor_update_area (MetaSurfaceActor *self, | ||||
|                                 int x, int y, int width, int height) | ||||
| { | ||||
|   MetaSurfaceActorPrivate *priv = self->priv; | ||||
|  | ||||
|   if (meta_shaped_texture_update_area (priv->texture, x, y, width, height)) | ||||
|     g_signal_emit (self, signals[REPAINT_SCHEDULED], 0); | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_surface_actor_is_obscured (MetaSurfaceActor *self) | ||||
| { | ||||
|   MetaSurfaceActorPrivate *priv = self->priv; | ||||
|   return meta_shaped_texture_is_obscured (priv->texture); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_surface_actor_set_input_region (MetaSurfaceActor *self, | ||||
|                                      cairo_region_t   *region) | ||||
| { | ||||
|   MetaSurfaceActorPrivate *priv = self->priv; | ||||
|  | ||||
|   if (priv->input_region) | ||||
|     cairo_region_destroy (priv->input_region); | ||||
|  | ||||
|   if (region) | ||||
|     priv->input_region = cairo_region_reference (region); | ||||
|   else | ||||
|     priv->input_region = NULL; | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_surface_actor_set_opaque_region (MetaSurfaceActor *self, | ||||
|                                       cairo_region_t   *region) | ||||
| { | ||||
|   MetaSurfaceActorPrivate *priv = self->priv; | ||||
|   meta_shaped_texture_set_opaque_region (priv->texture, region); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| is_frozen (MetaSurfaceActor *self) | ||||
| { | ||||
|   MetaSurfaceActorPrivate *priv = self->priv; | ||||
|   return priv->frozen; | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_surface_actor_process_damage (MetaSurfaceActor *self, | ||||
|                                    int x, int y, int width, int height) | ||||
| { | ||||
|   MetaSurfaceActorPrivate *priv = self->priv; | ||||
|  | ||||
|   if (is_frozen (self)) | ||||
|     { | ||||
|       /* The window is frozen due to an effect in progress: we ignore damage | ||||
|        * here on the off chance that this will stop the corresponding | ||||
|        * texture_from_pixmap from being update. | ||||
|        * | ||||
|        * needs_damage_all tracks that some unknown damage happened while the | ||||
|        * window was frozen so that when the window becomes unfrozen we can | ||||
|        * issue a full window update to cover any lost damage. | ||||
|        * | ||||
|        * It should be noted that this is an unreliable mechanism since it's | ||||
|        * quite likely that drivers will aim to provide a zero-copy | ||||
|        * implementation of the texture_from_pixmap extension and in those cases | ||||
|        * any drawing done to the window is always immediately reflected in the | ||||
|        * texture regardless of damage event handling. | ||||
|        */ | ||||
|       priv->needs_damage_all = TRUE; | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   META_SURFACE_ACTOR_GET_CLASS (self)->process_damage (self, x, y, width, height); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_surface_actor_pre_paint (MetaSurfaceActor *self) | ||||
| { | ||||
|   META_SURFACE_ACTOR_GET_CLASS (self)->pre_paint (self); | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_surface_actor_is_argb32 (MetaSurfaceActor *self) | ||||
| { | ||||
|   MetaShapedTexture *stex = meta_surface_actor_get_texture (self); | ||||
|   CoglTexture *texture = meta_shaped_texture_get_texture (stex); | ||||
|  | ||||
|   /* If we don't have a texture, like during initialization, assume | ||||
|    * that we're ARGB32. */ | ||||
|   if (!texture) | ||||
|     return TRUE; | ||||
|  | ||||
|   switch (cogl_texture_get_components (texture)) | ||||
|     { | ||||
|     case COGL_TEXTURE_COMPONENTS_A: | ||||
|     case COGL_TEXTURE_COMPONENTS_RGBA: | ||||
|       return TRUE; | ||||
|     case COGL_TEXTURE_COMPONENTS_RG: | ||||
|     case COGL_TEXTURE_COMPONENTS_RGB: | ||||
|     case COGL_TEXTURE_COMPONENTS_DEPTH: | ||||
|       return FALSE; | ||||
|     default: | ||||
|       g_assert_not_reached (); | ||||
|     } | ||||
| } | ||||
|  | ||||
| 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); | ||||
| } | ||||
| @@ -1,85 +0,0 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| #ifndef META_SURFACE_ACTOR_PRIVATE_H | ||||
| #define META_SURFACE_ACTOR_PRIVATE_H | ||||
|  | ||||
| #include <config.h> | ||||
|  | ||||
| #include <meta/meta-shaped-texture.h> | ||||
| #include <meta/window.h> | ||||
|  | ||||
| G_BEGIN_DECLS | ||||
|  | ||||
| #define META_TYPE_SURFACE_ACTOR            (meta_surface_actor_get_type()) | ||||
| #define META_SURFACE_ACTOR(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SURFACE_ACTOR, MetaSurfaceActor)) | ||||
| #define META_SURFACE_ACTOR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_SURFACE_ACTOR, MetaSurfaceActorClass)) | ||||
| #define META_IS_SURFACE_ACTOR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SURFACE_ACTOR)) | ||||
| #define META_IS_SURFACE_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_SURFACE_ACTOR)) | ||||
| #define META_SURFACE_ACTOR_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_SURFACE_ACTOR, MetaSurfaceActorClass)) | ||||
|  | ||||
| typedef struct _MetaSurfaceActor        MetaSurfaceActor; | ||||
| typedef struct _MetaSurfaceActorClass   MetaSurfaceActorClass; | ||||
| typedef struct _MetaSurfaceActorPrivate MetaSurfaceActorPrivate; | ||||
|  | ||||
| struct _MetaSurfaceActorClass | ||||
| { | ||||
|   /*< private >*/ | ||||
|   ClutterActorClass parent_class; | ||||
|  | ||||
|   void     (* process_damage)    (MetaSurfaceActor *actor, | ||||
|                                   int x, int y, int width, int height); | ||||
|   void     (* pre_paint)         (MetaSurfaceActor *actor); | ||||
|   gboolean (* is_visible)        (MetaSurfaceActor *actor); | ||||
|  | ||||
|   gboolean (* should_unredirect) (MetaSurfaceActor *actor); | ||||
|   void     (* set_unredirected)  (MetaSurfaceActor *actor, | ||||
|                                   gboolean          unredirected); | ||||
|   gboolean (* is_unredirected)   (MetaSurfaceActor *actor); | ||||
|  | ||||
|   MetaWindow *(* get_window)      (MetaSurfaceActor *actor); | ||||
| }; | ||||
|  | ||||
| struct _MetaSurfaceActor | ||||
| { | ||||
|   ClutterActor            parent; | ||||
|  | ||||
|   MetaSurfaceActorPrivate *priv; | ||||
| }; | ||||
|  | ||||
| GType meta_surface_actor_get_type (void); | ||||
|  | ||||
| cairo_surface_t *meta_surface_actor_get_image (MetaSurfaceActor      *self, | ||||
|                                                cairo_rectangle_int_t *clip); | ||||
|  | ||||
| MetaShapedTexture *meta_surface_actor_get_texture (MetaSurfaceActor *self); | ||||
| MetaWindow        *meta_surface_actor_get_window  (MetaSurfaceActor *self); | ||||
|  | ||||
| gboolean meta_surface_actor_is_obscured (MetaSurfaceActor *self); | ||||
| gboolean meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor      *self, | ||||
|                                                    cairo_rectangle_int_t *unobscured_bounds); | ||||
|  | ||||
| void meta_surface_actor_set_input_region (MetaSurfaceActor *self, | ||||
|                                           cairo_region_t   *region); | ||||
| void meta_surface_actor_set_opaque_region (MetaSurfaceActor *self, | ||||
|                                            cairo_region_t   *region); | ||||
|  | ||||
| void meta_surface_actor_update_area (MetaSurfaceActor *actor, | ||||
|                                      int x, int y, int width, int height); | ||||
|  | ||||
| void meta_surface_actor_process_damage (MetaSurfaceActor *actor, | ||||
|                                         int x, int y, int width, int height); | ||||
| void meta_surface_actor_pre_paint (MetaSurfaceActor *actor); | ||||
| gboolean meta_surface_actor_is_argb32 (MetaSurfaceActor *actor); | ||||
| gboolean meta_surface_actor_is_visible (MetaSurfaceActor *actor); | ||||
|  | ||||
| void meta_surface_actor_set_frozen (MetaSurfaceActor *actor, | ||||
|                                     gboolean          frozen); | ||||
|  | ||||
| gboolean meta_surface_actor_should_unredirect (MetaSurfaceActor *actor); | ||||
| void meta_surface_actor_set_unredirected (MetaSurfaceActor *actor, | ||||
|                                           gboolean          unredirected); | ||||
| gboolean meta_surface_actor_is_unredirected (MetaSurfaceActor *actor); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* META_SURFACE_ACTOR_PRIVATE_H */ | ||||
| @@ -7,7 +7,6 @@ | ||||
|  | ||||
| #include <X11/extensions/Xdamage.h> | ||||
| #include <meta/compositor-mutter.h> | ||||
| #include "meta-surface-actor.h" | ||||
|  | ||||
| MetaWindowActor *meta_window_actor_new (MetaWindow *window); | ||||
|  | ||||
| @@ -25,8 +24,8 @@ void meta_window_actor_unmaximize (MetaWindowActor *self, | ||||
|                                    MetaRectangle   *old_rect, | ||||
|                                    MetaRectangle   *new_rect); | ||||
|  | ||||
| void meta_window_actor_process_x11_damage (MetaWindowActor    *self, | ||||
|                                            XDamageNotifyEvent *event); | ||||
| void meta_window_actor_process_damage (MetaWindowActor    *self, | ||||
|                                        XDamageNotifyEvent *event); | ||||
|  | ||||
| void meta_window_actor_pre_paint      (MetaWindowActor    *self); | ||||
| void meta_window_actor_post_paint     (MetaWindowActor    *self); | ||||
| @@ -51,14 +50,19 @@ void     meta_window_actor_update_shape        (MetaWindowActor *self); | ||||
| void     meta_window_actor_update_opacity      (MetaWindowActor *self); | ||||
| void     meta_window_actor_mapped              (MetaWindowActor *self); | ||||
| void     meta_window_actor_unmapped            (MetaWindowActor *self); | ||||
| void     meta_window_actor_sync_updates_frozen (MetaWindowActor *self); | ||||
| void     meta_window_actor_set_updates_frozen  (MetaWindowActor *self, | ||||
|                                                 gboolean         updates_frozen); | ||||
| void     meta_window_actor_queue_frame_drawn   (MetaWindowActor *self, | ||||
|                                                 gboolean         no_delay_frame); | ||||
|  | ||||
| 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); | ||||
| void     meta_window_actor_stereo_notify (MetaWindowActor *actor, | ||||
|                                           gboolean         stereo_tree); | ||||
|  | ||||
| gboolean meta_window_actor_is_stereo (MetaWindowActor *actor); | ||||
|  | ||||
| void meta_window_actor_detach (MetaWindowActor *self); | ||||
|  | ||||
| #endif /* META_WINDOW_ACTOR_PRIVATE_H */ | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -122,6 +122,7 @@ meta_window_group_paint (ClutterActor *actor) | ||||
|  | ||||
|   MetaWindowGroup *window_group = META_WINDOW_GROUP (actor); | ||||
|   ClutterActor *stage = clutter_actor_get_stage (actor); | ||||
|   MetaCompScreen *info = meta_screen_get_compositor_data (window_group->screen); | ||||
|  | ||||
|   /* Normally we expect an actor to be drawn at it's position on the screen. | ||||
|    * However, if we're inside the paint of a ClutterClone, that won't be the | ||||
| @@ -164,6 +165,15 @@ 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 (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); | ||||
|   | ||||
| @@ -1,22 +1,12 @@ | ||||
|  | ||||
| pkglibdir = $(MUTTER_PLUGIN_DIR) | ||||
| pkglibdir=@MUTTER_PLUGIN_DIR@ | ||||
|  | ||||
| AM_CPPFLAGS = \ | ||||
| 	$(MUTTER_CFLAGS)						\ | ||||
| 	-I$(top_builddir)/src						\ | ||||
| 	-I$(top_srcdir)/src						\ | ||||
| 	-DMUTTER_LIBEXECDIR=\"$(libexecdir)\"				\ | ||||
| 	-DMUTTER_LOCALEDIR=\"$(localedir)\"				\ | ||||
| 	-DMUTTER_PKGDATADIR=\"$(pkgdatadir)\"				\ | ||||
| 	-DMUTTER_DATADIR=\"$(datadir)\"					\ | ||||
| 	-DG_LOG_DOMAIN=\"mutter\"					\ | ||||
| 	-DSN_API_NOT_YET_FROZEN=1					\ | ||||
| 	-DMUTTER_PLUGIN_DIR=\"$(MUTTER_PLUGIN_DIR)\" | ||||
| INCLUDES=@MUTTER_CFLAGS@ -I $(top_srcdir)/src -DMUTTER_LIBEXECDIR=\"$(libexecdir)\" -DHOST_ALIAS=\"@HOST_ALIAS@\" -DMUTTER_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\" -DMUTTER_PKGDATADIR=\"$(pkgdatadir)\" -DMUTTER_DATADIR=\"$(datadir)\" -DG_LOG_DOMAIN=\"mutter\" -DSN_API_NOT_YET_FROZEN=1 -DMUTTER_MAJOR_VERSION=$(MUTTER_MAJOR_VERSION) -DMUTTER_MINOR_VERSION=$(MUTTER_MINOR_VERSION) -DMUTTER_MICRO_VERSION=$(MUTTER_MICRO_VERSION) -DMUTTER_PLUGIN_API_VERSION=$(MUTTER_PLUGIN_API_VERSION) -DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\" | ||||
|  | ||||
| default_la_CFLAGS   = -fPIC | ||||
| default_la_SOURCES  = default.c | ||||
| default_la_LDFLAGS  = -module -avoid-version -no-undefined | ||||
| default_la_LIBADD   = $(CLUTTER_LIBS) | ||||
| default_la_LIBADD   = @CLUTTER_LIBS@ | ||||
|  | ||||
| pkglib_LTLIBRARIES = default.la | ||||
|  | ||||
|   | ||||
| @@ -32,8 +32,9 @@ | ||||
| #include <gmodule.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #define DESTROY_TIMEOUT   100 | ||||
| #define DESTROY_TIMEOUT   250 | ||||
| #define MINIMIZE_TIMEOUT  250 | ||||
| #define MAXIMIZE_TIMEOUT  250 | ||||
| #define MAP_TIMEOUT       250 | ||||
| #define SWITCH_TIMEOUT    500 | ||||
|  | ||||
| @@ -76,6 +77,18 @@ static void map        (MetaPlugin      *plugin, | ||||
|                         MetaWindowActor *actor); | ||||
| static void destroy    (MetaPlugin      *plugin, | ||||
|                         MetaWindowActor *actor); | ||||
| static void maximize   (MetaPlugin      *plugin, | ||||
|                         MetaWindowActor *actor, | ||||
|                         gint             x, | ||||
|                         gint             y, | ||||
|                         gint             width, | ||||
|                         gint             height); | ||||
| static void unmaximize (MetaPlugin      *plugin, | ||||
|                         MetaWindowActor *actor, | ||||
|                         gint             x, | ||||
|                         gint             y, | ||||
|                         gint             width, | ||||
|                         gint             height); | ||||
|  | ||||
| static void switch_workspace (MetaPlugin          *plugin, | ||||
|                               gint                 from, | ||||
| @@ -122,8 +135,12 @@ typedef struct _ActorPrivate | ||||
|   ClutterActor *orig_parent; | ||||
|  | ||||
|   ClutterTimeline *tml_minimize; | ||||
|   ClutterTimeline *tml_maximize; | ||||
|   ClutterTimeline *tml_destroy; | ||||
|   ClutterTimeline *tml_map; | ||||
|  | ||||
|   gboolean      is_minimized : 1; | ||||
|   gboolean      is_maximized : 1; | ||||
| } ActorPrivate; | ||||
|  | ||||
| /* callback data for when animations complete */ | ||||
| @@ -199,6 +216,8 @@ meta_default_plugin_class_init (MetaDefaultPluginClass *klass) | ||||
|   plugin_class->start            = start; | ||||
|   plugin_class->map              = map; | ||||
|   plugin_class->minimize         = minimize; | ||||
|   plugin_class->maximize         = maximize; | ||||
|   plugin_class->unmaximize       = unmaximize; | ||||
|   plugin_class->destroy          = destroy; | ||||
|   plugin_class->switch_workspace = switch_workspace; | ||||
|   plugin_class->show_tile_preview = show_tile_preview; | ||||
| @@ -469,6 +488,8 @@ on_minimize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data | ||||
|   /* FIXME - we shouldn't assume the original scale, it should be saved | ||||
|    * at the start of the effect */ | ||||
|   clutter_actor_set_scale (data->actor, 1.0, 1.0); | ||||
|   clutter_actor_move_anchor_point_from_gravity (data->actor, | ||||
|                                                 CLUTTER_GRAVITY_NORTH_WEST); | ||||
|  | ||||
|   /* Now notify the manager that we are done with this effect */ | ||||
|   meta_plugin_minimize_completed (plugin, window_actor); | ||||
| @@ -503,6 +524,11 @@ minimize (MetaPlugin *plugin, MetaWindowActor *window_actor) | ||||
|       EffectCompleteData *data = g_new0 (EffectCompleteData, 1); | ||||
|       ActorPrivate *apriv = get_actor_private (window_actor); | ||||
|  | ||||
|       apriv->is_minimized = TRUE; | ||||
|  | ||||
|       clutter_actor_move_anchor_point_from_gravity (actor, | ||||
|                                                     CLUTTER_GRAVITY_CENTER); | ||||
|  | ||||
|       animation = clutter_actor_animate (actor, | ||||
|                                          CLUTTER_EASE_IN_SINE, | ||||
|                                          MINIMIZE_TIMEOUT, | ||||
| @@ -523,6 +549,126 @@ minimize (MetaPlugin *plugin, MetaWindowActor *window_actor) | ||||
|     meta_plugin_minimize_completed (plugin, window_actor); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Minimize effect completion callback; this function restores actor state, and | ||||
|  * calls the manager callback function. | ||||
|  */ | ||||
| static void | ||||
| on_maximize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data) | ||||
| { | ||||
|   /* | ||||
|    * Must reverse the effect of the effect. | ||||
|    */ | ||||
|   MetaPlugin *plugin = data->plugin; | ||||
|   MetaWindowActor *window_actor = META_WINDOW_ACTOR (data->actor); | ||||
|   ActorPrivate *apriv = get_actor_private (window_actor); | ||||
|  | ||||
|   apriv->tml_maximize = NULL; | ||||
|  | ||||
|   /* FIXME - don't assume the original scale was 1.0 */ | ||||
|   clutter_actor_set_scale (data->actor, 1.0, 1.0); | ||||
|   clutter_actor_move_anchor_point_from_gravity (data->actor, | ||||
|                                                 CLUTTER_GRAVITY_NORTH_WEST); | ||||
|  | ||||
|   /* Now notify the manager that we are done with this effect */ | ||||
|   meta_plugin_maximize_completed (plugin, window_actor); | ||||
|  | ||||
|   g_free (data); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * The Nature of Maximize operation is such that it is difficult to do a visual | ||||
|  * effect that would work well. Scaling, the obvious effect, does not work that | ||||
|  * well, because at the end of the effect we end up with window content bigger | ||||
|  * and differently laid out than in the real window; this is a proof concept. | ||||
|  * | ||||
|  * (Something like a sound would be more appropriate.) | ||||
|  */ | ||||
| static void | ||||
| maximize (MetaPlugin *plugin, | ||||
|           MetaWindowActor *window_actor, | ||||
|           gint end_x, gint end_y, gint end_width, gint end_height) | ||||
| { | ||||
|   MetaWindowType type; | ||||
|   ClutterActor *actor = CLUTTER_ACTOR (window_actor); | ||||
|   MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor); | ||||
|  | ||||
|   gdouble  scale_x    = 1.0; | ||||
|   gdouble  scale_y    = 1.0; | ||||
|   gfloat   anchor_x   = 0; | ||||
|   gfloat   anchor_y   = 0; | ||||
|  | ||||
|   type = meta_window_get_window_type (meta_window); | ||||
|  | ||||
|   if (type == META_WINDOW_NORMAL) | ||||
|     { | ||||
|       ClutterAnimation *animation; | ||||
|       EffectCompleteData *data = g_new0 (EffectCompleteData, 1); | ||||
|       ActorPrivate *apriv = get_actor_private (window_actor); | ||||
|       gfloat width, height; | ||||
|       gfloat x, y; | ||||
|  | ||||
|       apriv->is_maximized = TRUE; | ||||
|  | ||||
|       clutter_actor_get_size (actor, &width, &height); | ||||
|       clutter_actor_get_position (actor, &x, &y); | ||||
|  | ||||
|       /* | ||||
|        * Work out the scale and anchor point so that the window is expanding | ||||
|        * smoothly into the target size. | ||||
|        */ | ||||
|       scale_x = (gdouble)end_width / (gdouble) width; | ||||
|       scale_y = (gdouble)end_height / (gdouble) height; | ||||
|  | ||||
|       anchor_x = (gdouble)(x - end_x)*(gdouble)width / | ||||
|         ((gdouble)(end_width - width)); | ||||
|       anchor_y = (gdouble)(y - end_y)*(gdouble)height / | ||||
|         ((gdouble)(end_height - height)); | ||||
|  | ||||
|       clutter_actor_move_anchor_point (actor, anchor_x, anchor_y); | ||||
|  | ||||
|       animation = clutter_actor_animate (actor, | ||||
|                                          CLUTTER_EASE_IN_SINE, | ||||
|                                          MAXIMIZE_TIMEOUT, | ||||
|                                          "scale-x", scale_x, | ||||
|                                          "scale-y", scale_y, | ||||
|                                          NULL); | ||||
|       apriv->tml_maximize = clutter_animation_get_timeline (animation); | ||||
|       data->plugin = plugin; | ||||
|       data->actor = actor; | ||||
|       g_signal_connect (apriv->tml_maximize, "completed", | ||||
|                         G_CALLBACK (on_maximize_effect_complete), | ||||
|                         data); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   meta_plugin_maximize_completed (plugin, window_actor); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * See comments on the maximize() function. | ||||
|  * | ||||
|  * (Just a skeleton code.) | ||||
|  */ | ||||
| static void | ||||
| unmaximize (MetaPlugin *plugin, | ||||
|             MetaWindowActor *window_actor, | ||||
|             gint end_x, gint end_y, gint end_width, gint end_height) | ||||
| { | ||||
|   MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor); | ||||
|   MetaWindowType type = meta_window_get_window_type (meta_window); | ||||
|  | ||||
|   if (type == META_WINDOW_NORMAL) | ||||
|     { | ||||
|       ActorPrivate *apriv = get_actor_private (window_actor); | ||||
|  | ||||
|       apriv->is_maximized = FALSE; | ||||
|     } | ||||
|  | ||||
|   /* Do this conditionally, if the effect requires completion callback. */ | ||||
|   meta_plugin_unmaximize_completed (plugin, window_actor); | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_map_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data) | ||||
| { | ||||
| @@ -535,6 +681,9 @@ on_map_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data) | ||||
|  | ||||
|   apriv->tml_map = NULL; | ||||
|  | ||||
|   clutter_actor_move_anchor_point_from_gravity (data->actor, | ||||
|                                                 CLUTTER_GRAVITY_NORTH_WEST); | ||||
|  | ||||
|   /* Now notify the manager that we are done with this effect */ | ||||
|   meta_plugin_map_completed (plugin, window_actor); | ||||
|  | ||||
| @@ -578,6 +727,9 @@ map (MetaPlugin *plugin, MetaWindowActor *window_actor) | ||||
|       g_signal_connect (apriv->tml_map, "completed", | ||||
|                         G_CALLBACK (on_map_effect_complete), | ||||
|                         data); | ||||
|  | ||||
|       apriv->is_minimized = FALSE; | ||||
|  | ||||
|     } | ||||
|   else | ||||
|     meta_plugin_map_completed (plugin, window_actor); | ||||
| @@ -617,12 +769,14 @@ destroy (MetaPlugin *plugin, MetaWindowActor *window_actor) | ||||
|       EffectCompleteData *data = g_new0 (EffectCompleteData, 1); | ||||
|       ActorPrivate *apriv = get_actor_private (window_actor); | ||||
|  | ||||
|       clutter_actor_move_anchor_point_from_gravity (actor, | ||||
|                                                     CLUTTER_GRAVITY_CENTER); | ||||
|  | ||||
|       animation = clutter_actor_animate (actor, | ||||
|                                          CLUTTER_EASE_OUT_QUAD, | ||||
|                                          CLUTTER_EASE_IN_SINE, | ||||
|                                          DESTROY_TIMEOUT, | ||||
|                                          "opacity", 0, | ||||
|                                          "scale-x", 0.8, | ||||
|                                          "scale-y", 0.8, | ||||
|                                          "scale-x", 0.0, | ||||
|                                          "scale-y", 1.0, | ||||
|                                          NULL); | ||||
|       apriv->tml_destroy = clutter_animation_get_timeline (animation); | ||||
|       data->plugin = plugin; | ||||
| @@ -738,6 +892,12 @@ kill_window_effects (MetaPlugin      *plugin, | ||||
|       g_signal_emit_by_name (apriv->tml_minimize, "completed", NULL); | ||||
|     } | ||||
|  | ||||
|   if (apriv->tml_maximize) | ||||
|     { | ||||
|       clutter_timeline_stop (apriv->tml_maximize); | ||||
|       g_signal_emit_by_name (apriv->tml_maximize, "completed", NULL); | ||||
|     } | ||||
|  | ||||
|   if (apriv->tml_map) | ||||
|     { | ||||
|       clutter_timeline_stop (apriv->tml_map); | ||||
|   | ||||
| @@ -121,7 +121,7 @@ meta_region_builder_finish (MetaRegionBuilder *builder) | ||||
|  | ||||
|   return result; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /* MetaRegionIterator */ | ||||
|  | ||||
| @@ -171,7 +171,7 @@ meta_region_iterator_next (MetaRegionIterator *iter) | ||||
|       iter->line_end = TRUE; | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| add_expanded_rect (MetaRegionBuilder  *builder, | ||||
|                    int                 x, | ||||
|   | ||||
							
								
								
									
										241
									
								
								src/core/above-tab-keycode.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										241
									
								
								src/core/above-tab-keycode.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,241 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* Find the keycode for the key above the tab key */ | ||||
| /* | ||||
|  * Copyright 2010 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/>. | ||||
|  */ | ||||
|  | ||||
| /* The standard cycle-windows keybinding should be the key above the | ||||
|  * tab key. This will have a different keysym on different keyboards - | ||||
|  * it's the ` (grave) key on US keyboards but something else on many | ||||
|  * other national layouts. So we need to figure out the keycode for | ||||
|  * this key without reference to key symbol. | ||||
|  * | ||||
|  * The "correct" way to do this is to get the XKB geometry from the | ||||
|  * X server, find the Tab key, find the key above the Tab key in the | ||||
|  * same section and use the keycode for that key. This is what I | ||||
|  * implemented here, but unfortunately, fetching the geometry is rather | ||||
|  * slow (It could take 20ms or more.) | ||||
|  * | ||||
|  * If you looking for a way to optimize Mutter startup performance: | ||||
|  * On all Linux systems using evdev the key above TAB will have | ||||
|  * keycode 49. (KEY_GRAVE=41 + the 8 code point offset between | ||||
|  * evdev keysyms and X keysyms.) So a configure option | ||||
|  * --with-above-tab-keycode=49 could be added that bypassed this | ||||
|  * code. It wouldn't work right for displaying Mutter remotely | ||||
|  * to a non-Linux X server, but that is pretty rare. | ||||
|  */ | ||||
|  | ||||
| #include <config.h> | ||||
|  | ||||
| #include <string.h> | ||||
|  | ||||
| #include "display-private.h" | ||||
|  | ||||
| #include <X11/keysym.h> | ||||
|  | ||||
| #ifdef HAVE_XKB | ||||
| #include <X11/XKBlib.h> | ||||
| #include <X11/extensions/XKBgeom.h> | ||||
|  | ||||
| static guint | ||||
| compute_above_tab_keycode (Display *xdisplay) | ||||
| { | ||||
|   XkbDescPtr keyboard; | ||||
|   XkbGeometryPtr geometry; | ||||
|   int i, j, k; | ||||
|   int tab_keycode; | ||||
|   char *tab_name; | ||||
|   XkbSectionPtr tab_section; | ||||
|   XkbBoundsRec tab_bounds; | ||||
|   XkbKeyPtr best_key = NULL; | ||||
|   guint best_keycode = (guint)-1; | ||||
|   int best_x_dist = G_MAXINT; | ||||
|   int best_y_dist = G_MAXINT; | ||||
|  | ||||
|   /* We need only the Names and the Geometry, but asking for these results | ||||
|    * in the Keyboard information retrieval failing for unknown reasons. | ||||
|    * (Testing with xorg-1.9.1.) So we ask for a part that we don't need | ||||
|    * as well. | ||||
|    */ | ||||
|   keyboard = XkbGetKeyboard (xdisplay, | ||||
|                              XkbGBN_ClientSymbolsMask | XkbGBN_KeyNamesMask | XkbGBN_GeometryMask, | ||||
|                              XkbUseCoreKbd); | ||||
|   if (!keyboard) | ||||
|     return best_keycode; | ||||
|  | ||||
|   geometry = keyboard->geom; | ||||
|  | ||||
|   /* There could potentially be multiple keys with the Tab keysym on the keyboard; | ||||
|    * but XKeysymToKeycode() returns us the one that the alt-Tab binding will | ||||
|    * use which is good enough | ||||
|    */ | ||||
|   tab_keycode = XKeysymToKeycode (xdisplay, XK_Tab); | ||||
|   if (tab_keycode == 0 || tab_keycode < keyboard->min_key_code || tab_keycode > keyboard->max_key_code) | ||||
|     goto out; | ||||
|  | ||||
|   /* The keyboard geometry is stored by key "name" rather than keycode. | ||||
|    * (Key names are 4-character strings like like TAB or AE01.) We use the | ||||
|    * 'names' part of the keyboard description to map keycode to key name. | ||||
|    * | ||||
|    * XKB has a "key aliases" feature where a single keyboard key can have | ||||
|    * multiple names (with separate sets of aliases in the 'names' part and | ||||
|    * in the 'geometry' part), but I don't really understand it or how it is used, | ||||
|    * so I'm ignoring it here. | ||||
|    */ | ||||
|  | ||||
|   tab_name = keyboard->names->keys[tab_keycode].name; /* Not NULL terminated! */ | ||||
|  | ||||
|   /* First, iterate through the keyboard geometry to find the tab key; the keyboard | ||||
|    * geometry has a three-level heirarchy of section > row > key | ||||
|    */ | ||||
|   for (i = 0; i < geometry->num_sections; i++) | ||||
|     { | ||||
|       XkbSectionPtr section = &geometry->sections[i]; | ||||
|       for (j = 0; j < section->num_rows; j++) | ||||
|         { | ||||
|           int x = 0; | ||||
|           int y = 0; | ||||
|  | ||||
|           XkbRowPtr row = §ion->rows[j]; | ||||
|           for (k = 0; k < row->num_keys; k++) | ||||
|             { | ||||
|               XkbKeyPtr key = &row->keys[k]; | ||||
|               XkbShapePtr shape = XkbKeyShape (geometry, key); | ||||
|  | ||||
|               if (row->vertical) | ||||
|                 y += key->gap; | ||||
|               else | ||||
|                 x += key->gap; | ||||
|  | ||||
|               if (strncmp (key->name.name, tab_name, XkbKeyNameLength) == 0) | ||||
|                 { | ||||
|                   tab_section = section; | ||||
|                   tab_bounds = shape->bounds; | ||||
|                   tab_bounds.x1 += row->left + x; | ||||
|                   tab_bounds.x2 += row->left + x; | ||||
|                   tab_bounds.y1 += row->top + y; | ||||
|                   tab_bounds.y2 += row->top + y; | ||||
|  | ||||
|                   goto found_tab; | ||||
|                 } | ||||
|  | ||||
|               if (row->vertical) | ||||
|                 y += (shape->bounds.y2 - shape->bounds.y1); | ||||
|               else | ||||
|                 x += (shape->bounds.x2 - shape->bounds.x1); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   /* No tab key found */ | ||||
|   goto out; | ||||
|  | ||||
|  found_tab: | ||||
|  | ||||
|   /* Now find the key that: | ||||
|    *  - Is in the same section as the Tab key | ||||
|    *  - Has a horizontal center in the Tab key's horizonal bounds | ||||
|    *  - Is above the Tab key at a distance closer than any other key | ||||
|    *  - In case of ties, has its horizontal center as close as possible | ||||
|    *    to the Tab key's horizontal center | ||||
|    */ | ||||
|   for (j = 0; j < tab_section->num_rows; j++) | ||||
|     { | ||||
|       int x = 0; | ||||
|       int y = 0; | ||||
|  | ||||
|       XkbRowPtr row = &tab_section->rows[j]; | ||||
|       for (k = 0; k < row->num_keys; k++) | ||||
|         { | ||||
|           XkbKeyPtr key = &row->keys[k]; | ||||
|           XkbShapePtr shape = XkbKeyShape(geometry, key); | ||||
|           XkbBoundsRec bounds = shape->bounds; | ||||
|           int x_center; | ||||
|           int x_dist, y_dist; | ||||
|  | ||||
|           if (row->vertical) | ||||
|             y += key->gap; | ||||
|           else | ||||
|             x += key->gap; | ||||
|  | ||||
|           bounds.x1 += row->left + x; | ||||
|           bounds.x2 += row->left + x; | ||||
|           bounds.y1 += row->top + y; | ||||
|           bounds.y2 += row->top + y; | ||||
|  | ||||
|           y_dist = tab_bounds.y1 - bounds.y2; | ||||
|           if (y_dist < 0) | ||||
|             continue; | ||||
|  | ||||
|           x_center = (bounds.x1 + bounds.x2) / 2; | ||||
|           if (x_center < tab_bounds.x1 || x_center > tab_bounds.x2) | ||||
|             continue; | ||||
|  | ||||
|           x_dist = ABS (x_center - (tab_bounds.x1 + tab_bounds.x2) / 2); | ||||
|  | ||||
|           if (y_dist < best_y_dist || | ||||
|               (y_dist == best_y_dist && x_dist < best_x_dist)) | ||||
|             { | ||||
|               best_key = key; | ||||
|               best_x_dist = x_dist; | ||||
|               best_y_dist = y_dist; | ||||
|              } | ||||
|  | ||||
|           if (row->vertical) | ||||
|             y += (shape->bounds.y2 - shape->bounds.y1); | ||||
|           else | ||||
|             x += (shape->bounds.x2 - shape->bounds.x1); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   if (best_key == NULL) | ||||
|     goto out; | ||||
|  | ||||
|   /* Now we need to resolve the name of the best key back to a keycode */ | ||||
|   for (i = keyboard->min_key_code; i < keyboard->max_key_code; i++) | ||||
|     { | ||||
|       if (strncmp (best_key->name.name, keyboard->names->keys[i].name, XkbKeyNameLength) == 0) | ||||
|         { | ||||
|           best_keycode = i; | ||||
|           break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  out: | ||||
|   XkbFreeKeyboard (keyboard, 0, True); | ||||
|  | ||||
|   return best_keycode; | ||||
| } | ||||
| #else /* !HAVE_XKB */ | ||||
| static guint | ||||
| compute_above_tab_keycode (Display *xdisplay) | ||||
| { | ||||
|   return XKeysymToKeycode (xdisplay, XK_grave); | ||||
| } | ||||
| #endif /* HAVE_XKB */ | ||||
|  | ||||
| guint | ||||
| meta_display_get_above_tab_keycode (MetaDisplay *display) | ||||
| { | ||||
|   if (display->above_tab_keycode == 0) /* not yet computed */ | ||||
|     display->above_tab_keycode = compute_above_tab_keycode (display->xdisplay); | ||||
|  | ||||
|   if (display->above_tab_keycode == (guint)-1) /* failed to compute */ | ||||
|     return 0; | ||||
|   else | ||||
|     return display->above_tab_keycode; | ||||
| } | ||||
| @@ -55,7 +55,7 @@ struct _ListNode | ||||
| struct _AgGetPropertyTask | ||||
| { | ||||
|   ListNode node; | ||||
| 
 | ||||
|    | ||||
|   AgPerDisplayData *dd; | ||||
|   Window window; | ||||
|   Atom property; | ||||
| @@ -77,7 +77,7 @@ struct _AgPerDisplayData | ||||
| { | ||||
|   ListNode node; | ||||
|   _XAsyncHandler async; | ||||
| 
 | ||||
|    | ||||
|   Display *display; | ||||
|   ListNode *pending_tasks; | ||||
|   ListNode *pending_tasks_tail; | ||||
| @@ -96,7 +96,7 @@ append_to_list (ListNode **head, | ||||
|                 ListNode  *task) | ||||
| { | ||||
|   task->next = NULL; | ||||
| 
 | ||||
|    | ||||
|   if (*tail == NULL) | ||||
|     { | ||||
|       assert (*head == NULL); | ||||
| @@ -131,10 +131,10 @@ remove_from_list (ListNode **head, | ||||
| 
 | ||||
|           if (node == *tail) | ||||
|             *tail = prev; | ||||
| 
 | ||||
|            | ||||
|           break; | ||||
|         } | ||||
| 
 | ||||
|        | ||||
|       prev = node; | ||||
|       node = node->next; | ||||
|     } | ||||
| @@ -152,7 +152,7 @@ move_to_completed (AgPerDisplayData  *dd, | ||||
|   remove_from_list (&dd->pending_tasks, | ||||
|                     &dd->pending_tasks_tail, | ||||
|                     &task->node); | ||||
| 
 | ||||
|    | ||||
|   append_to_list (&dd->completed_tasks, | ||||
|                   &dd->completed_tasks_tail, | ||||
|                   &task->node); | ||||
| @@ -187,18 +187,18 @@ find_pending_by_request_sequence (AgPerDisplayData *dd, | ||||
|    * I'm not sure this is 100% guaranteed, if it is, | ||||
|    * it would be a big speedup. | ||||
|    */ | ||||
| 
 | ||||
|    | ||||
|   node = dd->pending_tasks; | ||||
|   while (node != NULL) | ||||
|     { | ||||
|       AgGetPropertyTask *task = (AgGetPropertyTask*) node; | ||||
| 
 | ||||
|        | ||||
|       if (task->request_seq == request_seq) | ||||
|         return task; | ||||
| 
 | ||||
|        | ||||
|       node = node->next; | ||||
|     } | ||||
| 
 | ||||
|    | ||||
|   return NULL; | ||||
| } | ||||
| 
 | ||||
| @@ -216,12 +216,12 @@ async_get_property_handler (Display *dpy, | ||||
|   int bytes_read; | ||||
| 
 | ||||
|   dd = (AgPerDisplayData*) data; | ||||
| 
 | ||||
|    | ||||
| #if 0 | ||||
|   printf ("%s: seeing request seq %ld buflen %d\n", __FUNCTION__, | ||||
|           dpy->last_request_read, len); | ||||
| #endif | ||||
| 
 | ||||
|    | ||||
|   task = find_pending_by_request_sequence (dd, dpy->last_request_read); | ||||
| 
 | ||||
|   if (task == NULL) | ||||
| @@ -231,7 +231,7 @@ async_get_property_handler (Display *dpy, | ||||
| 
 | ||||
|   task->have_reply = True; | ||||
|   move_to_completed (dd, task); | ||||
| 
 | ||||
|    | ||||
|   /* read bytes so far */ | ||||
|   bytes_read = SIZEOF (xReply); | ||||
| 
 | ||||
| @@ -240,7 +240,7 @@ async_get_property_handler (Display *dpy, | ||||
|       xError errbuf; | ||||
| 
 | ||||
|       task->error = rep->error.errorCode; | ||||
| 
 | ||||
|        | ||||
| #ifdef DEBUG_SPEW | ||||
|       printf ("%s: error code = %d (ignoring error, eating %d bytes, generic.length = %ld)\n", | ||||
|               __FUNCTION__, task->error, (SIZEOF (xError) - bytes_read), | ||||
| @@ -263,7 +263,7 @@ async_get_property_handler (Display *dpy, | ||||
|       _XGetAsyncReply (dpy, (char *)&errbuf, rep, buf, len, | ||||
|                        (SIZEOF (xError) - bytes_read) >> 2, /* in 32-bit words */ | ||||
|                        False); /* really seems like it should be True */ | ||||
| 
 | ||||
|        | ||||
|       return True; | ||||
|     } | ||||
| 
 | ||||
| @@ -368,7 +368,7 @@ async_get_property_handler (Display *dpy, | ||||
|                   char *netdata; | ||||
|                   char *lptr; | ||||
|                   char *end_lptr; | ||||
| 
 | ||||
|                    | ||||
|                   /* Store the 32-bit values in the end of the array */ | ||||
|                   netdata = task->data + nbytes / 2; | ||||
| 
 | ||||
| @@ -377,7 +377,7 @@ async_get_property_handler (Display *dpy, | ||||
|                                   netbytes); | ||||
| 
 | ||||
|                   /* Now move the 32-bit values to the front */ | ||||
| 
 | ||||
|                    | ||||
|                   lptr = task->data; | ||||
|                   end_lptr = task->data + nbytes; | ||||
|                   while (lptr != end_lptr) | ||||
| @@ -411,7 +411,7 @@ async_get_property_handler (Display *dpy, | ||||
| #if 0 | ||||
|             xError error; | ||||
| #endif | ||||
| 
 | ||||
|              | ||||
|             task->error = BadImplementation; | ||||
| 
 | ||||
| #if 0 | ||||
| @@ -468,21 +468,21 @@ get_display_data (Display *display, | ||||
| { | ||||
|   ListNode *node; | ||||
|   AgPerDisplayData *dd; | ||||
| 
 | ||||
|    | ||||
|   node = display_datas; | ||||
|   while (node != NULL) | ||||
|     { | ||||
|       dd = (AgPerDisplayData*) node; | ||||
| 
 | ||||
|        | ||||
|       if (dd->display == display) | ||||
|         return dd; | ||||
| 
 | ||||
|        | ||||
|       node = node->next; | ||||
|     } | ||||
| 
 | ||||
|   if (!create) | ||||
|     return NULL; | ||||
| 
 | ||||
|    | ||||
|   dd = Xcalloc (1, sizeof (AgPerDisplayData)); | ||||
|   if (dd == NULL) | ||||
|     return NULL; | ||||
| @@ -496,7 +496,7 @@ get_display_data (Display *display, | ||||
|   append_to_list (&display_datas, | ||||
|                   &display_datas_tail, | ||||
|                   &dd->node); | ||||
| 
 | ||||
|    | ||||
|   return dd; | ||||
| } | ||||
| 
 | ||||
| @@ -524,8 +524,8 @@ ag_task_create (Display *dpy, | ||||
| { | ||||
|   AgGetPropertyTask *task; | ||||
|   xGetPropertyReq *req; | ||||
|   AgPerDisplayData *dd; | ||||
| 
 | ||||
|   AgPerDisplayData *dd;   | ||||
|    | ||||
|   /* Fire up our request */ | ||||
|   LockDisplay (dpy); | ||||
| 
 | ||||
| @@ -535,7 +535,7 @@ ag_task_create (Display *dpy, | ||||
|       UnlockDisplay (dpy); | ||||
|       return NULL; | ||||
|     } | ||||
| 
 | ||||
|    | ||||
|   GetReq (GetProperty, req); | ||||
|   req->window = window; | ||||
|   req->property = property; | ||||
| @@ -561,7 +561,7 @@ ag_task_create (Display *dpy, | ||||
|                   &dd->pending_tasks_tail, | ||||
|                   &task->node); | ||||
|   dd->n_tasks_pending += 1; | ||||
| 
 | ||||
|    | ||||
|   UnlockDisplay (dpy); | ||||
| 
 | ||||
|   SyncHandle (); | ||||
| @@ -593,13 +593,13 @@ ag_task_get_reply_and_free (AgGetPropertyTask  *task, | ||||
|   *prop = NULL; | ||||
| 
 | ||||
|   dpy = task->dd->display; /* Xlib macros require a variable named "dpy" */ | ||||
| 
 | ||||
|    | ||||
|   if (task->error != Success) | ||||
|     { | ||||
|       Status s = task->error; | ||||
| 
 | ||||
|       free_task (task); | ||||
| 
 | ||||
|        | ||||
|       return s; | ||||
|     } | ||||
| 
 | ||||
| @@ -620,7 +620,7 @@ ag_task_get_reply_and_free (AgGetPropertyTask  *task, | ||||
|   SyncHandle (); | ||||
| 
 | ||||
|   free_task (task); | ||||
| 
 | ||||
|    | ||||
|   return Success; | ||||
| } | ||||
| 
 | ||||
| @@ -657,7 +657,7 @@ ag_get_next_completed_task (Display *display) | ||||
| 
 | ||||
|   if (dd == NULL) | ||||
|     return NULL; | ||||
| 
 | ||||
|    | ||||
| #ifdef DEBUG_SPEW | ||||
|   printf ("%d pending %d completed\n", | ||||
|           dd->n_tasks_pending, | ||||
| @@ -4,16 +4,16 @@ | ||||
| 
 | ||||
| /*
 | ||||
|  * Copyright (C) 2002 Havoc Pennington | ||||
|  * | ||||
|  *  | ||||
|  * Permission to use, copy, modify, distribute, and sell this software | ||||
|  * and its documentation for any purpose is hereby granted without | ||||
|  * fee, provided that the above copyright notice appear in all copies | ||||
|  * and that both that copyright notice and this permission notice | ||||
|  * appear in supporting documentation. | ||||
|  * | ||||
|  *  | ||||
|  * The above copyright notice and this permission notice shall be | ||||
|  * included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||
|  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||||
| @@ -366,25 +366,11 @@ meta_barrier_fire_event (MetaBarrier    *barrier, | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_display_process_barrier_event (MetaDisplay *display, | ||||
|                                     XIEvent     *event) | ||||
| meta_display_process_barrier_event (MetaDisplay    *display, | ||||
|                                     XIBarrierEvent *xev) | ||||
| { | ||||
|   MetaBarrier *barrier; | ||||
|   XIBarrierEvent *xev; | ||||
|  | ||||
|   if (event == NULL) | ||||
|     return FALSE; | ||||
|  | ||||
|   switch (event->evtype) | ||||
|     { | ||||
|     case XI_BarrierHit: | ||||
|     case XI_BarrierLeave: | ||||
|       break; | ||||
|     default: | ||||
|       return FALSE; | ||||
|     } | ||||
|  | ||||
|   xev = (XIBarrierEvent *) event; | ||||
|   barrier = g_hash_table_lookup (display->xids, &xev->barrier); | ||||
|   if (barrier != NULL) | ||||
|     { | ||||
|   | ||||
							
								
								
									
										148
									
								
								src/core/bell.c
									
									
									
									
									
								
							
							
						
						
									
										148
									
								
								src/core/bell.c
									
									
									
									
									
								
							| @@ -2,10 +2,10 @@ | ||||
|  | ||||
| /* Mutter visual bell */ | ||||
|  | ||||
| /* | ||||
| /*  | ||||
|  * Copyright (C) 2002 Sun Microsystems Inc. | ||||
|  * Copyright (C) 2005, 2006 Elijah Newren | ||||
|  * | ||||
|  *  | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
| @@ -15,7 +15,7 @@ | ||||
|  * 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/>. | ||||
|  */ | ||||
| @@ -58,6 +58,88 @@ | ||||
| #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 | ||||
| @@ -71,11 +153,37 @@ | ||||
|  */ | ||||
| #ifdef HAVE_XKB | ||||
| static void | ||||
| bell_flash_fullscreen (MetaDisplay *display, | ||||
| bell_flash_fullscreen (MetaDisplay *display,  | ||||
|                        XkbAnyEvent *xkb_ev) | ||||
| { | ||||
|   XkbBellNotifyEvent *xkb_bell_ev = (XkbBellNotifyEvent *) xkb_ev; | ||||
|   MetaScreen *screen; | ||||
|  | ||||
|   g_assert (xkb_ev->xkb_type == XkbBellNotify); | ||||
|   meta_compositor_flash_screen (display->compositor, display->screen); | ||||
|   if (xkb_bell_ev->window != None) | ||||
|     { | ||||
|       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  | ||||
|     { | ||||
|       GSList *screen_list = display->screens; | ||||
|       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; | ||||
| 	} | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -96,7 +204,7 @@ bell_flash_fullscreen (MetaDisplay *display, | ||||
|  * Bug: This is the parallel to bell_flash_window_frame(), so it should | ||||
|  * really be called meta_bell_unflash_window_frame(). | ||||
|  */ | ||||
| static gboolean | ||||
| static gboolean  | ||||
| bell_unflash_frame (gpointer data) | ||||
| { | ||||
|   MetaFrame *frame = (MetaFrame *) data; | ||||
| @@ -120,7 +228,6 @@ bell_unflash_frame (gpointer data) | ||||
| static void | ||||
| bell_flash_window_frame (MetaWindow *window) | ||||
| { | ||||
|   guint id; | ||||
|   g_assert (window->frame != NULL); | ||||
|   window->frame->is_flashing = 1; | ||||
|   meta_frame_queue_draw (window->frame); | ||||
| @@ -129,9 +236,8 @@ bell_flash_window_frame (MetaWindow *window) | ||||
|    * we are guaranteed to get at least one frame drawn in the | ||||
|    * flashed state, no matter how loaded we are. | ||||
|    */ | ||||
|   id = g_timeout_add_full (META_PRIORITY_REDRAW, 100, | ||||
|         bell_unflash_frame, window->frame, NULL); | ||||
|   g_source_set_name_by_id (id, "[mutter] bell_unflash_frame"); | ||||
|   g_timeout_add_full (META_PRIORITY_REDRAW, 100, | ||||
|       bell_unflash_frame, window->frame, NULL); | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -143,12 +249,12 @@ bell_flash_window_frame (MetaWindow *window) | ||||
|  * flashes the screen. | ||||
|  */ | ||||
| static void | ||||
| bell_flash_frame (MetaDisplay *display, | ||||
| bell_flash_frame (MetaDisplay *display,  | ||||
| 		  XkbAnyEvent *xkb_ev) | ||||
| { | ||||
|   XkbBellNotifyEvent *xkb_bell_event = (XkbBellNotifyEvent *) xkb_ev; | ||||
|   MetaWindow *window; | ||||
|  | ||||
|    | ||||
|   g_assert (xkb_ev->xkb_type == XkbBellNotify); | ||||
|   window = meta_display_lookup_x_window (display, xkb_bell_event->window); | ||||
|   if (!window && (display->focus_window)) | ||||
| @@ -180,10 +286,10 @@ bell_flash_frame (MetaDisplay *display, | ||||
|  * Bug: This should be merged with meta_bell_notify(). | ||||
|  */ | ||||
| static void | ||||
| bell_visual_notify (MetaDisplay *display, | ||||
| bell_visual_notify (MetaDisplay *display,  | ||||
| 			 XkbAnyEvent *xkb_ev) | ||||
| { | ||||
|   switch (meta_prefs_get_visual_bell_type ()) | ||||
|   switch (meta_prefs_get_visual_bell_type ())  | ||||
|     { | ||||
|     case G_DESKTOP_VISUAL_BELL_FULLSCREEN_FLASH: | ||||
|       bell_flash_fullscreen (display, xkb_ev); | ||||
| @@ -195,7 +301,7 @@ bell_visual_notify (MetaDisplay *display, | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_bell_notify (MetaDisplay *display, | ||||
| meta_bell_notify (MetaDisplay *display,  | ||||
| 		  XkbAnyEvent *xkb_ev) | ||||
| { | ||||
|   /* flash something */ | ||||
| @@ -271,19 +377,19 @@ meta_bell_init (MetaDisplay *display) | ||||
| #ifdef HAVE_XKB | ||||
|   int xkb_base_error_type, xkb_opcode; | ||||
|  | ||||
|   if (!XkbQueryExtension (display->xdisplay, &xkb_opcode, | ||||
| 			  &display->xkb_base_event_type, | ||||
| 			  &xkb_base_error_type, | ||||
|   if (!XkbQueryExtension (display->xdisplay, &xkb_opcode,  | ||||
| 			  &display->xkb_base_event_type,  | ||||
| 			  &xkb_base_error_type,  | ||||
| 			  NULL, NULL)) | ||||
|     { | ||||
|       display->xkb_base_event_type = -1; | ||||
|       g_message ("could not find XKB extension."); | ||||
|       return FALSE; | ||||
|     } | ||||
|   else | ||||
|   else  | ||||
|     { | ||||
|       unsigned int mask = XkbBellNotifyMask; | ||||
|       gboolean visual_bell_auto_reset = FALSE; | ||||
|       gboolean visual_bell_auto_reset = FALSE;  | ||||
|       /* TRUE if and when non-broken version is available */ | ||||
|       XkbSelectEvents (display->xdisplay, | ||||
| 		       XkbUseCoreKbd, | ||||
| @@ -326,6 +432,6 @@ meta_bell_shutdown (MetaDisplay *display) | ||||
| void | ||||
| meta_bell_notify_frame_destroy (MetaFrame *frame) | ||||
| { | ||||
|   if (frame->is_flashing) | ||||
|   if (frame->is_flashing)  | ||||
|     g_source_remove_by_funcs_user_data (&g_timeout_funcs, frame); | ||||
| } | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ | ||||
|  | ||||
| /* | ||||
| /*  | ||||
|  * Copyright (C) 2002 Sun Microsystems 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 | ||||
| @@ -12,7 +12,7 @@ | ||||
|  * 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/>. | ||||
|  */ | ||||
| @@ -28,7 +28,7 @@ | ||||
| /** | ||||
|  * meta_bell_notify: | ||||
|  * @display: The display the bell event came in on | ||||
|  * @xkb_ev: The bell event we just received | ||||
|  * @xkb_ev: The bell event we just received  | ||||
|  * | ||||
|  * Gives the user some kind of visual bell; in fact, this is our response | ||||
|  * to any kind of bell request, but we set it up so that we only get | ||||
|   | ||||
| @@ -2,9 +2,9 @@ | ||||
|  | ||||
| /* Simple box operations */ | ||||
|  | ||||
| /* | ||||
| /*  | ||||
|  * Copyright (C) 2005, 2006 Elijah Newren | ||||
|  * | ||||
|  *  | ||||
|  * This program is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU General Public License as | ||||
|  * published by the Free Software Foundation; either version 2 of the | ||||
| @@ -14,7 +14,7 @@ | ||||
|  * 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/>. | ||||
|  */ | ||||
| @@ -43,7 +43,7 @@ typedef enum | ||||
|  *   region_to_string: (RECT_LENGTH+strlen(separator_string)) * | ||||
|  *                     g_list_length (region) | ||||
|  *   edge_to_string:   EDGE_LENGTH | ||||
|  *   edge_list_to_...: (EDGE_LENGTH+strlen(separator_string)) * | ||||
|  *   edge_list_to_...: (EDGE_LENGTH+strlen(separator_string)) *  | ||||
|  *                     g_list_length (edge_list) | ||||
|  */ | ||||
| #define RECT_LENGTH 27 | ||||
| @@ -181,7 +181,7 @@ void meta_rectangle_find_linepoint_closest_to_point (double x1,    double y1, | ||||
| /* Return whether an edge overlaps or is adjacent to the rectangle in the | ||||
|  * nonzero-width dimension of the edge. | ||||
|  */ | ||||
| gboolean meta_rectangle_edge_aligns (const MetaRectangle *rect, | ||||
| gboolean meta_rectangle_edge_aligns (const MetaRectangle *rect,  | ||||
|                                      const MetaEdge      *edge); | ||||
|  | ||||
| /* Compare two edges, so that sorting functions can put a list of edges in | ||||
|   | ||||
							
								
								
									
										113
									
								
								src/core/boxes.c
									
									
									
									
									
								
							
							
						
						
									
										113
									
								
								src/core/boxes.c
									
									
									
									
									
								
							| @@ -6,14 +6,14 @@ | ||||
|  * @Short_Description: Simple box operations | ||||
|  */ | ||||
|  | ||||
| /* | ||||
| /*  | ||||
|  * Copyright (C) 2005, 2006 Elijah Newren | ||||
|  * [meta_rectangle_intersect() is copyright the GTK+ Team according to Havoc, | ||||
|  * see gdkrectangle.c.  As far as Havoc knows, he probably wrote | ||||
|  * meta_rectangle_equal(), and I'm guessing it's (C) Red Hat.  So...] | ||||
|  * Copyright (C) 1995-2000  GTK+ Team | ||||
|  * 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 | ||||
| @@ -23,7 +23,7 @@ | ||||
|  * 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/>. | ||||
|  */ | ||||
| @@ -69,7 +69,7 @@ meta_rectangle_to_string (const MetaRectangle *rect, | ||||
|    * Should be more than enough space.  Note that of this space, the | ||||
|    * trailing \0 will be overwritten for all but the last rectangle. | ||||
|    */ | ||||
|   g_snprintf (output, RECT_LENGTH, "%d,%d +%d,%d", | ||||
|   g_snprintf (output, RECT_LENGTH, "%d,%d +%d,%d",  | ||||
|               rect->x, rect->y, rect->width, rect->height); | ||||
|  | ||||
|   return output; | ||||
| @@ -96,7 +96,7 @@ meta_rectangle_region_to_string (GList      *region, | ||||
|   while (tmp) | ||||
|     { | ||||
|       MetaRectangle *rect = tmp->data; | ||||
|       g_snprintf (rect_string, RECT_LENGTH, "[%d,%d +%d,%d]", | ||||
|       g_snprintf (rect_string, RECT_LENGTH, "[%d,%d +%d,%d]",  | ||||
|                   rect->x, rect->y, rect->width, rect->height); | ||||
|       cur = g_stpcpy (cur, rect_string); | ||||
|       tmp = tmp->next; | ||||
| @@ -118,7 +118,7 @@ meta_rectangle_edge_to_string (const MetaEdge *edge, | ||||
|    * Plus 2 for parenthesis, 4 for 2 more numbers, 2 more commas, and | ||||
|    * 2 more spaces, for a total of 10 more. | ||||
|    */ | ||||
|   g_snprintf (output, EDGE_LENGTH, "[%d,%d +%d,%d], %2d, %2d", | ||||
|   g_snprintf (output, EDGE_LENGTH, "[%d,%d +%d,%d], %2d, %2d",  | ||||
|               edge->rect.x, edge->rect.y, edge->rect.width, edge->rect.height, | ||||
|               edge->side_type, edge->edge_type); | ||||
|  | ||||
| @@ -150,7 +150,7 @@ meta_rectangle_edge_list_to_string (GList      *edge_list, | ||||
|     { | ||||
|       MetaEdge      *edge = tmp->data; | ||||
|       MetaRectangle *rect = &edge->rect; | ||||
|       g_snprintf (rect_string, EDGE_LENGTH, "([%d,%d +%d,%d], %2d, %2d)", | ||||
|       g_snprintf (rect_string, EDGE_LENGTH, "([%d,%d +%d,%d], %2d, %2d)",  | ||||
|                   rect->x, rect->y, rect->width, rect->height, | ||||
|                   edge->side_type, edge->edge_type); | ||||
|       cur = g_stpcpy (cur, rect_string); | ||||
| @@ -210,7 +210,7 @@ meta_rectangle_intersect (const MetaRectangle *src1, | ||||
|   dest_y = MAX (src1->y, src2->y); | ||||
|   dest_w = MIN (src1->x + src1->width, src2->x + src2->width) - dest_x; | ||||
|   dest_h = MIN (src1->y + src1->height, src2->y + src2->height) - dest_y; | ||||
|  | ||||
|    | ||||
|   if (dest_w > 0 && dest_h > 0) | ||||
|     { | ||||
|       dest->x = dest_x; | ||||
| @@ -320,7 +320,7 @@ gboolean | ||||
| meta_rectangle_contains_rect  (const MetaRectangle *outer_rect, | ||||
|                                const MetaRectangle *inner_rect) | ||||
| { | ||||
|   return | ||||
|   return  | ||||
|     inner_rect->x                      >= outer_rect->x && | ||||
|     inner_rect->y                      >= outer_rect->y && | ||||
|     inner_rect->x + inner_rect->width  <= outer_rect->x + outer_rect->width && | ||||
| @@ -339,7 +339,7 @@ meta_rectangle_resize_with_gravity (const MetaRectangle *old_rect, | ||||
|    * boxes.h has a good comment, but I'm not sure if the below info is also | ||||
|    * helpful on top of that (or whether it has superfluous info). | ||||
|    */ | ||||
|  | ||||
|   | ||||
|   /* These formulas may look overly simplistic at first but you can work | ||||
|    * everything out with a left_frame_with, right_frame_width, | ||||
|    * border_width, and old and new client area widths (instead of old total | ||||
| @@ -389,7 +389,7 @@ meta_rectangle_resize_with_gravity (const MetaRectangle *old_rect, | ||||
|       break; | ||||
|     } | ||||
|   rect->width = new_width; | ||||
|  | ||||
|    | ||||
|   /* Next, the y direction */ | ||||
|   switch (gravity) | ||||
|     { | ||||
| @@ -546,26 +546,6 @@ compare_rect_areas (gconstpointer a, gconstpointer b) | ||||
|   return b_area - a_area; /* positive ret value denotes b > a, ... */ | ||||
| } | ||||
|  | ||||
| /* ... and another helper for get_minimal_spanning_set_for_region()... */ | ||||
| static gboolean | ||||
| check_strut_align (MetaStrut *strut, const MetaRectangle *rect) | ||||
| { | ||||
|   /* Check whether @strut actually aligns to the side of @rect it claims */ | ||||
|   switch (strut->side) | ||||
|     { | ||||
|     case META_SIDE_TOP: | ||||
|       return BOX_TOP (strut->rect) <= BOX_TOP (*rect); | ||||
|     case META_SIDE_BOTTOM: | ||||
|       return BOX_BOTTOM (strut->rect) >= BOX_BOTTOM (*rect); | ||||
|     case META_SIDE_LEFT: | ||||
|       return BOX_LEFT (strut->rect) <= BOX_LEFT (*rect); | ||||
|     case META_SIDE_RIGHT: | ||||
|       return BOX_RIGHT (strut->rect) >= BOX_RIGHT (*rect); | ||||
|     default: | ||||
|       return FALSE; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * meta_rectangle_get_minimal_spanning_set_for_region: | ||||
|  * @basic_rect: Input rectangle | ||||
| @@ -649,9 +629,8 @@ meta_rectangle_get_minimal_spanning_set_for_region ( | ||||
|  | ||||
|   for (strut_iter = all_struts; strut_iter; strut_iter = strut_iter->next) | ||||
|     { | ||||
|       GList *rect_iter; | ||||
|       MetaStrut *strut = (MetaStrut*)strut_iter->data; | ||||
|       MetaRectangle *strut_rect = &strut->rect; | ||||
|       GList *rect_iter;  | ||||
|       MetaRectangle *strut_rect = &((MetaStrut*)strut_iter->data)->rect; | ||||
|  | ||||
|       tmp_list = ret; | ||||
|       ret = NULL; | ||||
| @@ -659,9 +638,7 @@ meta_rectangle_get_minimal_spanning_set_for_region ( | ||||
|       while (rect_iter) | ||||
|         { | ||||
|           MetaRectangle *rect = (MetaRectangle*) rect_iter->data; | ||||
|  | ||||
|           if (!meta_rectangle_overlap (strut_rect, rect) || | ||||
|               !check_strut_align (strut, basic_rect)) | ||||
|           if (!meta_rectangle_overlap (rect, strut_rect)) | ||||
|             ret = g_list_prepend (ret, rect); | ||||
|           else | ||||
|             { | ||||
| @@ -787,7 +764,7 @@ meta_rectangle_expand_to_avoiding_struts (MetaRectangle       *rect, | ||||
|    */ | ||||
|   g_assert ((direction == META_DIRECTION_HORIZONTAL) ^ | ||||
|             (direction == META_DIRECTION_VERTICAL  )); | ||||
|  | ||||
|   | ||||
|   if (direction == META_DIRECTION_HORIZONTAL) | ||||
|     { | ||||
|       rect->x      = expand_to->x; | ||||
| @@ -799,12 +776,12 @@ meta_rectangle_expand_to_avoiding_struts (MetaRectangle       *rect, | ||||
|       rect->height = expand_to->height; | ||||
|     } | ||||
|  | ||||
|  | ||||
|   | ||||
|   /* Run over all struts */ | ||||
|   for (strut_iter = all_struts; strut_iter; strut_iter = strut_iter->next) | ||||
|     { | ||||
|       MetaStrut *strut = (MetaStrut*) strut_iter->data; | ||||
|  | ||||
|   | ||||
|       /* Skip struts that don't overlap */ | ||||
|       if (!meta_rectangle_overlap (&strut->rect, rect)) | ||||
|         continue; | ||||
| @@ -845,7 +822,7 @@ meta_rectangle_expand_to_avoiding_struts (MetaRectangle       *rect, | ||||
| void | ||||
| meta_rectangle_free_list_and_elements (GList *filled_list) | ||||
| { | ||||
|   g_list_foreach (filled_list, | ||||
|   g_list_foreach (filled_list,  | ||||
|                   (void (*)(gpointer,gpointer))&g_free, /* ew, for ugly */ | ||||
|                   NULL); | ||||
|   g_list_free (filled_list); | ||||
| @@ -923,20 +900,20 @@ meta_rectangle_clamp_to_fit_into_region (const GList         *spanning_rects, | ||||
|     { | ||||
|       MetaRectangle *compare_rect = temp->data; | ||||
|       int            maximal_overlap_amount_for_compare; | ||||
|  | ||||
|        | ||||
|       /* If x is fixed and the entire width of rect doesn't fit in compare, | ||||
|        * skip this rectangle. | ||||
|        */ | ||||
|       if ((fixed_directions & FIXED_DIRECTION_X) && | ||||
|           (compare_rect->x > rect->x || | ||||
|           (compare_rect->x > rect->x ||  | ||||
|            compare_rect->x + compare_rect->width < rect->x + rect->width)) | ||||
|         continue; | ||||
|  | ||||
|          | ||||
|       /* If y is fixed and the entire height of rect doesn't fit in compare, | ||||
|        * skip this rectangle. | ||||
|        */ | ||||
|       if ((fixed_directions & FIXED_DIRECTION_Y) && | ||||
|           (compare_rect->y > rect->y || | ||||
|           (compare_rect->y > rect->y ||  | ||||
|            compare_rect->y + compare_rect->height < rect->y + rect->height)) | ||||
|         continue; | ||||
|  | ||||
| @@ -993,20 +970,20 @@ meta_rectangle_clip_to_region (const GList         *spanning_rects, | ||||
|       MetaRectangle *compare_rect = temp->data; | ||||
|       MetaRectangle  overlap; | ||||
|       int            maximal_overlap_amount_for_compare; | ||||
|  | ||||
|       | ||||
|       /* If x is fixed and the entire width of rect doesn't fit in compare, | ||||
|        * skip the rectangle. | ||||
|        */ | ||||
|       if ((fixed_directions & FIXED_DIRECTION_X) && | ||||
|           (compare_rect->x > rect->x || | ||||
|           (compare_rect->x > rect->x ||  | ||||
|            compare_rect->x + compare_rect->width < rect->x + rect->width)) | ||||
|         continue; | ||||
|  | ||||
|          | ||||
|       /* If y is fixed and the entire height of rect doesn't fit in compare, | ||||
|        * skip the rectangle. | ||||
|        */ | ||||
|       if ((fixed_directions & FIXED_DIRECTION_Y) && | ||||
|           (compare_rect->y > rect->y || | ||||
|           (compare_rect->y > rect->y ||  | ||||
|            compare_rect->y + compare_rect->height < rect->y + rect->height)) | ||||
|         continue; | ||||
|  | ||||
| @@ -1066,26 +1043,26 @@ meta_rectangle_shove_into_region (const GList         *spanning_rects, | ||||
|   /* First, find best rectangle from spanning_rects to which we will shove | ||||
|    * rect into. | ||||
|    */ | ||||
|  | ||||
|    | ||||
|   for (temp = spanning_rects; temp; temp = temp->next) | ||||
|     { | ||||
|       MetaRectangle *compare_rect = temp->data; | ||||
|       int            maximal_overlap_amount_for_compare; | ||||
|       int            dist_to_compare; | ||||
|  | ||||
|        | ||||
|       /* If x is fixed and the entire width of rect doesn't fit in compare, | ||||
|        * skip this rectangle. | ||||
|        */ | ||||
|       if ((fixed_directions & FIXED_DIRECTION_X) && | ||||
|           (compare_rect->x > rect->x || | ||||
|           (compare_rect->x > rect->x ||  | ||||
|            compare_rect->x + compare_rect->width < rect->x + rect->width)) | ||||
|         continue; | ||||
|  | ||||
|          | ||||
|       /* If y is fixed and the entire height of rect doesn't fit in compare, | ||||
|        * skip this rectangle. | ||||
|        */ | ||||
|       if ((fixed_directions & FIXED_DIRECTION_Y) && | ||||
|           (compare_rect->y > rect->y || | ||||
|           (compare_rect->y > rect->y ||  | ||||
|            compare_rect->y + compare_rect->height < rect->y + rect->height)) | ||||
|         continue; | ||||
|  | ||||
| @@ -1241,7 +1218,7 @@ meta_rectangle_edge_aligns (const MetaRectangle *rect, const MetaEdge *edge) | ||||
| } | ||||
|  | ||||
| static GList* | ||||
| get_rect_minus_overlap (const GList   *rect_in_list, | ||||
| get_rect_minus_overlap (const GList   *rect_in_list,  | ||||
|                         MetaRectangle *overlap) | ||||
| { | ||||
|   MetaRectangle *temp; | ||||
| @@ -1286,7 +1263,7 @@ get_rect_minus_overlap (const GList   *rect_in_list, | ||||
| } | ||||
|  | ||||
| static GList* | ||||
| replace_rect_with_list (GList *old_element, | ||||
| replace_rect_with_list (GList *old_element,  | ||||
|                         GList *new_list) | ||||
| { | ||||
|   GList *ret; | ||||
| @@ -1498,7 +1475,7 @@ rectangle_and_edge_intersection (const MetaRectangle *rect, | ||||
|   overlap->edge_type = -1; | ||||
|   overlap->side_type = -1; | ||||
|  | ||||
|   /* Figure out what the intersection is */ | ||||
|   /* Figure out what the intersection is */   | ||||
|   result->x = MAX (rect->x, rect2->x); | ||||
|   result->y = MAX (rect->y, rect2->y); | ||||
|   result->width  = MIN (BOX_RIGHT (*rect),  BOX_RIGHT (*rect2))  - result->x; | ||||
| @@ -1569,7 +1546,7 @@ rectangle_and_edge_intersection (const MetaRectangle *rect, | ||||
|  * TOP<->BOTTOM). | ||||
|  */ | ||||
| static GList* | ||||
| add_edges (GList               *cur_edges, | ||||
| add_edges (GList               *cur_edges,  | ||||
|            const MetaRectangle *rect, | ||||
|            gboolean             rect_is_internal) | ||||
| { | ||||
| @@ -1583,23 +1560,23 @@ add_edges (GList               *cur_edges, | ||||
|       switch (i) | ||||
|         { | ||||
|         case 0: | ||||
|           temp_edge->side_type = | ||||
|           temp_edge->side_type =  | ||||
|             rect_is_internal ? META_SIDE_LEFT : META_SIDE_RIGHT; | ||||
|           temp_edge->rect.width = 0; | ||||
|           break; | ||||
|         case 1: | ||||
|           temp_edge->side_type = | ||||
|           temp_edge->side_type =  | ||||
|             rect_is_internal ? META_SIDE_RIGHT : META_SIDE_LEFT; | ||||
|           temp_edge->rect.x     += temp_edge->rect.width; | ||||
|           temp_edge->rect.width  = 0; | ||||
|           break; | ||||
|         case 2: | ||||
|           temp_edge->side_type = | ||||
|           temp_edge->side_type =  | ||||
|             rect_is_internal ? META_SIDE_TOP : META_SIDE_BOTTOM; | ||||
|           temp_edge->rect.height = 0; | ||||
|           break; | ||||
|         case 3: | ||||
|           temp_edge->side_type = | ||||
|           temp_edge->side_type =  | ||||
|             rect_is_internal ? META_SIDE_BOTTOM : META_SIDE_TOP; | ||||
|           temp_edge->rect.y      += temp_edge->rect.height; | ||||
|           temp_edge->rect.height  = 0; | ||||
| @@ -1616,8 +1593,8 @@ add_edges (GList               *cur_edges, | ||||
|  * edges to cur_list.  Return cur_list when finished. | ||||
|  */ | ||||
| static GList* | ||||
| split_edge (GList *cur_list, | ||||
|             const MetaEdge *old_edge, | ||||
| split_edge (GList *cur_list,  | ||||
|             const MetaEdge *old_edge,  | ||||
|             const MetaEdge *remove) | ||||
| { | ||||
|   MetaEdge *temp_edge; | ||||
| @@ -1676,7 +1653,7 @@ split_edge (GList *cur_list, | ||||
|  * if and how rect and edge intersect. | ||||
|  */ | ||||
| static void | ||||
| fix_up_edges (MetaRectangle *rect,         MetaEdge *edge, | ||||
| fix_up_edges (MetaRectangle *rect,         MetaEdge *edge,  | ||||
|               GList         **strut_edges, GList    **edge_splits, | ||||
|               gboolean      *edge_needs_removal) | ||||
| { | ||||
| @@ -1800,7 +1777,7 @@ meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect, | ||||
| { | ||||
|   GList        *ret; | ||||
|   GList        *fixed_strut_rects; | ||||
|   GList        *edge_iter; | ||||
|   GList        *edge_iter;  | ||||
|   const GList  *strut_rect_iter; | ||||
|  | ||||
|   /* The algorithm is basically as follows: | ||||
| @@ -1840,7 +1817,7 @@ meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect, | ||||
|           GList *splits_of_cur_edge = NULL; | ||||
|           gboolean edge_needs_removal = FALSE; | ||||
|  | ||||
|           fix_up_edges (strut_rect,       cur_edge, | ||||
|           fix_up_edges (strut_rect,       cur_edge,  | ||||
|                         &new_strut_edges, &splits_of_cur_edge, | ||||
|                         &edge_needs_removal); | ||||
|  | ||||
| @@ -2004,7 +1981,7 @@ meta_rectangle_find_nonintersected_monitor_edges ( | ||||
|   for (; all_struts; all_struts = all_struts->next) | ||||
|     temp_rects = g_slist_prepend (temp_rects, | ||||
|                                   &((MetaStrut*)all_struts->data)->rect); | ||||
|   ret = meta_rectangle_remove_intersections_with_boxes_from_edges (ret, | ||||
|   ret = meta_rectangle_remove_intersections_with_boxes_from_edges (ret,  | ||||
|                                                                    temp_rects); | ||||
|   g_slist_free (temp_rects); | ||||
|  | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user