Compare commits
	
		
			2 Commits
		
	
	
		
			wip/ui-on-
			...
			wip/xdg-sh
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					c9e225822c | ||
| 
						 | 
					1689de7015 | 
							
								
								
									
										22
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -75,15 +75,15 @@ 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/mutter-plugins.pc
 | 
			
		||||
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/wayland/gtk-shell-protocol.c
 | 
			
		||||
src/wayland/gtk-shell-server-protocol.h
 | 
			
		||||
src/wayland/xdg-shell-protocol.c
 | 
			
		||||
src/wayland/xdg-shell-server-protocol.h
 | 
			
		||||
src/wayland/xserver-protocol.c
 | 
			
		||||
src/wayland/xserver-server-protocol.h
 | 
			
		||||
doc/reference/*.args
 | 
			
		||||
doc/reference/*.bak
 | 
			
		||||
doc/reference/*.hierarchy
 | 
			
		||||
@@ -101,11 +101,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
 | 
			
		||||
@@ -1,5 +1,7 @@
 | 
			
		||||
 | 
			
		||||
SUBDIRS=src po doc
 | 
			
		||||
SUBDIRS=src protocol po doc
 | 
			
		||||
 | 
			
		||||
EXTRA_DIST = HACKING MAINTAINERS rationales.txt
 | 
			
		||||
 | 
			
		||||
DISTCLEANFILES = intltool-extract intltool-merge intltool-update po/stamp-it po/.intltool-merge-cache
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										44
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										44
									
								
								NEWS
									
									
									
									
									
								
							@@ -1,47 +1,3 @@
 | 
			
		||||
3.12.0
 | 
			
		||||
======
 | 
			
		||||
* Fix grab issue with SSD xwayland windows [Rui; #726123]
 | 
			
		||||
* Misc. bug fixes [Jasper, Ray, Rui, Florian; #727011]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Rui Matos, Florian Müllner, Jasper St. Pierre, Ray Strode
 | 
			
		||||
 | 
			
		||||
3.11.92
 | 
			
		||||
=======
 | 
			
		||||
* Fix identification of CSD windows [Owen; #723029]
 | 
			
		||||
* Update keyboard state unconditionally [Rui; #722847]
 | 
			
		||||
* Misc bug fixes and cleanups [Owen, Rui, Giovanni, Matthias, Adel, Ryan,
 | 
			
		||||
  Jasper, Marek, Florian; #723580, #726123, #726683]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Giovanni Campagna, Marek Chalupa, Matthias Clasen, Adel Gadllah, Ryan Lortie,
 | 
			
		||||
  Rui Matos, Florian Müllner, Jasper St. Pierre, Owen W. Taylor
 | 
			
		||||
 | 
			
		||||
3.11.91
 | 
			
		||||
=======
 | 
			
		||||
* Don't use keysym to match keybindings [Rui; #678001]
 | 
			
		||||
* Fix message tray icons showing up blank (again) [Adel; #725180]
 | 
			
		||||
* Improve keybinding lookups [Rui; #725588]
 | 
			
		||||
* Fix dynamic updates of titlebar style properties [Owen; #725751]
 | 
			
		||||
* Fix positioning of manually positioned windows [Owen; #724049]
 | 
			
		||||
* Misc bug fixes and cleanups [Jasper, Carlos, Adel, Giovanni, Florian; #720631,
 | 
			
		||||
  #724969, #725216, #724402, #722266, #725338, #725525]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Giovanni Campagna, Adel Gadllah, Carlos Garnacho, Rui Matos, Florian Müllner,
 | 
			
		||||
  Jasper St. Pierre, Owen W. Taylor
 | 
			
		||||
 | 
			
		||||
3.11.90
 | 
			
		||||
=======
 | 
			
		||||
* Fix double-scaling on high DPI resolutions [Adel; #723931]
 | 
			
		||||
* Make tile previews a compositor effect [Stefano, Florian; #665758]
 | 
			
		||||
* Misc. bug fixes and cleanups [Ryan, Giovanni, Jasper, Adel; #722530, #724257,
 | 
			
		||||
  #724258, #720631, #724364, #724472]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Giovanni Campagna, Marek Chalupa, Stefano Facchini, Adel Gadllah,
 | 
			
		||||
  Ryan Lortie, Florian Müllner, Jasper St. Pierre, Rico Tzschichholz
 | 
			
		||||
 | 
			
		||||
3.11.5
 | 
			
		||||
======
 | 
			
		||||
* Fix CSD titlebars being placed off-screen [Jasper; #719772]
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										416
									
								
								README
									
									
									
									
									
										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.10
 | 
			
		||||
REQUIRED_AUTOMAKE_VERSION=1.13
 | 
			
		||||
 | 
			
		||||
(test -f $srcdir/configure.ac \
 | 
			
		||||
  && test -d $srcdir/src) || {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										17
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								configure.ac
									
									
									
									
									
								
							@@ -2,8 +2,8 @@ AC_PREREQ(2.50)
 | 
			
		||||
AC_CONFIG_MACRO_DIR([m4])
 | 
			
		||||
 | 
			
		||||
m4_define([mutter_major_version], [3])
 | 
			
		||||
m4_define([mutter_minor_version], [12])
 | 
			
		||||
m4_define([mutter_micro_version], [0])
 | 
			
		||||
m4_define([mutter_minor_version], [11])
 | 
			
		||||
m4_define([mutter_micro_version], [5])
 | 
			
		||||
 | 
			
		||||
m4_define([mutter_version],
 | 
			
		||||
          [mutter_major_version.mutter_minor_version.mutter_micro_version])
 | 
			
		||||
@@ -16,7 +16,7 @@ AC_INIT([mutter], [mutter_version],
 | 
			
		||||
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 foreign no-dist-gzip dist-xz tar-ustar])
 | 
			
		||||
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],)
 | 
			
		||||
AM_MAINTAINER_MODE([enable])
 | 
			
		||||
 | 
			
		||||
@@ -78,7 +78,7 @@ MUTTER_PC_MODULES="
 | 
			
		||||
   cairo >= 1.10.0
 | 
			
		||||
   gsettings-desktop-schemas >= 3.7.3
 | 
			
		||||
   xcomposite >= 0.2 xfixes xrender xdamage xi >= 1.6.0
 | 
			
		||||
   $CLUTTER_PACKAGE >= 1.17.5
 | 
			
		||||
   $CLUTTER_PACKAGE >= 1.17.1
 | 
			
		||||
   cogl-1.0 >= 1.17.1
 | 
			
		||||
   upower-glib >= 0.99.0
 | 
			
		||||
   gnome-desktop-3.0
 | 
			
		||||
@@ -133,7 +133,7 @@ AC_ARG_WITH([wayland-protocols],
 | 
			
		||||
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"])
 | 
			
		||||
            [XWAYLAND_PATH="$bindir/Xorg"])
 | 
			
		||||
 | 
			
		||||
AM_GLIB_GNU_GETTEXT
 | 
			
		||||
 | 
			
		||||
@@ -142,6 +142,11 @@ AM_GLIB_GNU_GETTEXT
 | 
			
		||||
PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.14.0)
 | 
			
		||||
PKG_CHECK_MODULES(MUTTER_LAUNCH, libdrm libsystemd-login)
 | 
			
		||||
 | 
			
		||||
saved_LIBS="$LIBS"
 | 
			
		||||
LIBS="$LIBS $MUTTER_LAUNCH"
 | 
			
		||||
AC_CHECK_FUNCS([sd_session_get_vt])
 | 
			
		||||
LIBS="$saved_LIBS"
 | 
			
		||||
 | 
			
		||||
# Unconditionally use this dir to avoid a circular dep with gnomecc
 | 
			
		||||
GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings"
 | 
			
		||||
AC_SUBST(GNOME_KEYBINDINGS_KEYSDIR)
 | 
			
		||||
@@ -453,6 +458,7 @@ doc/reference/meta-docs.sgml
 | 
			
		||||
src/Makefile
 | 
			
		||||
src/libmutter-wayland.pc
 | 
			
		||||
src/compositor/plugins/Makefile
 | 
			
		||||
protocol/Makefile
 | 
			
		||||
po/Makefile.in
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
@@ -480,6 +486,7 @@ mutter-wayland-$VERSION
 | 
			
		||||
	Session management:       ${found_sm}
 | 
			
		||||
	Shape extension:          ${found_shape}
 | 
			
		||||
	Xsync:                    ${found_xsync}
 | 
			
		||||
	Xcursor:                  ${have_xcursor}
 | 
			
		||||
"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -16,11 +16,11 @@ src/core/monitor.c
 | 
			
		||||
src/core/mutter.c
 | 
			
		||||
src/core/prefs.c
 | 
			
		||||
src/core/screen.c
 | 
			
		||||
src/x11/session.c
 | 
			
		||||
src/core/session.c
 | 
			
		||||
src/core/util.c
 | 
			
		||||
src/core/window.c
 | 
			
		||||
src/x11/window-props.c
 | 
			
		||||
src/x11/xprops.c
 | 
			
		||||
src/core/window-props.c
 | 
			
		||||
src/core/xprops.c
 | 
			
		||||
src/mutter-wayland.desktop.in
 | 
			
		||||
src/org.gnome.mutter.gschema.xml.in
 | 
			
		||||
src/org.gnome.mutter.wayland.gschema.xml.in
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								protocol/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								protocol/Makefile.am
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
NULL =
 | 
			
		||||
 | 
			
		||||
EXTRA_DIST = \
 | 
			
		||||
	gtk-shell.xml \
 | 
			
		||||
	xdg-shell.xml \
 | 
			
		||||
	xserver.xml \
 | 
			
		||||
	$(NULL)
 | 
			
		||||
@@ -40,22 +40,19 @@
 | 
			
		||||
 | 
			
		||||
    <enum name="version">
 | 
			
		||||
      <description summary="latest protocol version">
 | 
			
		||||
	The 'current' member of this enum gives the version of the
 | 
			
		||||
	protocol.  Implementations can compare this to the version
 | 
			
		||||
	they implement using static_assert to ensure the protocol and
 | 
			
		||||
	implementation versions match.
 | 
			
		||||
	Use this enum to check the protocol version, and it will be updated
 | 
			
		||||
	automatically.
 | 
			
		||||
      </description>
 | 
			
		||||
      <entry name="current" value="3" summary="Always the latest version"/>
 | 
			
		||||
      <entry name="current" value="2" summary="Always the latest version"/>
 | 
			
		||||
    </enum>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    <request name="use_unstable_version">
 | 
			
		||||
      <description summary="enable use of this unstable version">
 | 
			
		||||
	Negotiate the unstable version of the interface.  This
 | 
			
		||||
	mechanism is in place to ensure client and server agree on the
 | 
			
		||||
	unstable versions of the protocol that they speak or exit
 | 
			
		||||
	cleanly if they don't agree.  This request will go away once
 | 
			
		||||
	the xdg-shell protocol is stable.
 | 
			
		||||
	Use this request in order to enable use of this interface.
 | 
			
		||||
 | 
			
		||||
	Understand and agree that one is using an unstable interface,
 | 
			
		||||
	that will likely change in the future, breaking the API.
 | 
			
		||||
      </description>
 | 
			
		||||
      <arg name="version" type="int"/>
 | 
			
		||||
    </request>
 | 
			
		||||
@@ -278,7 +275,7 @@
 | 
			
		||||
      <arg name="output" type="object" interface="wl_output" allow-null="true"/>
 | 
			
		||||
    </request>
 | 
			
		||||
 | 
			
		||||
    <enum name="state">
 | 
			
		||||
    <enum name="state_type">
 | 
			
		||||
      <description summary="types of state on the surface">
 | 
			
		||||
        The different state values used on the surface. This is designed for
 | 
			
		||||
        state values like maximized, fullscreen. It is paired with the
 | 
			
		||||
							
								
								
									
										18
									
								
								protocol/xserver.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								protocol/xserver.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
<protocol name="xserver">
 | 
			
		||||
 | 
			
		||||
  <interface name="xserver" version="1">
 | 
			
		||||
    <request name="set_window_id">
 | 
			
		||||
      <arg name="surface" type="object" interface="wl_surface"/>
 | 
			
		||||
      <arg name="id" type="uint"/>
 | 
			
		||||
    </request>
 | 
			
		||||
 | 
			
		||||
    <event name="client">
 | 
			
		||||
      <arg name="fd" type="fd"/>
 | 
			
		||||
    </event>
 | 
			
		||||
 | 
			
		||||
    <event name="listen_socket">
 | 
			
		||||
      <arg name="fd" type="fd"/>
 | 
			
		||||
    </event>
 | 
			
		||||
  </interface>
 | 
			
		||||
 | 
			
		||||
</protocol>
 | 
			
		||||
@@ -29,18 +29,6 @@
 | 
			
		||||
	<KeyListEntry name="move-to-workspace-down"
 | 
			
		||||
	              _description="Move window one workspace down" />
 | 
			
		||||
 | 
			
		||||
	<KeyListEntry name="move-to-monitor-left"
 | 
			
		||||
	              _description="Move window one monitor to the left" />
 | 
			
		||||
 | 
			
		||||
	<KeyListEntry name="move-to-monitor-right"
 | 
			
		||||
	              _description="Move window one monitor to the right" />
 | 
			
		||||
 | 
			
		||||
	<KeyListEntry name="move-to-monitor-up"
 | 
			
		||||
	              _description="Move window one monitor up" />
 | 
			
		||||
 | 
			
		||||
	<KeyListEntry name="move-to-monitor-down"
 | 
			
		||||
	              _description="Move window one monitor down" />
 | 
			
		||||
 | 
			
		||||
	<KeyListEntry name="switch-applications"
 | 
			
		||||
	              _description="Switch applications"/>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										154
									
								
								src/Makefile.am
									
									
									
									
									
								
							
							
						
						
									
										154
									
								
								src/Makefile.am
									
									
									
									
									
								
							@@ -6,14 +6,12 @@ lib_LTLIBRARIES = libmutter-wayland.la
 | 
			
		||||
SUBDIRS=compositor/plugins
 | 
			
		||||
 | 
			
		||||
INCLUDES=								\
 | 
			
		||||
	-DCLUTTER_ENABLE_COMPOSITOR_API					\
 | 
			
		||||
	-DCLUTTER_ENABLE_EXPERIMENTAL_API				\
 | 
			
		||||
	-DCOGL_ENABLE_EXPERIMENTAL_API					\
 | 
			
		||||
	-DCOGL_ENABLE_EXPERIMENTAL_2_0_API                              \
 | 
			
		||||
	$(MUTTER_CFLAGS)						\
 | 
			
		||||
	-I$(top_builddir)						\
 | 
			
		||||
	-I$(srcdir)							\
 | 
			
		||||
	-I$(srcdir)/backends						\
 | 
			
		||||
	-I$(srcdir)/core						\
 | 
			
		||||
	-I$(srcdir)/ui							\
 | 
			
		||||
	-I$(srcdir)/compositor						\
 | 
			
		||||
@@ -30,55 +28,28 @@ INCLUDES=								\
 | 
			
		||||
	-DMUTTER_PLUGIN_API_VERSION=$(MUTTER_PLUGIN_API_VERSION)	\
 | 
			
		||||
	-DMUTTER_PKGLIBDIR=\"$(pkglibdir)\"				\
 | 
			
		||||
	-DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\"			\
 | 
			
		||||
	-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\"			\
 | 
			
		||||
	-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\"
 | 
			
		||||
 | 
			
		||||
INCLUDES += \
 | 
			
		||||
	-I$(srcdir)/wayland						\
 | 
			
		||||
	-I$(builddir)/wayland						\
 | 
			
		||||
	-DXWAYLAND_PATH='"@XWAYLAND_PATH@"'
 | 
			
		||||
 | 
			
		||||
mutter_built_sources = \
 | 
			
		||||
	$(dbus_idle_built_sources)		\
 | 
			
		||||
	$(dbus_display_config_built_sources)	\
 | 
			
		||||
	$(dbus_xrandr_built_sources)		\
 | 
			
		||||
	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
 | 
			
		||||
	wayland/gtk-shell-protocol.c		\
 | 
			
		||||
	wayland/gtk-shell-server-protocol.h	\
 | 
			
		||||
	wayland/xdg-shell-protocol.c		\
 | 
			
		||||
	wayland/xdg-shell-server-protocol.h	\
 | 
			
		||||
	wayland/xserver-protocol.c		\
 | 
			
		||||
	wayland/xserver-server-protocol.h
 | 
			
		||||
 | 
			
		||||
libmutter_wayland_la_SOURCES =			\
 | 
			
		||||
	backends/meta-backend.c			\
 | 
			
		||||
	backends/meta-backend.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-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/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-weston-launch.c		\
 | 
			
		||||
	backends/native/meta-weston-launch.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	\
 | 
			
		||||
	backends/x11/meta-xrandr-shared.h		\
 | 
			
		||||
	core/above-tab-keycode.c		\
 | 
			
		||||
	core/async-getprop.c			\
 | 
			
		||||
	core/async-getprop.h			\
 | 
			
		||||
	core/barrier.c				\
 | 
			
		||||
	meta/barrier.h				\
 | 
			
		||||
	core/bell.c				\
 | 
			
		||||
@@ -109,10 +80,6 @@ libmutter_wayland_la_SOURCES =			\
 | 
			
		||||
	compositor/meta-shaped-texture-private.h 	\
 | 
			
		||||
	compositor/meta-surface-actor.c		\
 | 
			
		||||
	compositor/meta-surface-actor.h		\
 | 
			
		||||
	compositor/meta-surface-actor-x11.c	\
 | 
			
		||||
	compositor/meta-surface-actor-x11.h	\
 | 
			
		||||
	compositor/meta-surface-actor-wayland.c	\
 | 
			
		||||
	compositor/meta-surface-actor-wayland.h	\
 | 
			
		||||
	compositor/meta-texture-rectangle.c	\
 | 
			
		||||
	compositor/meta-texture-rectangle.h	\
 | 
			
		||||
	compositor/meta-texture-tower.c		\
 | 
			
		||||
@@ -133,6 +100,7 @@ libmutter_wayland_la_SOURCES =			\
 | 
			
		||||
	meta/meta-shadow-factory.h		\
 | 
			
		||||
	meta/meta-window-actor.h		\
 | 
			
		||||
	meta/compositor-mutter.h 		\
 | 
			
		||||
	core/above-tab-keycode.c		\
 | 
			
		||||
	core/constraints.c			\
 | 
			
		||||
	core/constraints.h			\
 | 
			
		||||
	core/core.c				\
 | 
			
		||||
@@ -140,19 +108,39 @@ libmutter_wayland_la_SOURCES =			\
 | 
			
		||||
	core/display.c				\
 | 
			
		||||
	core/display-private.h			\
 | 
			
		||||
	meta/display.h				\
 | 
			
		||||
	ui/draw-workspace.c			\
 | 
			
		||||
	ui/draw-workspace.h			\
 | 
			
		||||
	core/edge-resistance.c			\
 | 
			
		||||
	core/edge-resistance.h			\
 | 
			
		||||
	core/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-kms.c			\
 | 
			
		||||
	core/monitor-private.h			\
 | 
			
		||||
	core/monitor-xrandr.c			\
 | 
			
		||||
	core/mutter-Xatomtype.h			\
 | 
			
		||||
	core/place.c				\
 | 
			
		||||
	core/place.h				\
 | 
			
		||||
	core/prefs.c				\
 | 
			
		||||
@@ -161,6 +149,8 @@ libmutter_wayland_la_SOURCES =			\
 | 
			
		||||
	core/screen-private.h			\
 | 
			
		||||
	meta/screen.h				\
 | 
			
		||||
	meta/types.h				\
 | 
			
		||||
	core/session.c				\
 | 
			
		||||
	core/session.h				\
 | 
			
		||||
	core/stack.c				\
 | 
			
		||||
	core/stack.h				\
 | 
			
		||||
	core/stack-tracker.c			\
 | 
			
		||||
@@ -168,11 +158,17 @@ libmutter_wayland_la_SOURCES =			\
 | 
			
		||||
	core/util.c				\
 | 
			
		||||
	meta/util.h				\
 | 
			
		||||
	core/util-private.h			\
 | 
			
		||||
	core/window-props.c			\
 | 
			
		||||
	core/window-props.h			\
 | 
			
		||||
	core/window-x11.c			\
 | 
			
		||||
	core/window-x11.h			\
 | 
			
		||||
	core/window.c				\
 | 
			
		||||
	core/window-private.h			\
 | 
			
		||||
	meta/window.h				\
 | 
			
		||||
	core/workspace.c			\
 | 
			
		||||
	core/workspace-private.h		\
 | 
			
		||||
	core/xprops.c				\
 | 
			
		||||
	core/xprops.h				\
 | 
			
		||||
	meta/common.h				\
 | 
			
		||||
	core/core.h				\
 | 
			
		||||
	ui/ui.h					\
 | 
			
		||||
@@ -184,36 +180,19 @@ libmutter_wayland_la_SOURCES =			\
 | 
			
		||||
	ui/metaaccellabel.h			\
 | 
			
		||||
	ui/resizepopup.c			\
 | 
			
		||||
	ui/resizepopup.h			\
 | 
			
		||||
	ui/tabpopup.c				\
 | 
			
		||||
	ui/tabpopup.h				\
 | 
			
		||||
	ui/tile-preview.c			\
 | 
			
		||||
	ui/tile-preview.h			\
 | 
			
		||||
	ui/theme-parser.c			\
 | 
			
		||||
	ui/theme.c				\
 | 
			
		||||
	meta/theme.h				\
 | 
			
		||||
	ui/theme-private.h			\
 | 
			
		||||
	ui/ui.c					\
 | 
			
		||||
	x11/iconcache.c				\
 | 
			
		||||
	x11/iconcache.h				\
 | 
			
		||||
	x11/async-getprop.c			\
 | 
			
		||||
	x11/async-getprop.h			\
 | 
			
		||||
	x11/group-private.h			\
 | 
			
		||||
	x11/group-props.c			\
 | 
			
		||||
	x11/group-props.h			\
 | 
			
		||||
	x11/group.c				\
 | 
			
		||||
	meta/group.h				\
 | 
			
		||||
	x11/session.c				\
 | 
			
		||||
	x11/session.h				\
 | 
			
		||||
	x11/window-props.c			\
 | 
			
		||||
	x11/window-props.h			\
 | 
			
		||||
	x11/window-x11.c			\
 | 
			
		||||
	x11/window-x11.h			\
 | 
			
		||||
	x11/window-x11-private.h		\
 | 
			
		||||
	x11/xprops.c				\
 | 
			
		||||
	x11/xprops.h				\
 | 
			
		||||
	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-xwayland.c			\
 | 
			
		||||
	wayland/meta-wayland-data-device.c      \
 | 
			
		||||
	wayland/meta-wayland-data-device.h      \
 | 
			
		||||
	wayland/meta-wayland-keyboard.c		\
 | 
			
		||||
@@ -228,8 +207,8 @@ libmutter_wayland_la_SOURCES =			\
 | 
			
		||||
	wayland/meta-wayland-surface.h		\
 | 
			
		||||
	wayland/meta-wayland-types.h		\
 | 
			
		||||
	wayland/meta-wayland-versions.h		\
 | 
			
		||||
	wayland/window-wayland.c		\
 | 
			
		||||
	wayland/window-wayland.h
 | 
			
		||||
	wayland/meta-weston-launch.c		\
 | 
			
		||||
	wayland/meta-weston-launch.h
 | 
			
		||||
 | 
			
		||||
nodist_libmutter_wayland_la_SOURCES =		\
 | 
			
		||||
	$(mutter_built_sources)
 | 
			
		||||
@@ -286,9 +265,7 @@ mutter_wayland_LDADD = $(MUTTER_LIBS) libmutter-wayland.la
 | 
			
		||||
 | 
			
		||||
bin_PROGRAMS+=mutter-launch
 | 
			
		||||
 | 
			
		||||
mutter_launch_SOURCES = 			\
 | 
			
		||||
	backends/native/weston-launch.c 	\
 | 
			
		||||
	backends/native/weston-launch.h
 | 
			
		||||
mutter_launch_SOURCES = wayland/weston-launch.c wayland/weston-launch.h
 | 
			
		||||
 | 
			
		||||
mutter_launch_CFLAGS = $(MUTTER_LAUNCH_CFLAGS) -DLIBDIR=\"$(libdir)\"
 | 
			
		||||
mutter_launch_LDFLAGS = $(MUTTER_LAUNCH_LIBS) -lpam
 | 
			
		||||
@@ -332,7 +309,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
 | 
			
		||||
 | 
			
		||||
@@ -383,15 +360,13 @@ EXTRA_DIST=$(desktopfiles_files) 	\
 | 
			
		||||
	$(desktopfiles_in_files)	\
 | 
			
		||||
	$(wmproperties_in_files)	\
 | 
			
		||||
	$(xml_in_files)			\
 | 
			
		||||
	$(wayland_protocols)		\
 | 
			
		||||
	org.gnome.mutter.gschema.xml.in \
 | 
			
		||||
	org.gnome.mutter.wayland.gschema.xml.in \
 | 
			
		||||
	mutter-schemas.convert \
 | 
			
		||||
	libmutter-wayland.pc.in \
 | 
			
		||||
	mutter-enum-types.h.in \
 | 
			
		||||
	mutter-enum-types.c.in \
 | 
			
		||||
	org.gnome.Mutter.DisplayConfig.xml	\
 | 
			
		||||
	org.gnome.Mutter.IdleMonitor.xml
 | 
			
		||||
	xrandr.xml idle-monitor.xml
 | 
			
		||||
 | 
			
		||||
BUILT_SOURCES = $(mutter_built_sources)
 | 
			
		||||
MUTTER_STAMP_FILES = stamp-mutter-enum-types.h
 | 
			
		||||
@@ -416,24 +391,27 @@ 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) : 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
 | 
			
		||||
		$(srcdir)/idle-monitor.xml
 | 
			
		||||
 | 
			
		||||
%-protocol.c : $(srcdir)/wayland/protocol/%.xml
 | 
			
		||||
wayland/%-protocol.c : $(top_builddir)/protocol/%.xml
 | 
			
		||||
	mkdir -p wayland
 | 
			
		||||
	$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
 | 
			
		||||
%-server-protocol.h : $(srcdir)/wayland/protocol/%.xml
 | 
			
		||||
wayland/%-server-protocol.h : $(top_builddir)/protocol/%.xml
 | 
			
		||||
	mkdir -p wayland
 | 
			
		||||
	$(AM_V_GEN)$(WAYLAND_SCANNER) server-header < $< > $@
 | 
			
		||||
 
 | 
			
		||||
@@ -1,157 +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/main.h>
 | 
			
		||||
 | 
			
		||||
#include <gdk/gdkx.h>
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
#include <clutter/x11/clutter-x11.h>
 | 
			
		||||
 | 
			
		||||
#include "backends/native/meta-weston-launch.h"
 | 
			
		||||
#include <meta/util.h>
 | 
			
		||||
 | 
			
		||||
/* 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
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static MetaLauncher *launcher;
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_clutter_init (void)
 | 
			
		||||
{
 | 
			
		||||
  GSource *source;
 | 
			
		||||
 | 
			
		||||
  /* When running as an X11 compositor, we install our own event filter and
 | 
			
		||||
   * pass events to Clutter explicitly, so we need to prevent Clutter from
 | 
			
		||||
   * handling our events.
 | 
			
		||||
   *
 | 
			
		||||
   * However, when running as a Wayland compostior under X11 nested, Clutter
 | 
			
		||||
   * Clutter needs to see events related to its own window. We need to
 | 
			
		||||
   * eventually replace this with a proper frontend / backend split: Clutter
 | 
			
		||||
   * under nested is connecting to the "host X server" to get its events it
 | 
			
		||||
   * needs to put up a window, and GTK+ is connecting to the "inner X server".
 | 
			
		||||
   * The two would the same in the X11 compositor case, but not when running
 | 
			
		||||
   * XWayland as a Wayland compositor.
 | 
			
		||||
   */
 | 
			
		||||
  if (!meta_is_wayland_compositor ())
 | 
			
		||||
    {
 | 
			
		||||
      clutter_x11_set_display (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
 | 
			
		||||
      clutter_x11_disable_event_retrieval ();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /* If we're running on bare metal, we're a display server,
 | 
			
		||||
   * so start talking to weston-launch. */
 | 
			
		||||
#if defined(CLUTTER_WINDOWING_EGL)
 | 
			
		||||
  if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
 | 
			
		||||
    launcher = meta_launcher_new ();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_activate_vt (int vt, GError **error)
 | 
			
		||||
{
 | 
			
		||||
  if (launcher)
 | 
			
		||||
    return meta_launcher_activate_vt (launcher, vt, error);
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      g_debug ("Ignoring VT switch keybinding, not running as display server");
 | 
			
		||||
      return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 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;
 | 
			
		||||
 | 
			
		||||
  if (!meta_launcher_activate_vt (launcher, -1, &error))
 | 
			
		||||
    {
 | 
			
		||||
      g_warning ("Could not activate session: %s\n", error->message);
 | 
			
		||||
      g_error_free (error);
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,34 +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>
 | 
			
		||||
 | 
			
		||||
void meta_clutter_init (void);
 | 
			
		||||
 | 
			
		||||
gboolean meta_activate_vt (int vt, GError **error);
 | 
			
		||||
 | 
			
		||||
#endif /* META_BACKEND_H */
 | 
			
		||||
@@ -1,50 +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;
 | 
			
		||||
 | 
			
		||||
  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,98 +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 "meta-cursor.h"
 | 
			
		||||
 | 
			
		||||
struct _MetaCursorTracker {
 | 
			
		||||
  GObject parent_instance;
 | 
			
		||||
 | 
			
		||||
  MetaScreen *screen;
 | 
			
		||||
 | 
			
		||||
  gboolean is_showing;
 | 
			
		||||
  gboolean has_hw_cursor;
 | 
			
		||||
 | 
			
		||||
  /* The cursor tracker stores the cursor for the current grab
 | 
			
		||||
   * operation, the cursor for the window with pointer focus, and
 | 
			
		||||
   * the cursor for the root window, which contains either the
 | 
			
		||||
   * default arrow cursor or the 'busy' hourglass if we're launching
 | 
			
		||||
   * an app.
 | 
			
		||||
   *
 | 
			
		||||
   * We choose the first one available -- if there's a grab cursor,
 | 
			
		||||
   * we choose that cursor, if there's window cursor, we choose that,
 | 
			
		||||
   * otherwise we choose the root cursor.
 | 
			
		||||
   *
 | 
			
		||||
   * The displayed_cursor contains the chosen cursor.
 | 
			
		||||
   */
 | 
			
		||||
  MetaCursorReference *displayed_cursor;
 | 
			
		||||
 | 
			
		||||
  MetaCursorReference *grab_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;
 | 
			
		||||
 | 
			
		||||
  MetaCursorReference *theme_cursors[META_CURSOR_LAST];
 | 
			
		||||
 | 
			
		||||
  int current_x, current_y;
 | 
			
		||||
  MetaRectangle current_rect;
 | 
			
		||||
  MetaRectangle previous_rect;
 | 
			
		||||
  gboolean previous_is_valid;
 | 
			
		||||
 | 
			
		||||
  CoglPipeline *pipeline;
 | 
			
		||||
  int drm_fd;
 | 
			
		||||
  struct gbm_device *gbm;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaCursorTrackerClass {
 | 
			
		||||
  GObjectClass parent_class;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
gboolean meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
 | 
			
		||||
					    XEvent            *xevent);
 | 
			
		||||
 | 
			
		||||
void     meta_cursor_tracker_set_grab_cursor     (MetaCursorTracker   *tracker,
 | 
			
		||||
                                                  MetaCursorReference *cursor);
 | 
			
		||||
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);
 | 
			
		||||
void     meta_cursor_tracker_paint           (MetaCursorTracker *tracker);
 | 
			
		||||
 | 
			
		||||
void     meta_cursor_tracker_force_update (MetaCursorTracker *tracker);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1,412 +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-cursor-tracker-private.h" /* for tracker->gbm */
 | 
			
		||||
 | 
			
		||||
#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 void
 | 
			
		||||
translate_meta_cursor (MetaCursor   cursor,
 | 
			
		||||
                       guint       *glyph_out,
 | 
			
		||||
                       const char **name_out)
 | 
			
		||||
{
 | 
			
		||||
  guint glyph = XC_num_glyphs;
 | 
			
		||||
  const char *name = NULL;
 | 
			
		||||
 | 
			
		||||
  switch (cursor)
 | 
			
		||||
    {
 | 
			
		||||
    case META_CURSOR_DEFAULT:
 | 
			
		||||
      glyph = XC_left_ptr;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_NORTH_RESIZE:
 | 
			
		||||
      glyph = XC_top_side;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_SOUTH_RESIZE:
 | 
			
		||||
      glyph = XC_bottom_side;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_WEST_RESIZE:
 | 
			
		||||
      glyph = XC_left_side;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_EAST_RESIZE:
 | 
			
		||||
      glyph = XC_right_side;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_SE_RESIZE:
 | 
			
		||||
      glyph = XC_bottom_right_corner;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_SW_RESIZE:
 | 
			
		||||
      glyph = XC_bottom_left_corner;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_NE_RESIZE:
 | 
			
		||||
      glyph = XC_top_right_corner;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_NW_RESIZE:
 | 
			
		||||
      glyph = XC_top_left_corner;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_MOVE_OR_RESIZE_WINDOW:
 | 
			
		||||
      glyph = XC_fleur;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_BUSY:
 | 
			
		||||
      glyph = XC_watch;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_DND_IN_DRAG:
 | 
			
		||||
      name = "dnd-none";
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_DND_MOVE:
 | 
			
		||||
      name = "dnd-move";
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_DND_COPY:
 | 
			
		||||
      name = "dnd-copy";
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_DND_UNSUPPORTED_TARGET:
 | 
			
		||||
      name = "dnd-none";
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_POINTING_HAND:
 | 
			
		||||
      glyph = XC_hand2;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_CROSSHAIR:
 | 
			
		||||
      glyph = XC_crosshair;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_IBEAM:
 | 
			
		||||
      glyph = XC_xterm;
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
      g_assert_not_reached ();
 | 
			
		||||
      glyph = 0; /* silence compiler */
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  *glyph_out = glyph;
 | 
			
		||||
  *name_out = name;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Cursor
 | 
			
		||||
load_cursor_on_server (MetaDisplay *display,
 | 
			
		||||
                       MetaCursor   cursor)
 | 
			
		||||
{
 | 
			
		||||
  Cursor xcursor;
 | 
			
		||||
  guint glyph;
 | 
			
		||||
  const char *name;
 | 
			
		||||
 | 
			
		||||
  translate_meta_cursor (cursor, &glyph, &name);
 | 
			
		||||
 | 
			
		||||
  if (name != NULL)
 | 
			
		||||
    xcursor = XcursorLibraryLoadCursor (display->xdisplay, name);
 | 
			
		||||
  else
 | 
			
		||||
    xcursor = XCreateFontCursor (display->xdisplay, glyph);
 | 
			
		||||
 | 
			
		||||
  return xcursor;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Cursor
 | 
			
		||||
meta_display_create_x_cursor (MetaDisplay *display,
 | 
			
		||||
                              MetaCursor cursor)
 | 
			
		||||
{
 | 
			
		||||
  return load_cursor_on_server (display, cursor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static XcursorImage *
 | 
			
		||||
load_cursor_on_client (MetaDisplay *display,
 | 
			
		||||
                       MetaCursor   cursor)
 | 
			
		||||
{
 | 
			
		||||
  XcursorImage *image;
 | 
			
		||||
  guint glyph;
 | 
			
		||||
  const char *name;
 | 
			
		||||
  const char *theme = XcursorGetTheme (display->xdisplay);
 | 
			
		||||
  int size = XcursorGetDefaultSize (display->xdisplay);
 | 
			
		||||
 | 
			
		||||
  translate_meta_cursor (cursor, &glyph, &name);
 | 
			
		||||
 | 
			
		||||
  if (name != NULL)
 | 
			
		||||
    image = XcursorLibraryLoadImage (name, theme, size);
 | 
			
		||||
  else
 | 
			
		||||
    image = XcursorShapeLoadImage (glyph, theme, size);
 | 
			
		||||
 | 
			
		||||
  return image;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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 void
 | 
			
		||||
meta_cursor_image_load_from_xcursor_image (MetaCursorTracker *tracker,
 | 
			
		||||
                                           MetaCursorImage   *image,
 | 
			
		||||
                                           XcursorImage      *xc_image)
 | 
			
		||||
{
 | 
			
		||||
  int width, height, rowstride;
 | 
			
		||||
  CoglPixelFormat cogl_format;
 | 
			
		||||
  uint32_t gbm_format;
 | 
			
		||||
  ClutterBackend *clutter_backend;
 | 
			
		||||
  CoglContext *cogl_context;
 | 
			
		||||
 | 
			
		||||
  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);
 | 
			
		||||
 | 
			
		||||
  if (tracker->gbm)
 | 
			
		||||
    meta_cursor_image_load_gbm_buffer (tracker->gbm,
 | 
			
		||||
                                       image,
 | 
			
		||||
                                       (uint8_t *) xc_image->pixels,
 | 
			
		||||
                                       width, height, rowstride,
 | 
			
		||||
                                       gbm_format);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetaCursorReference *
 | 
			
		||||
meta_cursor_reference_from_theme (MetaCursorTracker  *tracker,
 | 
			
		||||
                                  MetaCursor          cursor)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorReference *self;
 | 
			
		||||
  XcursorImage *image;
 | 
			
		||||
 | 
			
		||||
  if (tracker->theme_cursors[cursor])
 | 
			
		||||
    return meta_cursor_reference_ref (tracker->theme_cursors[cursor]);
 | 
			
		||||
 | 
			
		||||
  image = load_cursor_on_client (tracker->screen->display, cursor);
 | 
			
		||||
  if (!image)
 | 
			
		||||
    return NULL;
 | 
			
		||||
 | 
			
		||||
  self = g_slice_new0 (MetaCursorReference);
 | 
			
		||||
  self->ref_count = 1;
 | 
			
		||||
  meta_cursor_image_load_from_xcursor_image (tracker, &self->image, image);
 | 
			
		||||
 | 
			
		||||
  XcursorImageDestroy (image);
 | 
			
		||||
  return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_cursor_image_load_from_buffer (MetaCursorTracker  *tracker,
 | 
			
		||||
                                    MetaCursorImage    *image,
 | 
			
		||||
                                    struct wl_resource *buffer,
 | 
			
		||||
                                    int                 hot_x,
 | 
			
		||||
                                    int                 hot_y)
 | 
			
		||||
{
 | 
			
		||||
  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 (tracker->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 (tracker->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 (tracker->gbm)
 | 
			
		||||
        {
 | 
			
		||||
          image->bo = gbm_bo_import (tracker->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 (MetaCursorTracker  *tracker,
 | 
			
		||||
                                   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 (tracker, &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;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,42 +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/meta-cursor-tracker.h>
 | 
			
		||||
#include <meta/common.h>
 | 
			
		||||
#include <wayland-server.h>
 | 
			
		||||
 | 
			
		||||
MetaCursorReference * meta_cursor_reference_from_theme  (MetaCursorTracker  *tracker,
 | 
			
		||||
                                                         MetaCursor          cursor);
 | 
			
		||||
 | 
			
		||||
MetaCursorReference * meta_cursor_reference_from_buffer (MetaCursorTracker  *tracker,
 | 
			
		||||
                                                         struct wl_resource *buffer,
 | 
			
		||||
                                                         int                 hot_x,
 | 
			
		||||
                                                         int                 hot_y);
 | 
			
		||||
 | 
			
		||||
#endif /* META_CURSOR_H */
 | 
			
		||||
@@ -1,286 +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));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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,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
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 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 "backends/x11/meta-idle-monitor-xsync.h"
 | 
			
		||||
#include "backends/native/meta-idle-monitor-native.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)
 | 
			
		||||
 | 
			
		||||
static MetaIdleMonitor *device_monitors[256];
 | 
			
		||||
static int              device_id_max;
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GType
 | 
			
		||||
get_idle_monitor_type (void)
 | 
			
		||||
{
 | 
			
		||||
  if (meta_is_wayland_compositor ())
 | 
			
		||||
    return META_TYPE_IDLE_MONITOR_NATIVE;
 | 
			
		||||
  else
 | 
			
		||||
    return META_TYPE_IDLE_MONITOR_XSYNC;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
ensure_device_monitor (int device_id)
 | 
			
		||||
{
 | 
			
		||||
  if (device_monitors[device_id])
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  device_monitors[device_id] = g_object_new (get_idle_monitor_type (),
 | 
			
		||||
                                             "device-id", device_id,
 | 
			
		||||
                                             NULL);
 | 
			
		||||
  device_id_max = MAX (device_id_max, device_id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* FIXME -- destroy device monitors at some point */
 | 
			
		||||
G_GNUC_UNUSED static void
 | 
			
		||||
destroy_device_monitor (int device_id)
 | 
			
		||||
{
 | 
			
		||||
  g_clear_object (&device_monitors[device_id]);
 | 
			
		||||
  if (device_id == device_id_max)
 | 
			
		||||
    device_id_max--;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 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)
 | 
			
		||||
{
 | 
			
		||||
  ensure_device_monitor (0);
 | 
			
		||||
  return device_monitors[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)
 | 
			
		||||
{
 | 
			
		||||
  g_return_val_if_fail (device_id > 0 && device_id < 256, NULL);
 | 
			
		||||
 | 
			
		||||
  ensure_device_monitor (device_id);
 | 
			
		||||
  return device_monitors[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: (allow-none): The callback to call when the user has
 | 
			
		||||
 *     accumulated @interval_msec milliseconds of idle time.
 | 
			
		||||
 * @user_data: (allow-none): 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: (allow-none): The callback to call when the user is
 | 
			
		||||
 *     active again.
 | 
			
		||||
 * @user_data: (allow-none): 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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_idle_monitor_xsync_handle_xevent_all (XEvent *xevent)
 | 
			
		||||
{
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  if (meta_is_wayland_compositor ())
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i <= device_id_max; i++)
 | 
			
		||||
    if (device_monitors[i])
 | 
			
		||||
      meta_idle_monitor_xsync_handle_xevent (device_monitors[i], (XSyncAlarmNotifyEvent*)xevent);
 | 
			
		||||
}
 | 
			
		||||
@@ -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,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,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,366 +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/util.h>
 | 
			
		||||
#include "display-private.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);
 | 
			
		||||
 | 
			
		||||
  g_assert (!meta_is_wayland_compositor ());
 | 
			
		||||
 | 
			
		||||
  monitor_xsync->display = meta_get_display ()->xdisplay;
 | 
			
		||||
  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);
 | 
			
		||||
        }
 | 
			
		||||
      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,49 +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);
 | 
			
		||||
 | 
			
		||||
void meta_idle_monitor_xsync_handle_xevent_all (XEvent *xevent);
 | 
			
		||||
 | 
			
		||||
#endif /* META_IDLE_MONITOR_XSYNC_H */
 | 
			
		||||
@@ -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_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);
 | 
			
		||||
 | 
			
		||||
#endif /* META_MONITOR_MANAGER_XRANDR_H */
 | 
			
		||||
@@ -11,21 +11,35 @@
 | 
			
		||||
#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           show_redraw : 1;
 | 
			
		||||
  guint           debug       : 1;
 | 
			
		||||
  guint           no_mipmaps  : 1;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
  ClutterActor          *stage, *window_group, *top_window_group;
 | 
			
		||||
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;
 | 
			
		||||
@@ -43,17 +57,19 @@ struct _MetaCompositor
 | 
			
		||||
/* 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);
 | 
			
		||||
 | 
			
		||||
#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
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -315,44 +324,3 @@ meta_plugin_manager_confirm_display_change (MetaPluginManager *plugin_mgr)
 | 
			
		||||
  else
 | 
			
		||||
    return meta_plugin_complete_display_change (plugin, TRUE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_plugin_manager_show_tile_preview (MetaPluginManager *plugin_mgr,
 | 
			
		||||
                                       MetaWindow        *window,
 | 
			
		||||
                                       MetaRectangle     *tile_rect,
 | 
			
		||||
                                       int                tile_monitor_number)
 | 
			
		||||
{
 | 
			
		||||
  MetaPlugin *plugin = plugin_mgr->plugin;
 | 
			
		||||
  MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
 | 
			
		||||
  MetaDisplay *display = plugin_mgr->compositor->display;
 | 
			
		||||
 | 
			
		||||
  if (display->display_opening)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  if (klass->show_tile_preview)
 | 
			
		||||
    {
 | 
			
		||||
      klass->show_tile_preview (plugin, window, tile_rect, tile_monitor_number);
 | 
			
		||||
      return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_plugin_manager_hide_tile_preview (MetaPluginManager *plugin_mgr)
 | 
			
		||||
{
 | 
			
		||||
  MetaPlugin *plugin = plugin_mgr->plugin;
 | 
			
		||||
  MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
 | 
			
		||||
  MetaDisplay *display = plugin_mgr->compositor->display;
 | 
			
		||||
 | 
			
		||||
  if (display->display_opening)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  if (klass->hide_tile_preview)
 | 
			
		||||
    {
 | 
			
		||||
      klass->hide_tile_preview (plugin);
 | 
			
		||||
      return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 | 
			
		||||
@@ -75,9 +75,4 @@ gboolean _meta_plugin_xevent_filter (MetaPlugin *plugin,
 | 
			
		||||
 | 
			
		||||
void     meta_plugin_manager_confirm_display_change (MetaPluginManager *mgr);
 | 
			
		||||
 | 
			
		||||
gboolean meta_plugin_manager_show_tile_preview (MetaPluginManager *mgr,
 | 
			
		||||
                                                MetaWindow        *window,
 | 
			
		||||
                                                MetaRectangle     *tile_rect,
 | 
			
		||||
                                                int                tile_monitor_number);
 | 
			
		||||
gboolean meta_plugin_manager_hide_tile_preview (MetaPluginManager *mgr);
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -30,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,6 +166,21 @@ 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)
 | 
			
		||||
@@ -102,7 +208,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
 | 
			
		||||
@@ -110,6 +224,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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -176,7 +310,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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -197,14 +331,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
 | 
			
		||||
 */
 | 
			
		||||
@@ -213,15 +349,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
 | 
			
		||||
 
 | 
			
		||||
@@ -33,7 +33,6 @@
 | 
			
		||||
#include "meta-texture-tower.h"
 | 
			
		||||
 | 
			
		||||
#include "meta-shaped-texture-private.h"
 | 
			
		||||
#include "meta-window-actor-private.h"
 | 
			
		||||
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
#include <cogl/cogl.h>
 | 
			
		||||
@@ -43,6 +42,8 @@
 | 
			
		||||
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,
 | 
			
		||||
@@ -72,6 +73,8 @@ struct _MetaShapedTexturePrivate
 | 
			
		||||
  CoglTexture *texture;
 | 
			
		||||
  CoglTexture *mask_texture;
 | 
			
		||||
 | 
			
		||||
  cairo_region_t *input_shape_region;
 | 
			
		||||
 | 
			
		||||
  /* The region containing only fully opaque pixels */
 | 
			
		||||
  cairo_region_t *opaque_region;
 | 
			
		||||
 | 
			
		||||
@@ -95,6 +98,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));
 | 
			
		||||
@@ -459,6 +463,71 @@ meta_shaped_texture_paint (ClutterActor *actor)
 | 
			
		||||
    cairo_region_destroy (blended_region);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_shaped_texture_pick (ClutterActor       *actor,
 | 
			
		||||
			  const ClutterColor *color)
 | 
			
		||||
{
 | 
			
		||||
  MetaShapedTexture *stex = (MetaShapedTexture *) actor;
 | 
			
		||||
  MetaShapedTexturePrivate *priv = stex->priv;
 | 
			
		||||
 | 
			
		||||
  if (!clutter_actor_should_pick_paint (actor) ||
 | 
			
		||||
      (priv->clip_region && cairo_region_is_empty (priv->clip_region)))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  /* If there is no region then use the regular pick */
 | 
			
		||||
  if (priv->input_shape_region == NULL)
 | 
			
		||||
    CLUTTER_ACTOR_CLASS (meta_shaped_texture_parent_class)->pick (actor, color);
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      int n_rects;
 | 
			
		||||
      float *rectangles;
 | 
			
		||||
      int i;
 | 
			
		||||
      CoglPipeline *pipeline;
 | 
			
		||||
      CoglContext *ctx;
 | 
			
		||||
      CoglFramebuffer *fb;
 | 
			
		||||
      CoglColor cogl_color;
 | 
			
		||||
 | 
			
		||||
      /* Note: We don't bother trying to intersect the pick and clip regions
 | 
			
		||||
       * since needing to copy the region, do the intersection, and probably
 | 
			
		||||
       * increase the number of rectangles seems more likely to have a negative
 | 
			
		||||
       * effect.
 | 
			
		||||
       *
 | 
			
		||||
       * NB: Most of the time when just using rectangles for picking then
 | 
			
		||||
       * picking shouldn't involve any rendering, and minimizing the number of
 | 
			
		||||
       * rectangles has more benefit than reducing the area of the pick
 | 
			
		||||
       * region.
 | 
			
		||||
       */
 | 
			
		||||
 | 
			
		||||
      n_rects = cairo_region_num_rectangles (priv->input_shape_region);
 | 
			
		||||
      rectangles = g_alloca (sizeof (float) * 4 * n_rects);
 | 
			
		||||
 | 
			
		||||
      for (i = 0; i < n_rects; i++)
 | 
			
		||||
        {
 | 
			
		||||
          cairo_rectangle_int_t rect;
 | 
			
		||||
          int pos = i * 4;
 | 
			
		||||
 | 
			
		||||
          cairo_region_get_rectangle (priv->input_shape_region, i, &rect);
 | 
			
		||||
 | 
			
		||||
          rectangles[pos] = rect.x;
 | 
			
		||||
          rectangles[pos + 1] = rect.y;
 | 
			
		||||
          rectangles[pos + 2] = rect.x + rect.width;
 | 
			
		||||
          rectangles[pos + 3] = rect.y + rect.height;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
 | 
			
		||||
      fb = cogl_get_draw_framebuffer ();
 | 
			
		||||
 | 
			
		||||
      cogl_color_init_from_4ub (&cogl_color, color->red, color->green, color->blue, color->alpha);
 | 
			
		||||
 | 
			
		||||
      pipeline = cogl_pipeline_new (ctx);
 | 
			
		||||
      cogl_pipeline_set_color (pipeline, &cogl_color);
 | 
			
		||||
 | 
			
		||||
      cogl_framebuffer_draw_rectangles (fb, pipeline,
 | 
			
		||||
                                        rectangles, n_rects);
 | 
			
		||||
      cogl_object_unref (pipeline);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_shaped_texture_get_preferred_width (ClutterActor *self,
 | 
			
		||||
                                         gfloat        for_height,
 | 
			
		||||
@@ -577,18 +646,8 @@ static cairo_region_t *
 | 
			
		||||
effective_unobscured_region (MetaShapedTexture *self)
 | 
			
		||||
{
 | 
			
		||||
  MetaShapedTexturePrivate *priv = self->priv;
 | 
			
		||||
  ClutterActor *parent = clutter_actor_get_parent (CLUTTER_ACTOR (self));
 | 
			
		||||
 | 
			
		||||
  if (clutter_actor_has_mapped_clones (CLUTTER_ACTOR (self)))
 | 
			
		||||
    return NULL;
 | 
			
		||||
 | 
			
		||||
  while (parent && !META_IS_WINDOW_ACTOR (parent))
 | 
			
		||||
    parent = clutter_actor_get_parent (parent);
 | 
			
		||||
 | 
			
		||||
  if (parent && clutter_actor_has_mapped_clones (parent))
 | 
			
		||||
    return NULL;
 | 
			
		||||
 | 
			
		||||
  return priv->unobscured_region;
 | 
			
		||||
  return clutter_actor_has_mapped_clones (CLUTTER_ACTOR (self)) ? NULL : priv->unobscured_region;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
@@ -705,6 +764,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,195 +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 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_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);
 | 
			
		||||
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
  surface_actor_class->process_damage = meta_surface_actor_wayland_process_damage;
 | 
			
		||||
  surface_actor_class->pre_paint = meta_surface_actor_wayland_pre_paint;
 | 
			
		||||
  surface_actor_class->is_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,66 +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);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif /* __META_SURFACE_ACTOR_WAYLAND_H__ */
 | 
			
		||||
@@ -1,459 +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"
 | 
			
		||||
 | 
			
		||||
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_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_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_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__ */
 | 
			
		||||
@@ -10,37 +10,26 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <config.h>
 | 
			
		||||
 | 
			
		||||
#include "meta-surface-actor.h"
 | 
			
		||||
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
#include <cogl/cogl-wayland-server.h>
 | 
			
		||||
#include <cogl/cogl-texture-pixmap-x11.h>
 | 
			
		||||
#include <meta/meta-shaped-texture.h>
 | 
			
		||||
#include "meta-surface-actor.h"
 | 
			
		||||
#include "meta-wayland-private.h"
 | 
			
		||||
#include "meta-cullable.h"
 | 
			
		||||
 | 
			
		||||
#include "meta-shaped-texture-private.h"
 | 
			
		||||
 | 
			
		||||
struct _MetaSurfaceActorPrivate
 | 
			
		||||
{
 | 
			
		||||
  MetaShapedTexture *texture;
 | 
			
		||||
 | 
			
		||||
  cairo_region_t *input_region;
 | 
			
		||||
 | 
			
		||||
  /* Freeze/thaw accounting */
 | 
			
		||||
  guint needs_damage_all : 1;
 | 
			
		||||
  guint frozen : 1;
 | 
			
		||||
  MetaWaylandBuffer *buffer;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
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];
 | 
			
		||||
G_DEFINE_TYPE_WITH_CODE (MetaSurfaceActor, meta_surface_actor, CLUTTER_TYPE_ACTOR,
 | 
			
		||||
                         G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor      *self,
 | 
			
		||||
@@ -50,84 +39,9 @@ meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor      *self,
 | 
			
		||||
  return meta_shaped_texture_get_unobscured_bounds (priv->texture, unobscured_bounds);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_surface_actor_pick (ClutterActor       *actor,
 | 
			
		||||
                         const ClutterColor *color)
 | 
			
		||||
{
 | 
			
		||||
  MetaSurfaceActor *self = META_SURFACE_ACTOR (actor);
 | 
			
		||||
  MetaSurfaceActorPrivate *priv = self->priv;
 | 
			
		||||
 | 
			
		||||
  if (!clutter_actor_should_pick_paint (actor))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  /* If there is no region then use the regular pick */
 | 
			
		||||
  if (priv->input_region == NULL)
 | 
			
		||||
    CLUTTER_ACTOR_CLASS (meta_surface_actor_parent_class)->pick (actor, color);
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      int n_rects;
 | 
			
		||||
      float *rectangles;
 | 
			
		||||
      int i;
 | 
			
		||||
      CoglPipeline *pipeline;
 | 
			
		||||
      CoglContext *ctx;
 | 
			
		||||
      CoglFramebuffer *fb;
 | 
			
		||||
      CoglColor cogl_color;
 | 
			
		||||
 | 
			
		||||
      n_rects = cairo_region_num_rectangles (priv->input_region);
 | 
			
		||||
      rectangles = g_alloca (sizeof (float) * 4 * n_rects);
 | 
			
		||||
 | 
			
		||||
      for (i = 0; i < n_rects; i++)
 | 
			
		||||
        {
 | 
			
		||||
          cairo_rectangle_int_t rect;
 | 
			
		||||
          int pos = i * 4;
 | 
			
		||||
 | 
			
		||||
          cairo_region_get_rectangle (priv->input_region, i, &rect);
 | 
			
		||||
 | 
			
		||||
          rectangles[pos + 0] = rect.x;
 | 
			
		||||
          rectangles[pos + 1] = rect.y;
 | 
			
		||||
          rectangles[pos + 2] = rect.x + rect.width;
 | 
			
		||||
          rectangles[pos + 3] = rect.y + rect.height;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
 | 
			
		||||
      fb = cogl_get_draw_framebuffer ();
 | 
			
		||||
 | 
			
		||||
      cogl_color_init_from_4ub (&cogl_color, color->red, color->green, color->blue, color->alpha);
 | 
			
		||||
 | 
			
		||||
      pipeline = cogl_pipeline_new (ctx);
 | 
			
		||||
      cogl_pipeline_set_color (pipeline, &cogl_color);
 | 
			
		||||
      cogl_framebuffer_draw_rectangles (fb, pipeline, rectangles, n_rects);
 | 
			
		||||
      cogl_object_unref (pipeline);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_surface_actor_dispose (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  MetaSurfaceActor *self = META_SURFACE_ACTOR (object);
 | 
			
		||||
  MetaSurfaceActorPrivate *priv = self->priv;
 | 
			
		||||
 | 
			
		||||
  g_clear_pointer (&priv->input_region, cairo_region_destroy);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (meta_surface_actor_parent_class)->dispose (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_surface_actor_class_init (MetaSurfaceActorClass *klass)
 | 
			
		||||
{
 | 
			
		||||
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
  ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
  object_class->dispose = meta_surface_actor_dispose;
 | 
			
		||||
  actor_class->pick = meta_surface_actor_pick;
 | 
			
		||||
 | 
			
		||||
  signals[REPAINT_SCHEDULED] = g_signal_new ("repaint-scheduled",
 | 
			
		||||
                                             G_TYPE_FROM_CLASS (object_class),
 | 
			
		||||
                                             G_SIGNAL_RUN_LAST,
 | 
			
		||||
                                             0,
 | 
			
		||||
                                             NULL, NULL, NULL,
 | 
			
		||||
                                             G_TYPE_NONE, 0);
 | 
			
		||||
 | 
			
		||||
  g_type_class_add_private (klass, sizeof (MetaSurfaceActorPrivate));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -178,14 +92,51 @@ 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)
 | 
			
		||||
static void
 | 
			
		||||
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);
 | 
			
		||||
  if (meta_is_wayland_compositor ())
 | 
			
		||||
    {
 | 
			
		||||
      struct wl_resource *resource = priv->buffer->resource;
 | 
			
		||||
      struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (resource);
 | 
			
		||||
 | 
			
		||||
      if (shm_buffer)
 | 
			
		||||
        {
 | 
			
		||||
          CoglTexture2D *texture = COGL_TEXTURE_2D (priv->buffer->texture);
 | 
			
		||||
          cogl_wayland_texture_set_region_from_shm_buffer (texture, x, y, width, height, shm_buffer, x, y, 0, NULL);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      CoglTexturePixmapX11 *texture = COGL_TEXTURE_PIXMAP_X11 (meta_shaped_texture_get_texture (priv->texture));
 | 
			
		||||
      cogl_texture_pixmap_x11_update_area (texture, x, y, width, height);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_surface_actor_damage_all (MetaSurfaceActor *self)
 | 
			
		||||
{
 | 
			
		||||
  MetaSurfaceActorPrivate *priv = self->priv;
 | 
			
		||||
  CoglTexture *texture = meta_shaped_texture_get_texture (priv->texture);
 | 
			
		||||
 | 
			
		||||
  update_area (self, 0, 0, cogl_texture_get_width (texture), cogl_texture_get_height (texture));
 | 
			
		||||
  return meta_shaped_texture_update_area (priv->texture, 0, 0, cogl_texture_get_width (texture), cogl_texture_get_height (texture));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_surface_actor_damage_area (MetaSurfaceActor *self,
 | 
			
		||||
                                int               x,
 | 
			
		||||
                                int               y,
 | 
			
		||||
                                int               width,
 | 
			
		||||
                                int               height)
 | 
			
		||||
{
 | 
			
		||||
  MetaSurfaceActorPrivate *priv = self->priv;
 | 
			
		||||
 | 
			
		||||
  update_area (self, x, y, width, height);
 | 
			
		||||
  return meta_shaped_texture_update_area (priv->texture, x, y, width, height);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
@@ -195,19 +146,33 @@ meta_surface_actor_is_obscured (MetaSurfaceActor *self)
 | 
			
		||||
  return meta_shaped_texture_is_obscured (priv->texture);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_surface_actor_attach_wayland_buffer (MetaSurfaceActor *self,
 | 
			
		||||
                                          MetaWaylandBuffer *buffer)
 | 
			
		||||
{
 | 
			
		||||
  MetaSurfaceActorPrivate *priv = self->priv;
 | 
			
		||||
  priv->buffer = buffer;
 | 
			
		||||
 | 
			
		||||
  if (buffer)
 | 
			
		||||
    meta_shaped_texture_set_texture (priv->texture, buffer->texture);
 | 
			
		||||
  else
 | 
			
		||||
    meta_shaped_texture_set_texture (priv->texture, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_surface_actor_set_texture (MetaSurfaceActor *self,
 | 
			
		||||
                                CoglTexture      *texture)
 | 
			
		||||
{
 | 
			
		||||
  MetaSurfaceActorPrivate *priv = self->priv;
 | 
			
		||||
  meta_shaped_texture_set_texture (priv->texture, texture);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_surface_actor_set_input_region (MetaSurfaceActor *self,
 | 
			
		||||
                                     cairo_region_t   *region)
 | 
			
		||||
{
 | 
			
		||||
  MetaSurfaceActorPrivate *priv = self->priv;
 | 
			
		||||
 | 
			
		||||
  if (priv->input_region)
 | 
			
		||||
    cairo_region_destroy (priv->input_region);
 | 
			
		||||
 | 
			
		||||
  if (region)
 | 
			
		||||
    priv->input_region = cairo_region_reference (region);
 | 
			
		||||
  else
 | 
			
		||||
    priv->input_region = NULL;
 | 
			
		||||
  meta_shaped_texture_set_input_shape_region (priv->texture, region);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -218,121 +183,8 @@ meta_surface_actor_set_opaque_region (MetaSurfaceActor *self,
 | 
			
		||||
  meta_shaped_texture_set_opaque_region (priv->texture, region);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
is_frozen (MetaSurfaceActor *self)
 | 
			
		||||
MetaSurfaceActor *
 | 
			
		||||
meta_surface_actor_new (void)
 | 
			
		||||
{
 | 
			
		||||
  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);
 | 
			
		||||
  return g_object_new (META_TYPE_SURFACE_ACTOR, NULL);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@
 | 
			
		||||
#include <config.h>
 | 
			
		||||
 | 
			
		||||
#include <meta/meta-shaped-texture.h>
 | 
			
		||||
#include <meta/window.h>
 | 
			
		||||
#include "meta-wayland-types.h"
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
@@ -25,18 +25,6 @@ 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
 | 
			
		||||
@@ -48,38 +36,33 @@ struct _MetaSurfaceActor
 | 
			
		||||
 | 
			
		||||
GType meta_surface_actor_get_type (void);
 | 
			
		||||
 | 
			
		||||
MetaSurfaceActor *meta_surface_actor_new (void);
 | 
			
		||||
 | 
			
		||||
cairo_surface_t *meta_surface_actor_get_image (MetaSurfaceActor      *self,
 | 
			
		||||
                                               cairo_rectangle_int_t *clip);
 | 
			
		||||
 | 
			
		||||
MetaShapedTexture *meta_surface_actor_get_texture (MetaSurfaceActor *self);
 | 
			
		||||
MetaWindow        *meta_surface_actor_get_window  (MetaSurfaceActor *self);
 | 
			
		||||
 | 
			
		||||
gboolean meta_surface_actor_damage_all  (MetaSurfaceActor *self);
 | 
			
		||||
gboolean meta_surface_actor_damage_area (MetaSurfaceActor *self,
 | 
			
		||||
                                         int               x,
 | 
			
		||||
                                         int               y,
 | 
			
		||||
                                         int               width,
 | 
			
		||||
                                         int               height);
 | 
			
		||||
 | 
			
		||||
gboolean meta_surface_actor_is_obscured (MetaSurfaceActor *self);
 | 
			
		||||
gboolean meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor      *self,
 | 
			
		||||
                                                   cairo_rectangle_int_t *unobscured_bounds);
 | 
			
		||||
 | 
			
		||||
void meta_surface_actor_set_texture (MetaSurfaceActor *self,
 | 
			
		||||
                                     CoglTexture      *texture);
 | 
			
		||||
void meta_surface_actor_attach_wayland_buffer (MetaSurfaceActor  *self,
 | 
			
		||||
                                               MetaWaylandBuffer *buffer);
 | 
			
		||||
void meta_surface_actor_set_input_region (MetaSurfaceActor *self,
 | 
			
		||||
                                          cairo_region_t   *region);
 | 
			
		||||
void meta_surface_actor_set_opaque_region (MetaSurfaceActor *self,
 | 
			
		||||
                                           cairo_region_t   *region);
 | 
			
		||||
 | 
			
		||||
void meta_surface_actor_update_area (MetaSurfaceActor *actor,
 | 
			
		||||
                                     int x, int y, int width, int height);
 | 
			
		||||
 | 
			
		||||
void meta_surface_actor_process_damage (MetaSurfaceActor *actor,
 | 
			
		||||
                                        int x, int y, int width, int height);
 | 
			
		||||
void meta_surface_actor_pre_paint (MetaSurfaceActor *actor);
 | 
			
		||||
gboolean meta_surface_actor_is_argb32 (MetaSurfaceActor *actor);
 | 
			
		||||
gboolean meta_surface_actor_is_visible (MetaSurfaceActor *actor);
 | 
			
		||||
 | 
			
		||||
void meta_surface_actor_set_frozen (MetaSurfaceActor *actor,
 | 
			
		||||
                                    gboolean          frozen);
 | 
			
		||||
 | 
			
		||||
gboolean meta_surface_actor_should_unredirect (MetaSurfaceActor *actor);
 | 
			
		||||
void meta_surface_actor_set_unredirected (MetaSurfaceActor *actor,
 | 
			
		||||
                                          gboolean          unredirected);
 | 
			
		||||
gboolean meta_surface_actor_is_unredirected (MetaSurfaceActor *actor);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif /* META_SURFACE_ACTOR_PRIVATE_H */
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,9 @@
 | 
			
		||||
 | 
			
		||||
#include <config.h>
 | 
			
		||||
 | 
			
		||||
#include <wayland-server.h>
 | 
			
		||||
#include <meta-wayland-private.h>
 | 
			
		||||
 | 
			
		||||
#include <X11/extensions/Xdamage.h>
 | 
			
		||||
#include <meta/compositor-mutter.h>
 | 
			
		||||
#include "meta-surface-actor.h"
 | 
			
		||||
@@ -60,6 +63,5 @@ void meta_window_actor_effect_completed (MetaWindowActor *actor,
 | 
			
		||||
                                         gulong           event);
 | 
			
		||||
 | 
			
		||||
MetaSurfaceActor *meta_window_actor_get_surface (MetaWindowActor *self);
 | 
			
		||||
void meta_window_actor_update_surface (MetaWindowActor *self);
 | 
			
		||||
 | 
			
		||||
#endif /* META_WINDOW_ACTOR_PRIVATE_H */
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -164,6 +164,19 @@ meta_window_group_paint (ClutterActor *actor)
 | 
			
		||||
  paint_y_offset = paint_y_origin - actor_y_origin;
 | 
			
		||||
  cairo_region_translate (clip_region, -paint_x_offset, -paint_y_offset);
 | 
			
		||||
 | 
			
		||||
  if (!meta_is_wayland_compositor ())
 | 
			
		||||
    {
 | 
			
		||||
      MetaCompScreen *info = meta_screen_get_compositor_data (window_group->screen);
 | 
			
		||||
      if (info->unredirected_window != NULL)
 | 
			
		||||
        {
 | 
			
		||||
          cairo_rectangle_int_t unredirected_rect;
 | 
			
		||||
 | 
			
		||||
          meta_window_get_frame_rect (info->unredirected_window, (MetaRectangle *)&unredirected_rect);
 | 
			
		||||
          cairo_region_subtract_rectangle (unobscured_region, &unredirected_rect);
 | 
			
		||||
          cairo_region_subtract_rectangle (clip_region, &unredirected_rect);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_cullable_cull_out (META_CULLABLE (window_group), unobscured_region, clip_region);
 | 
			
		||||
 | 
			
		||||
  cairo_region_destroy (unobscured_region);
 | 
			
		||||
 
 | 
			
		||||
@@ -39,7 +39,6 @@
 | 
			
		||||
#define SWITCH_TIMEOUT    500
 | 
			
		||||
 | 
			
		||||
#define ACTOR_DATA_KEY "MCCP-Default-actor-data"
 | 
			
		||||
#define SCREEN_TILE_PREVIEW_DATA_KEY "MCCP-Default-screen-tile-preview-data"
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_DEFAULT_PLUGIN            (meta_default_plugin_get_type ())
 | 
			
		||||
#define META_DEFAULT_PLUGIN(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEFAULT_PLUGIN, MetaDefaultPlugin))
 | 
			
		||||
@@ -68,7 +67,6 @@ struct _MetaDefaultPluginClass
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static GQuark actor_data_quark = 0;
 | 
			
		||||
static GQuark screen_tile_preview_data_quark = 0;
 | 
			
		||||
 | 
			
		||||
static void start      (MetaPlugin      *plugin);
 | 
			
		||||
static void minimize   (MetaPlugin      *plugin,
 | 
			
		||||
@@ -99,12 +97,6 @@ static void kill_window_effects   (MetaPlugin      *plugin,
 | 
			
		||||
                                   MetaWindowActor *actor);
 | 
			
		||||
static void kill_switch_workspace (MetaPlugin      *plugin);
 | 
			
		||||
 | 
			
		||||
static void show_tile_preview (MetaPlugin      *plugin,
 | 
			
		||||
                               MetaWindow      *window,
 | 
			
		||||
                               MetaRectangle   *tile_rect,
 | 
			
		||||
                               int              tile_monitor_number);
 | 
			
		||||
static void hide_tile_preview (MetaPlugin      *plugin);
 | 
			
		||||
 | 
			
		||||
static void confirm_display_change (MetaPlugin *plugin);
 | 
			
		||||
 | 
			
		||||
static const MetaPluginInfo * plugin_info (MetaPlugin *plugin);
 | 
			
		||||
@@ -151,15 +143,6 @@ typedef struct
 | 
			
		||||
} EffectCompleteData;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef struct _ScreenTilePreview
 | 
			
		||||
{
 | 
			
		||||
  ClutterActor   *actor;
 | 
			
		||||
 | 
			
		||||
  GdkRGBA        *preview_color;
 | 
			
		||||
 | 
			
		||||
  MetaRectangle   tile_rect;
 | 
			
		||||
} ScreenTilePreview;
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_default_plugin_dispose (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
@@ -220,8 +203,6 @@ meta_default_plugin_class_init (MetaDefaultPluginClass *klass)
 | 
			
		||||
  plugin_class->unmaximize       = unmaximize;
 | 
			
		||||
  plugin_class->destroy          = destroy;
 | 
			
		||||
  plugin_class->switch_workspace = switch_workspace;
 | 
			
		||||
  plugin_class->show_tile_preview = show_tile_preview;
 | 
			
		||||
  plugin_class->hide_tile_preview = hide_tile_preview;
 | 
			
		||||
  plugin_class->plugin_info      = plugin_info;
 | 
			
		||||
  plugin_class->kill_window_effects   = kill_window_effects;
 | 
			
		||||
  plugin_class->kill_switch_workspace = kill_switch_workspace;
 | 
			
		||||
@@ -768,82 +749,6 @@ destroy (MetaPlugin *plugin, MetaWindowActor *window_actor)
 | 
			
		||||
    meta_plugin_destroy_completed (plugin, window_actor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Tile preview private data accessor
 | 
			
		||||
 */
 | 
			
		||||
static void
 | 
			
		||||
free_screen_tile_preview (gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  ScreenTilePreview *preview = data;
 | 
			
		||||
 | 
			
		||||
  if (G_LIKELY (preview != NULL)) {
 | 
			
		||||
    clutter_actor_destroy (preview->actor);
 | 
			
		||||
    g_slice_free (ScreenTilePreview, preview);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static ScreenTilePreview *
 | 
			
		||||
get_screen_tile_preview (MetaScreen *screen)
 | 
			
		||||
{
 | 
			
		||||
  ScreenTilePreview *preview = g_object_get_qdata (G_OBJECT (screen), screen_tile_preview_data_quark);
 | 
			
		||||
 | 
			
		||||
  if (G_UNLIKELY (screen_tile_preview_data_quark == 0))
 | 
			
		||||
    screen_tile_preview_data_quark = g_quark_from_static_string (SCREEN_TILE_PREVIEW_DATA_KEY);
 | 
			
		||||
 | 
			
		||||
  if (G_UNLIKELY (!preview))
 | 
			
		||||
    {
 | 
			
		||||
      preview = g_slice_new0 (ScreenTilePreview);
 | 
			
		||||
 | 
			
		||||
      preview->actor = clutter_actor_new ();
 | 
			
		||||
      clutter_actor_set_background_color (preview->actor, CLUTTER_COLOR_Blue);
 | 
			
		||||
      clutter_actor_set_opacity (preview->actor, 100);
 | 
			
		||||
 | 
			
		||||
      clutter_actor_add_child (meta_get_window_group_for_screen (screen), preview->actor);
 | 
			
		||||
      g_object_set_qdata_full (G_OBJECT (screen),
 | 
			
		||||
                               screen_tile_preview_data_quark, preview,
 | 
			
		||||
                               free_screen_tile_preview);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return preview;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
show_tile_preview (MetaPlugin    *plugin,
 | 
			
		||||
                   MetaWindow    *window,
 | 
			
		||||
                   MetaRectangle *tile_rect,
 | 
			
		||||
                   int            tile_monitor_number)
 | 
			
		||||
{
 | 
			
		||||
  MetaScreen *screen = meta_plugin_get_screen (plugin);
 | 
			
		||||
  ScreenTilePreview *preview = get_screen_tile_preview (screen);
 | 
			
		||||
  ClutterActor *window_actor;
 | 
			
		||||
 | 
			
		||||
  if (CLUTTER_ACTOR_IS_VISIBLE (preview->actor)
 | 
			
		||||
      && preview->tile_rect.x == tile_rect->x
 | 
			
		||||
      && preview->tile_rect.y == tile_rect->y
 | 
			
		||||
      && preview->tile_rect.width == tile_rect->width
 | 
			
		||||
      && preview->tile_rect.height == tile_rect->height)
 | 
			
		||||
    return; /* nothing to do */
 | 
			
		||||
 | 
			
		||||
  clutter_actor_set_position (preview->actor, tile_rect->x, tile_rect->y);
 | 
			
		||||
  clutter_actor_set_size (preview->actor, tile_rect->width, tile_rect->height);
 | 
			
		||||
 | 
			
		||||
  clutter_actor_show (preview->actor);
 | 
			
		||||
 | 
			
		||||
  window_actor = CLUTTER_ACTOR (meta_window_get_compositor_private (window));
 | 
			
		||||
  clutter_actor_lower (preview->actor, window_actor);
 | 
			
		||||
 | 
			
		||||
  preview->tile_rect = *tile_rect;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
hide_tile_preview (MetaPlugin *plugin)
 | 
			
		||||
{
 | 
			
		||||
  MetaScreen *screen = meta_plugin_get_screen (plugin);
 | 
			
		||||
  ScreenTilePreview *preview = get_screen_tile_preview (screen);
 | 
			
		||||
 | 
			
		||||
  clutter_actor_hide (preview->actor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
kill_switch_workspace (MetaPlugin     *plugin)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										110
									
								
								src/core/bell.c
									
									
									
									
									
								
							
							
						
						
									
										110
									
								
								src/core/bell.c
									
									
									
									
									
								
							@@ -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
 | 
			
		||||
@@ -74,8 +156,34 @@ static void
 | 
			
		||||
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;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
@@ -425,9 +425,8 @@ setup_constraint_info (ConstraintInfo      *info,
 | 
			
		||||
   * the monitor.
 | 
			
		||||
   */
 | 
			
		||||
  if (meta_prefs_get_force_fullscreen() &&
 | 
			
		||||
      window->client_type != META_WINDOW_CLIENT_TYPE_WAYLAND &&
 | 
			
		||||
      !window->hide_titlebar_when_maximized &&
 | 
			
		||||
      (window->decorated || !meta_window_is_client_decorated (window)) &&
 | 
			
		||||
      window->decorated &&
 | 
			
		||||
      meta_rectangle_equal (new, &monitor_info->rect) &&
 | 
			
		||||
      window->has_fullscreen_func &&
 | 
			
		||||
      !window->fullscreen)
 | 
			
		||||
@@ -492,17 +491,12 @@ place_window_if_needed(MetaWindow     *window,
 | 
			
		||||
      !window->minimized &&
 | 
			
		||||
      !window->fullscreen)
 | 
			
		||||
    {
 | 
			
		||||
      MetaRectangle orig_rect;
 | 
			
		||||
      MetaRectangle placed_rect;
 | 
			
		||||
      MetaWorkspace *cur_workspace;
 | 
			
		||||
      const MetaMonitorInfo *monitor_info;
 | 
			
		||||
 | 
			
		||||
      meta_window_get_frame_rect (window, &placed_rect);
 | 
			
		||||
 | 
			
		||||
      orig_rect = info->orig;
 | 
			
		||||
      extend_by_frame (window, &orig_rect);
 | 
			
		||||
 | 
			
		||||
      meta_window_place (window, orig_rect.x, orig_rect.y,
 | 
			
		||||
      meta_window_place (window, info->orig.x, info->orig.y,
 | 
			
		||||
                         &placed_rect.x, &placed_rect.y);
 | 
			
		||||
      did_placement = TRUE;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,16 @@
 | 
			
		||||
#include "window-private.h"
 | 
			
		||||
#include "frame.h"
 | 
			
		||||
 | 
			
		||||
typedef enum
 | 
			
		||||
{
 | 
			
		||||
  META_IS_CONFIGURE_REQUEST = 1 << 0,
 | 
			
		||||
  META_DO_GRAVITY_ADJUST    = 1 << 1,
 | 
			
		||||
  META_IS_USER_ACTION       = 1 << 2,
 | 
			
		||||
  META_IS_MOVE_ACTION       = 1 << 3,
 | 
			
		||||
  META_IS_RESIZE_ACTION     = 1 << 4,
 | 
			
		||||
  META_IS_WAYLAND_RESIZE    = 1 << 5
 | 
			
		||||
} MetaMoveResizeFlags;
 | 
			
		||||
 | 
			
		||||
void meta_window_constrain (MetaWindow          *window,
 | 
			
		||||
                            MetaMoveResizeFlags  flags,
 | 
			
		||||
                            int                  resize_gravity,
 | 
			
		||||
 
 | 
			
		||||
@@ -274,7 +274,7 @@ meta_core_lower_beneath_grab_window (Display *xdisplay,
 | 
			
		||||
  MetaStackWindow stack_sibling;
 | 
			
		||||
 | 
			
		||||
  display = meta_display_for_x_display (xdisplay);
 | 
			
		||||
  screen = display->screen;
 | 
			
		||||
  screen = meta_display_screen_for_xwindow (display, xwindow);
 | 
			
		||||
  grab_window = display->grab_window;
 | 
			
		||||
 | 
			
		||||
  if (grab_window == NULL)
 | 
			
		||||
@@ -328,7 +328,8 @@ meta_core_maximize (Display *xdisplay,
 | 
			
		||||
  if (meta_prefs_get_raise_on_click ())
 | 
			
		||||
    meta_window_raise (window);
 | 
			
		||||
 | 
			
		||||
  meta_window_maximize (window, META_MAXIMIZE_BOTH);
 | 
			
		||||
  meta_window_maximize (window, 
 | 
			
		||||
                        META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -341,9 +342,11 @@ meta_core_toggle_maximize_vertically (Display *xdisplay,
 | 
			
		||||
    meta_window_raise (window);
 | 
			
		||||
 | 
			
		||||
  if (META_WINDOW_MAXIMIZED_VERTICALLY (window))
 | 
			
		||||
    meta_window_unmaximize (window, META_MAXIMIZE_VERTICAL);
 | 
			
		||||
    meta_window_unmaximize (window, 
 | 
			
		||||
                            META_MAXIMIZE_VERTICAL);
 | 
			
		||||
  else
 | 
			
		||||
    meta_window_maximize (window, META_MAXIMIZE_VERTICAL);
 | 
			
		||||
    meta_window_maximize (window,
 | 
			
		||||
    			    META_MAXIMIZE_VERTICAL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -356,9 +359,11 @@ meta_core_toggle_maximize_horizontally (Display *xdisplay,
 | 
			
		||||
    meta_window_raise (window);
 | 
			
		||||
 | 
			
		||||
  if (META_WINDOW_MAXIMIZED_HORIZONTALLY (window))
 | 
			
		||||
    meta_window_unmaximize (window, META_MAXIMIZE_HORIZONTAL);
 | 
			
		||||
    meta_window_unmaximize (window, 
 | 
			
		||||
                            META_MAXIMIZE_HORIZONTAL);
 | 
			
		||||
  else
 | 
			
		||||
    meta_window_maximize (window, META_MAXIMIZE_HORIZONTAL);
 | 
			
		||||
    meta_window_maximize (window,
 | 
			
		||||
    			    META_MAXIMIZE_HORIZONTAL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -371,9 +376,11 @@ meta_core_toggle_maximize (Display *xdisplay,
 | 
			
		||||
    meta_window_raise (window);
 | 
			
		||||
 | 
			
		||||
  if (META_WINDOW_MAXIMIZED (window))
 | 
			
		||||
    meta_window_unmaximize (window, META_MAXIMIZE_BOTH);
 | 
			
		||||
    meta_window_unmaximize (window, 
 | 
			
		||||
                            META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
 | 
			
		||||
  else
 | 
			
		||||
    meta_window_maximize (window, META_MAXIMIZE_BOTH);
 | 
			
		||||
    meta_window_maximize (window,
 | 
			
		||||
                          META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -385,7 +392,8 @@ meta_core_unmaximize (Display *xdisplay,
 | 
			
		||||
  if (meta_prefs_get_raise_on_click ())
 | 
			
		||||
    meta_window_raise (window);
 | 
			
		||||
 | 
			
		||||
  meta_window_unmaximize (window, META_MAXIMIZE_BOTH);
 | 
			
		||||
  meta_window_unmaximize (window,
 | 
			
		||||
                          META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -603,10 +611,13 @@ meta_core_get_workspace_name_with_index (Display *xdisplay,
 | 
			
		||||
                                         int      index)
 | 
			
		||||
{
 | 
			
		||||
  MetaDisplay *display;
 | 
			
		||||
  MetaScreen *screen;
 | 
			
		||||
  MetaWorkspace *workspace;
 | 
			
		||||
 | 
			
		||||
  display = meta_display_for_x_display (xdisplay);
 | 
			
		||||
  workspace = meta_screen_get_workspace_by_index (display->screen, index);
 | 
			
		||||
  screen = meta_display_screen_for_root (display, xroot);
 | 
			
		||||
  g_assert (screen != NULL);
 | 
			
		||||
  workspace = meta_screen_get_workspace_by_index (screen, index);
 | 
			
		||||
  return workspace ? meta_workspace_get_name (workspace) : NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -627,7 +638,7 @@ meta_core_begin_grab_op (Display    *xdisplay,
 | 
			
		||||
  MetaScreen *screen;
 | 
			
		||||
  
 | 
			
		||||
  display = meta_display_for_x_display (xdisplay);
 | 
			
		||||
  screen = display->screen;
 | 
			
		||||
  screen = meta_display_screen_for_xwindow (display, frame_xwindow);
 | 
			
		||||
 | 
			
		||||
  g_assert (screen != NULL);
 | 
			
		||||
  
 | 
			
		||||
@@ -667,6 +678,10 @@ meta_core_get_grab_frame (Display *xdisplay)
 | 
			
		||||
  display = meta_display_for_x_display (xdisplay);
 | 
			
		||||
 | 
			
		||||
  g_assert (display != NULL);
 | 
			
		||||
  g_assert (display->grab_op == META_GRAB_OP_NONE || 
 | 
			
		||||
            display->grab_screen != NULL);
 | 
			
		||||
  g_assert (display->grab_op == META_GRAB_OP_NONE ||
 | 
			
		||||
            display->grab_screen->display->xdisplay == xdisplay);
 | 
			
		||||
  
 | 
			
		||||
  if (display->grab_op != META_GRAB_OP_NONE &&
 | 
			
		||||
      display->grab_window &&
 | 
			
		||||
@@ -711,6 +726,16 @@ meta_core_set_screen_cursor (Display *xdisplay,
 | 
			
		||||
  meta_frame_set_screen_cursor (window->frame, cursor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_core_increment_event_serial (Display *xdisplay)
 | 
			
		||||
{
 | 
			
		||||
  MetaDisplay *display;
 | 
			
		||||
  
 | 
			
		||||
  display = meta_display_for_x_display (xdisplay);
 | 
			
		||||
 | 
			
		||||
  meta_display_increment_event_serial (display);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_invalidate_default_icons (void)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -193,6 +193,12 @@ void       meta_core_set_screen_cursor (Display *xdisplay,
 | 
			
		||||
                                        Window   frame_on_screen,
 | 
			
		||||
                                        MetaCursor cursor);
 | 
			
		||||
 | 
			
		||||
/* Used because we ignore EnterNotify when a window is unmapped that
 | 
			
		||||
 * really shouldn't cause focus changes, by comparing the event serial
 | 
			
		||||
 * of the EnterNotify and the UnmapNotify.
 | 
			
		||||
 */
 | 
			
		||||
void meta_core_increment_event_serial (Display *display);
 | 
			
		||||
 | 
			
		||||
void meta_invalidate_default_icons (void);
 | 
			
		||||
 | 
			
		||||
void meta_core_add_old_event_mask (Display     *xdisplay,
 | 
			
		||||
 
 | 
			
		||||
@@ -37,7 +37,7 @@
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
#include "wayland/meta-wayland-surface.h"
 | 
			
		||||
#include "meta-wayland-surface.h"
 | 
			
		||||
 | 
			
		||||
static void meta_window_present_delete_dialog (MetaWindow *window,
 | 
			
		||||
                                               guint32     timestamp);
 | 
			
		||||
@@ -143,7 +143,31 @@ void
 | 
			
		||||
meta_window_delete (MetaWindow  *window,
 | 
			
		||||
                    guint32      timestamp)
 | 
			
		||||
{
 | 
			
		||||
  META_WINDOW_GET_CLASS (window)->delete (window, timestamp);
 | 
			
		||||
  if (window->client_type == META_WINDOW_CLIENT_TYPE_X11)
 | 
			
		||||
    {
 | 
			
		||||
      meta_error_trap_push (window->display);
 | 
			
		||||
      if (window->delete_window)
 | 
			
		||||
        {
 | 
			
		||||
          meta_topic (META_DEBUG_WINDOW_OPS,
 | 
			
		||||
                      "Deleting %s with delete_window request\n",
 | 
			
		||||
                      window->desc);
 | 
			
		||||
          meta_window_send_icccm_message (window,
 | 
			
		||||
                                          window->display->atom_WM_DELETE_WINDOW,
 | 
			
		||||
                                          timestamp);
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          meta_topic (META_DEBUG_WINDOW_OPS,
 | 
			
		||||
                      "Deleting %s with explicit kill\n",
 | 
			
		||||
                      window->desc);
 | 
			
		||||
          XKillClient (window->display->xdisplay, window->xwindow);
 | 
			
		||||
        }
 | 
			
		||||
      meta_error_trap_pop (window->display);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      meta_wayland_surface_delete (window->surface);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_window_check_alive (window, timestamp);
 | 
			
		||||
 | 
			
		||||
@@ -176,10 +200,33 @@ meta_window_delete (MetaWindow  *window,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_window_kill (MetaWindow *window)
 | 
			
		||||
{
 | 
			
		||||
  META_WINDOW_GET_CLASS (window)->kill (window);
 | 
			
		||||
  meta_topic (META_DEBUG_WINDOW_OPS,
 | 
			
		||||
              "Killing %s brutally\n",
 | 
			
		||||
              window->desc);
 | 
			
		||||
 | 
			
		||||
  if (!meta_window_is_remote (window) &&
 | 
			
		||||
      window->net_wm_pid > 0)
 | 
			
		||||
    {
 | 
			
		||||
      meta_topic (META_DEBUG_WINDOW_OPS,
 | 
			
		||||
                  "Killing %s with kill()\n",
 | 
			
		||||
                  window->desc);
 | 
			
		||||
 | 
			
		||||
      if (kill (window->net_wm_pid, 9) < 0)
 | 
			
		||||
        meta_topic (META_DEBUG_WINDOW_OPS,
 | 
			
		||||
                    "Failed to signal %s: %s\n",
 | 
			
		||||
                    window->desc, strerror (errno));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_topic (META_DEBUG_WINDOW_OPS,
 | 
			
		||||
              "Disconnecting %s with XKillClient()\n",
 | 
			
		||||
              window->desc);
 | 
			
		||||
  meta_error_trap_push (window->display);
 | 
			
		||||
  XKillClient (window->display->xdisplay, window->xwindow);
 | 
			
		||||
  meta_error_trap_pop (window->display);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -214,7 +261,8 @@ meta_window_present_delete_dialog (MetaWindow *window, guint32 timestamp)
 | 
			
		||||
        {
 | 
			
		||||
          MetaWindow *w = tmp->data;
 | 
			
		||||
 | 
			
		||||
          if (w->transient_for == window && w->res_class &&
 | 
			
		||||
          if (w->xtransient_for == window->xwindow &&
 | 
			
		||||
              w->res_class &&
 | 
			
		||||
              g_ascii_strcasecmp (w->res_class, "mutter-dialog") == 0)
 | 
			
		||||
            {
 | 
			
		||||
              meta_window_activate (w, timestamp);
 | 
			
		||||
 
 | 
			
		||||
@@ -84,6 +84,14 @@ typedef enum {
 | 
			
		||||
  META_TILE_MAXIMIZED
 | 
			
		||||
} MetaTileMode;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
  META_FOCUS_NONE = 0,
 | 
			
		||||
  META_FOCUS_X_CLIENT = 1,
 | 
			
		||||
  META_FOCUS_WAYLAND_CLIENT = 2,
 | 
			
		||||
  META_FOCUS_NO_FOCUS_WINDOW = 3,
 | 
			
		||||
  META_FOCUS_STAGE = 4
 | 
			
		||||
} MetaFocusType;
 | 
			
		||||
 | 
			
		||||
struct _MetaDisplay
 | 
			
		||||
{
 | 
			
		||||
  GObject parent_instance;
 | 
			
		||||
@@ -92,7 +100,6 @@ struct _MetaDisplay
 | 
			
		||||
  Display *xdisplay;
 | 
			
		||||
 | 
			
		||||
  int clutter_event_filter;
 | 
			
		||||
  GSource *x11_event_source;
 | 
			
		||||
 | 
			
		||||
  Window leader_window;
 | 
			
		||||
  Window timestamp_pinging_window;
 | 
			
		||||
@@ -118,6 +125,7 @@ struct _MetaDisplay
 | 
			
		||||
   * like the no_focus_window or the stage X window. */
 | 
			
		||||
  Window focus_xwindow;
 | 
			
		||||
  gulong focus_serial;
 | 
			
		||||
  MetaFocusType focus_type;
 | 
			
		||||
 | 
			
		||||
  /* last timestamp passed to XSetInputFocus */
 | 
			
		||||
  guint32 last_focus_time;
 | 
			
		||||
@@ -146,12 +154,18 @@ struct _MetaDisplay
 | 
			
		||||
   * multiple events with the same serial.
 | 
			
		||||
   */
 | 
			
		||||
  guint focused_by_us : 1;
 | 
			
		||||
 | 
			
		||||
  guint static_gravity_works : 1;
 | 
			
		||||
  
 | 
			
		||||
  /*< private-ish >*/
 | 
			
		||||
  MetaScreen *screen;
 | 
			
		||||
  guint error_trap_synced_at_last_pop : 1;
 | 
			
		||||
  GSList *screens;
 | 
			
		||||
  MetaScreen *active_screen;
 | 
			
		||||
  GHashTable *xids;
 | 
			
		||||
  GHashTable *wayland_windows;
 | 
			
		||||
 | 
			
		||||
  int error_traps;
 | 
			
		||||
  int (* error_trap_handler) (Display     *display,
 | 
			
		||||
                              XErrorEvent *error);  
 | 
			
		||||
  int server_grab_count;
 | 
			
		||||
 | 
			
		||||
  /* serials of leave/unmap events that may
 | 
			
		||||
@@ -187,6 +201,7 @@ struct _MetaDisplay
 | 
			
		||||
  
 | 
			
		||||
  /* current window operation */
 | 
			
		||||
  MetaGrabOp  grab_op;
 | 
			
		||||
  MetaScreen *grab_screen;
 | 
			
		||||
  MetaWindow *grab_window;
 | 
			
		||||
  Window      grab_xwindow;
 | 
			
		||||
  int         grab_button;
 | 
			
		||||
@@ -209,6 +224,7 @@ struct _MetaDisplay
 | 
			
		||||
  gboolean    grab_threshold_movement_reached; /* raise_on_click == FALSE.    */
 | 
			
		||||
  MetaResizePopup *grab_resize_popup;
 | 
			
		||||
  GTimeVal    grab_last_moveresize_time;
 | 
			
		||||
  guint32     grab_motion_notify_time;
 | 
			
		||||
  GList*      grab_old_window_stacking;
 | 
			
		||||
  MetaEdgeResistanceData *grab_edge_resistance_data;
 | 
			
		||||
  unsigned int grab_last_user_action_was_snap;
 | 
			
		||||
@@ -226,8 +242,8 @@ struct _MetaDisplay
 | 
			
		||||
  int	      grab_resize_timeout_id;
 | 
			
		||||
 | 
			
		||||
  /* Keybindings stuff */
 | 
			
		||||
  GHashTable     *key_bindings;
 | 
			
		||||
  GHashTable     *key_bindings_index;
 | 
			
		||||
  MetaKeyBinding *key_bindings;
 | 
			
		||||
  int             n_key_bindings;
 | 
			
		||||
  int             min_keycode;
 | 
			
		||||
  int             max_keycode;
 | 
			
		||||
  KeySym *keymap;
 | 
			
		||||
@@ -254,8 +270,6 @@ struct _MetaDisplay
 | 
			
		||||
  /* Closing down the display */
 | 
			
		||||
  int closing;
 | 
			
		||||
 | 
			
		||||
  GSList *error_traps;
 | 
			
		||||
 | 
			
		||||
  /* Managed by group.c */
 | 
			
		||||
  GHashTable *groups_by_leader;
 | 
			
		||||
 | 
			
		||||
@@ -349,6 +363,10 @@ struct _MetaDisplayClass
 | 
			
		||||
gboolean      meta_display_open                (void);
 | 
			
		||||
void          meta_display_close               (MetaDisplay *display,
 | 
			
		||||
                                                guint32      timestamp);
 | 
			
		||||
MetaScreen*   meta_display_screen_for_x_screen (MetaDisplay *display,
 | 
			
		||||
                                                Screen      *screen);
 | 
			
		||||
MetaScreen*   meta_display_screen_for_xwindow  (MetaDisplay *display,
 | 
			
		||||
                                                Window       xindow);
 | 
			
		||||
void          meta_display_grab                (MetaDisplay *display);
 | 
			
		||||
void          meta_display_ungrab              (MetaDisplay *display);
 | 
			
		||||
 | 
			
		||||
@@ -448,9 +466,6 @@ int meta_resize_gravity_from_grab_op (MetaGrabOp op);
 | 
			
		||||
gboolean meta_grab_op_is_moving   (MetaGrabOp op);
 | 
			
		||||
gboolean meta_grab_op_is_resizing (MetaGrabOp op);
 | 
			
		||||
gboolean meta_grab_op_is_mouse    (MetaGrabOp op);
 | 
			
		||||
gboolean meta_grab_op_is_clicking (MetaGrabOp op);
 | 
			
		||||
gboolean meta_grab_op_is_wayland  (MetaGrabOp op);
 | 
			
		||||
gboolean meta_grab_op_is_keyboard (MetaGrabOp op);
 | 
			
		||||
 | 
			
		||||
void meta_display_devirtualize_modifiers (MetaDisplay        *display,
 | 
			
		||||
                                          MetaVirtualModifier modifiers,
 | 
			
		||||
@@ -478,21 +493,10 @@ gboolean meta_display_process_barrier_event (MetaDisplay *display,
 | 
			
		||||
                                             XIEvent     *event);
 | 
			
		||||
#endif /* HAVE_XI23 */
 | 
			
		||||
 | 
			
		||||
void meta_display_set_input_focus_xwindow (MetaDisplay *display,
 | 
			
		||||
                                           MetaScreen  *screen,
 | 
			
		||||
                                           Window       window,
 | 
			
		||||
                                           guint32      timestamp);
 | 
			
		||||
 | 
			
		||||
void meta_display_sync_wayland_input_focus (MetaDisplay *display);
 | 
			
		||||
void meta_display_update_focus_window (MetaDisplay *display,
 | 
			
		||||
                                       MetaWindow  *window,
 | 
			
		||||
                                       Window       xwindow,
 | 
			
		||||
                                       gulong       serial,
 | 
			
		||||
                                       gboolean     focused_by_us);
 | 
			
		||||
 | 
			
		||||
void meta_display_sanity_check_timestamps (MetaDisplay *display,
 | 
			
		||||
                                           guint32      timestamp);
 | 
			
		||||
gboolean meta_display_timestamp_too_old (MetaDisplay *display,
 | 
			
		||||
                                         guint32     *timestamp);
 | 
			
		||||
void meta_display_set_input_focus_xwindow (MetaDisplay   *display,
 | 
			
		||||
                                           MetaScreen    *screen,
 | 
			
		||||
                                           MetaFocusType  type,
 | 
			
		||||
                                           Window         window,
 | 
			
		||||
                                           guint32        timestamp);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3053
									
								
								src/core/display.c
									
									
									
									
									
								
							
							
						
						
									
										3053
									
								
								src/core/display.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -30,6 +30,7 @@
 | 
			
		||||
 */
 | 
			
		||||
#define WINDOW_EDGES_RELEVANT(window, display) \
 | 
			
		||||
  meta_window_should_be_showing (window) &&    \
 | 
			
		||||
  window->screen == display->grab_screen &&    \
 | 
			
		||||
  window         != display->grab_window &&    \
 | 
			
		||||
  window->type   != META_WINDOW_DESKTOP &&     \
 | 
			
		||||
  window->type   != META_WINDOW_MENU    &&     \
 | 
			
		||||
@@ -962,9 +963,9 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
 | 
			
		||||
  /*
 | 
			
		||||
   * 1st: Get the list of relevant windows, from bottom to top
 | 
			
		||||
   */
 | 
			
		||||
  stacked_windows =
 | 
			
		||||
    meta_stack_list_windows (display->screen->stack,
 | 
			
		||||
                             display->screen->active_workspace);
 | 
			
		||||
  stacked_windows = 
 | 
			
		||||
    meta_stack_list_windows (display->grab_screen->stack,
 | 
			
		||||
                             display->grab_screen->active_workspace);
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * 2nd: we need to separate that stacked list into a list of windows that
 | 
			
		||||
@@ -1025,7 +1026,7 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
 | 
			
		||||
           * by other windows or DOCKS, but that's handled below).
 | 
			
		||||
           */
 | 
			
		||||
          meta_rectangle_intersect (&cur_rect, 
 | 
			
		||||
                                    &display->screen->rect,
 | 
			
		||||
                                    &display->grab_screen->rect,
 | 
			
		||||
                                    &reduced);
 | 
			
		||||
 | 
			
		||||
          new_edges = NULL;
 | 
			
		||||
@@ -1122,8 +1123,8 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
 | 
			
		||||
   */
 | 
			
		||||
  cache_edges (display,
 | 
			
		||||
               edges,
 | 
			
		||||
               display->screen->active_workspace->monitor_edges,
 | 
			
		||||
               display->screen->active_workspace->screen_edges);
 | 
			
		||||
               display->grab_screen->active_workspace->monitor_edges,
 | 
			
		||||
               display->grab_screen->active_workspace->screen_edges);
 | 
			
		||||
  g_list_free (edges);
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,9 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2014 Red Hat
 | 
			
		||||
 *
 | 
			
		||||
/* 
 | 
			
		||||
 * Copyright (C) 2001 Havoc Pennington, error trapping inspired by GDK
 | 
			
		||||
 * code copyrighted by the GTK team.
 | 
			
		||||
 * 
 | 
			
		||||
 * 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,11 +13,9 @@
 | 
			
		||||
 * 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.
 | 
			
		||||
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -28,250 +27,42 @@
 | 
			
		||||
#include <config.h>
 | 
			
		||||
#include <meta/errors.h>
 | 
			
		||||
#include "display-private.h"
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <gdk/gdk.h>
 | 
			
		||||
 | 
			
		||||
/* This is a copy-paste of the error handling code in GDK, modified
 | 
			
		||||
 * so that it works with mutter's internal structures, since we don't
 | 
			
		||||
 * have a GDK display open. */
 | 
			
		||||
 | 
			
		||||
/* compare X sequence numbers handling wraparound */
 | 
			
		||||
#define SEQUENCE_COMPARE(a,op,b) (((long) (a) - (long) (b)) op 0)
 | 
			
		||||
 | 
			
		||||
typedef struct _GdkErrorTrap  GdkErrorTrap;
 | 
			
		||||
 | 
			
		||||
struct _GdkErrorTrap
 | 
			
		||||
{
 | 
			
		||||
  /* Next sequence when trap was pushed, i.e. first sequence to
 | 
			
		||||
   * ignore
 | 
			
		||||
   */
 | 
			
		||||
  gulong start_sequence;
 | 
			
		||||
 | 
			
		||||
  /* Next sequence when trap was popped, i.e. first sequence
 | 
			
		||||
   * to not ignore. 0 if trap is still active.
 | 
			
		||||
   */
 | 
			
		||||
  gulong end_sequence;
 | 
			
		||||
 | 
			
		||||
  /* Most recent error code within the sequence */
 | 
			
		||||
  int error_code;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* delivers an error event from the error handler in gdkmain-x11.c */
 | 
			
		||||
static void
 | 
			
		||||
meta_display_error_event (MetaDisplay *display,
 | 
			
		||||
                          XErrorEvent *error)
 | 
			
		||||
{
 | 
			
		||||
  GSList *tmp_list;
 | 
			
		||||
  gboolean ignore;
 | 
			
		||||
 | 
			
		||||
  ignore = FALSE;
 | 
			
		||||
  for (tmp_list = display->error_traps;
 | 
			
		||||
       tmp_list != NULL;
 | 
			
		||||
       tmp_list = tmp_list->next)
 | 
			
		||||
    {
 | 
			
		||||
      GdkErrorTrap *trap;
 | 
			
		||||
 | 
			
		||||
      trap = tmp_list->data;
 | 
			
		||||
 | 
			
		||||
      if (SEQUENCE_COMPARE (trap->start_sequence, <=, error->serial) &&
 | 
			
		||||
          (trap->end_sequence == 0 ||
 | 
			
		||||
           SEQUENCE_COMPARE (trap->end_sequence, >, error->serial)))
 | 
			
		||||
        {
 | 
			
		||||
          ignore = TRUE;
 | 
			
		||||
          trap->error_code = error->error_code;
 | 
			
		||||
          break; /* only innermost trap gets the error code */
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (!ignore)
 | 
			
		||||
    {
 | 
			
		||||
      gchar buf[64];
 | 
			
		||||
      gchar *msg;
 | 
			
		||||
 | 
			
		||||
      XGetErrorText (display->xdisplay, error->error_code, buf, 63);
 | 
			
		||||
 | 
			
		||||
      msg =
 | 
			
		||||
        g_strdup_printf ("mutter received an X Window System error: %s\n"
 | 
			
		||||
                         "  (Details: serial %ld error_code %d request_code %d minor_code %d)\n",
 | 
			
		||||
                         buf,
 | 
			
		||||
                         error->serial,
 | 
			
		||||
                         error->error_code,
 | 
			
		||||
                         error->request_code,
 | 
			
		||||
                         error->minor_code);
 | 
			
		||||
 | 
			
		||||
      g_error ("%s", msg);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
gdk_x_error (Display	 *xdisplay,
 | 
			
		||||
             XErrorEvent *error)
 | 
			
		||||
{
 | 
			
		||||
  MetaDisplay *display = meta_display_for_x_display (xdisplay);
 | 
			
		||||
  meta_display_error_event (display, error);
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* non-GDK previous error handler */
 | 
			
		||||
typedef int (*GdkXErrorHandler) (Display *, XErrorEvent *);
 | 
			
		||||
static GdkXErrorHandler _gdk_old_error_handler;
 | 
			
		||||
/* number of times we've pushed the GDK error handler */
 | 
			
		||||
static int _gdk_error_handler_push_count = 0;
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
_gdk_x11_error_handler_push (void)
 | 
			
		||||
{
 | 
			
		||||
  GdkXErrorHandler previous;
 | 
			
		||||
 | 
			
		||||
  previous = XSetErrorHandler (gdk_x_error);
 | 
			
		||||
 | 
			
		||||
  if (_gdk_error_handler_push_count > 0)
 | 
			
		||||
    {
 | 
			
		||||
      if (previous != gdk_x_error)
 | 
			
		||||
        g_warning ("XSetErrorHandler() called with a GDK error trap pushed. Don't do that.");
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      _gdk_old_error_handler = previous;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  _gdk_error_handler_push_count += 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
_gdk_x11_error_handler_pop  (void)
 | 
			
		||||
{
 | 
			
		||||
  g_return_if_fail (_gdk_error_handler_push_count > 0);
 | 
			
		||||
 | 
			
		||||
  _gdk_error_handler_push_count -= 1;
 | 
			
		||||
 | 
			
		||||
  if (_gdk_error_handler_push_count == 0)
 | 
			
		||||
    {
 | 
			
		||||
      XSetErrorHandler (_gdk_old_error_handler);
 | 
			
		||||
      _gdk_old_error_handler = NULL;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
delete_outdated_error_traps (MetaDisplay *display)
 | 
			
		||||
{
 | 
			
		||||
  GSList *tmp_list;
 | 
			
		||||
  gulong processed_sequence;
 | 
			
		||||
 | 
			
		||||
  processed_sequence = XLastKnownRequestProcessed (display->xdisplay);
 | 
			
		||||
 | 
			
		||||
  tmp_list = display->error_traps;
 | 
			
		||||
  while (tmp_list != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      GdkErrorTrap *trap = tmp_list->data;
 | 
			
		||||
 | 
			
		||||
      if (trap->end_sequence != 0 &&
 | 
			
		||||
          SEQUENCE_COMPARE (trap->end_sequence, <=, processed_sequence))
 | 
			
		||||
        {
 | 
			
		||||
          GSList *free_me = tmp_list;
 | 
			
		||||
 | 
			
		||||
          tmp_list = tmp_list->next;
 | 
			
		||||
          display->error_traps = g_slist_delete_link (display->error_traps, free_me);
 | 
			
		||||
          g_slice_free (GdkErrorTrap, trap);
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          tmp_list = tmp_list->next;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
/* In GTK+-3.0, the error trapping code was significantly rewritten. The new code
 | 
			
		||||
 * has some neat features (like knowing automatically if a sync is needed or not
 | 
			
		||||
 * and handling errors asynchronously when the error code isn't needed immediately),
 | 
			
		||||
 * but it's basically incompatible with the hacks we played with GTK+-2.0 to
 | 
			
		||||
 * use a custom error handler along with gdk_error_trap_push().
 | 
			
		||||
 *
 | 
			
		||||
 * Since the main point of our custom error trap was to get the error logged
 | 
			
		||||
 * to the right place, with GTK+-3.0 we simply omit our own error handler and
 | 
			
		||||
 * use the GTK+ handling straight-up.
 | 
			
		||||
 * (See https://bugzilla.gnome.org/show_bug.cgi?id=630216 for restoring logging.)
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_error_trap_push (MetaDisplay *display)
 | 
			
		||||
{
 | 
			
		||||
  GdkErrorTrap *trap;
 | 
			
		||||
 | 
			
		||||
  delete_outdated_error_traps (display);
 | 
			
		||||
 | 
			
		||||
  /* set up the Xlib callback to tell us about errors */
 | 
			
		||||
  _gdk_x11_error_handler_push ();
 | 
			
		||||
 | 
			
		||||
  trap = g_slice_new0 (GdkErrorTrap);
 | 
			
		||||
 | 
			
		||||
  trap->start_sequence = XNextRequest (display->xdisplay);
 | 
			
		||||
  trap->error_code = Success;
 | 
			
		||||
 | 
			
		||||
  display->error_traps =
 | 
			
		||||
    g_slist_prepend (display->error_traps, trap);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gint
 | 
			
		||||
meta_error_trap_pop_internal (MetaDisplay *display,
 | 
			
		||||
                              gboolean     need_code)
 | 
			
		||||
{
 | 
			
		||||
  GdkErrorTrap *trap;
 | 
			
		||||
  GSList *tmp_list;
 | 
			
		||||
  int result;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (display->error_traps != NULL, Success);
 | 
			
		||||
 | 
			
		||||
  /* Find the first trap that hasn't been popped already */
 | 
			
		||||
  trap = NULL; /* quiet gcc */
 | 
			
		||||
  for (tmp_list = display->error_traps;
 | 
			
		||||
       tmp_list != NULL;
 | 
			
		||||
       tmp_list = tmp_list->next)
 | 
			
		||||
    {
 | 
			
		||||
      trap = tmp_list->data;
 | 
			
		||||
 | 
			
		||||
      if (trap->end_sequence == 0)
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (trap != NULL, Success);
 | 
			
		||||
  g_assert (trap->end_sequence == 0);
 | 
			
		||||
 | 
			
		||||
  /* May need to sync to fill in trap->error_code if we care about
 | 
			
		||||
   * getting an error code.
 | 
			
		||||
   */
 | 
			
		||||
  if (need_code)
 | 
			
		||||
    {
 | 
			
		||||
      gulong processed_sequence;
 | 
			
		||||
      gulong next_sequence;
 | 
			
		||||
 | 
			
		||||
      next_sequence = XNextRequest (display->xdisplay);
 | 
			
		||||
      processed_sequence = XLastKnownRequestProcessed (display->xdisplay);
 | 
			
		||||
 | 
			
		||||
      /* If our last request was already processed, there is no point
 | 
			
		||||
       * in syncing. i.e. if last request was a round trip (or even if
 | 
			
		||||
       * we got an event with the serial of a non-round-trip)
 | 
			
		||||
       */
 | 
			
		||||
      if ((next_sequence - 1) != processed_sequence)
 | 
			
		||||
        {
 | 
			
		||||
          XSync (display->xdisplay, False);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      result = trap->error_code;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      result = Success;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /* record end of trap, giving us a range of
 | 
			
		||||
   * error sequences we'll ignore.
 | 
			
		||||
   */
 | 
			
		||||
  trap->end_sequence = XNextRequest (display->xdisplay);
 | 
			
		||||
 | 
			
		||||
  /* remove the Xlib callback */
 | 
			
		||||
  _gdk_x11_error_handler_pop ();
 | 
			
		||||
 | 
			
		||||
  /* we may already be outdated */
 | 
			
		||||
  delete_outdated_error_traps (display);
 | 
			
		||||
 | 
			
		||||
  return result;
 | 
			
		||||
  gdk_error_trap_push ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_error_trap_pop (MetaDisplay *display)
 | 
			
		||||
{
 | 
			
		||||
  meta_error_trap_pop_internal (display, FALSE);
 | 
			
		||||
  gdk_error_trap_pop_ignored ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_error_trap_push_with_return (MetaDisplay *display)
 | 
			
		||||
{
 | 
			
		||||
  gdk_error_trap_push ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
meta_error_trap_pop_with_return  (MetaDisplay *display)
 | 
			
		||||
{
 | 
			
		||||
  return meta_error_trap_pop_internal (display, TRUE);
 | 
			
		||||
  return gdk_error_trap_pop ();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2266
									
								
								src/core/events.c
									
									
									
									
									
								
							
							
						
						
									
										2266
									
								
								src/core/events.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,32 +0,0 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Havoc Pennington
 | 
			
		||||
 * Copyright (C) 2002, 2003, 2004 Red Hat, Inc.
 | 
			
		||||
 * Copyright (C) 2003, 2004 Rob Adams
 | 
			
		||||
 * Copyright (C) 2004-2006 Elijah Newren
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License as
 | 
			
		||||
 * published by the Free Software Foundation; either version 2 of the
 | 
			
		||||
 * License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <meta/display.h>
 | 
			
		||||
 | 
			
		||||
#ifndef META_EVENTS_H
 | 
			
		||||
#define META_EVENTS_H
 | 
			
		||||
 | 
			
		||||
void meta_display_init_events (MetaDisplay *display);
 | 
			
		||||
void meta_display_free_events (MetaDisplay *display);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@@ -35,7 +35,8 @@
 | 
			
		||||
                    ButtonPressMask | ButtonReleaseMask |          \
 | 
			
		||||
                    PointerMotionMask | PointerMotionHintMask |    \
 | 
			
		||||
                    EnterWindowMask | LeaveWindowMask |            \
 | 
			
		||||
                    FocusChangeMask)
 | 
			
		||||
                    FocusChangeMask |                              \
 | 
			
		||||
                    ColormapChangeMask)
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_window_ensure_frame (MetaWindow *window)
 | 
			
		||||
@@ -92,6 +93,7 @@ meta_window_ensure_frame (MetaWindow *window)
 | 
			
		||||
    visual = NULL;
 | 
			
		||||
  
 | 
			
		||||
  frame->xwindow = meta_ui_create_frame_window (window->screen->ui,
 | 
			
		||||
                                                window->display->xdisplay,
 | 
			
		||||
                                                visual,
 | 
			
		||||
                                                frame->rect.x,
 | 
			
		||||
                                                frame->rect.y,
 | 
			
		||||
 
 | 
			
		||||
@@ -230,7 +230,7 @@ read_rgb_icon (MetaDisplay   *display,
 | 
			
		||||
  int mini_w, mini_h;
 | 
			
		||||
  gulong *data_as_long;
 | 
			
		||||
 | 
			
		||||
  meta_error_trap_push (display);
 | 
			
		||||
  meta_error_trap_push_with_return (display);
 | 
			
		||||
  type = None;
 | 
			
		||||
  data = NULL;
 | 
			
		||||
  result = XGetWindowProperty (display->xdisplay,
 | 
			
		||||
@@ -504,7 +504,7 @@ get_kwm_win_icon (MetaDisplay *display,
 | 
			
		||||
  *pixmap = None;
 | 
			
		||||
  *mask = None;
 | 
			
		||||
 | 
			
		||||
  meta_error_trap_push (display);
 | 
			
		||||
  meta_error_trap_push_with_return (display);
 | 
			
		||||
  icons = NULL;
 | 
			
		||||
  result = XGetWindowProperty (display->xdisplay, xwindow,
 | 
			
		||||
                               display->atom__KWM_WIN_ICON,
 | 
			
		||||
@@ -30,7 +30,6 @@
 | 
			
		||||
#include <gio/gio.h>
 | 
			
		||||
#include <meta/keybindings.h>
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaKeyHandler MetaKeyHandler;
 | 
			
		||||
struct _MetaKeyHandler
 | 
			
		||||
{
 | 
			
		||||
  char *name;
 | 
			
		||||
@@ -48,48 +47,9 @@ struct _MetaKeyBinding
 | 
			
		||||
  KeyCode keycode;
 | 
			
		||||
  unsigned int mask;
 | 
			
		||||
  MetaVirtualModifier modifiers;
 | 
			
		||||
  gint flags;
 | 
			
		||||
  MetaKeyHandler *handler;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * MetaKeyCombo:
 | 
			
		||||
 * @keysym: keysym
 | 
			
		||||
 * @keycode: keycode
 | 
			
		||||
 * @modifiers: modifiers
 | 
			
		||||
 */
 | 
			
		||||
typedef struct _MetaKeyCombo MetaKeyCombo;
 | 
			
		||||
struct _MetaKeyCombo
 | 
			
		||||
{
 | 
			
		||||
  unsigned int keysym;
 | 
			
		||||
  unsigned int keycode;
 | 
			
		||||
  MetaVirtualModifier modifiers;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
  char *name;
 | 
			
		||||
  GSettings *settings;
 | 
			
		||||
 | 
			
		||||
  MetaKeyBindingAction action;
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * A list of MetaKeyCombos. Each of them is bound to
 | 
			
		||||
   * this keypref. If one has keysym==modifiers==0, it is
 | 
			
		||||
   * ignored.
 | 
			
		||||
   */
 | 
			
		||||
  GSList *combos;
 | 
			
		||||
 | 
			
		||||
  /* for keybindings that can have shift or not like Alt+Tab */
 | 
			
		||||
  gboolean      add_shift:1;
 | 
			
		||||
 | 
			
		||||
  /* for keybindings that apply only to a window */
 | 
			
		||||
  gboolean      per_window:1;
 | 
			
		||||
 | 
			
		||||
  /* for keybindings not added with meta_display_add_keybinding() */
 | 
			
		||||
  gboolean      builtin:1;
 | 
			
		||||
} MetaKeyPref;
 | 
			
		||||
 | 
			
		||||
void     meta_display_init_keys             (MetaDisplay *display);
 | 
			
		||||
void     meta_display_shutdown_keys         (MetaDisplay *display);
 | 
			
		||||
void     meta_screen_grab_keys              (MetaScreen  *screen);
 | 
			
		||||
@@ -117,8 +77,5 @@ gboolean meta_prefs_add_keybinding          (const char           *name,
 | 
			
		||||
 | 
			
		||||
gboolean meta_prefs_remove_keybinding       (const char    *name);
 | 
			
		||||
 | 
			
		||||
GList *meta_prefs_get_keybindings (void);
 | 
			
		||||
void meta_prefs_get_overlay_binding (MetaKeyCombo *combo);
 | 
			
		||||
const char *meta_prefs_get_iso_next_group_option (void);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -42,7 +42,7 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define _GNU_SOURCE
 | 
			
		||||
#define _XOPEN_SOURCE /* for putenv() and some signal-related functions */
 | 
			
		||||
#define _SVID_SOURCE /* for putenv() and some signal-related functions */
 | 
			
		||||
 | 
			
		||||
#include <config.h>
 | 
			
		||||
#include <meta/main.h>
 | 
			
		||||
@@ -50,11 +50,14 @@
 | 
			
		||||
#include "display-private.h"
 | 
			
		||||
#include <meta/errors.h>
 | 
			
		||||
#include "ui.h"
 | 
			
		||||
#include "session.h"
 | 
			
		||||
#include <meta/prefs.h>
 | 
			
		||||
#include <meta/compositor.h>
 | 
			
		||||
#include "meta-wayland-private.h"
 | 
			
		||||
 | 
			
		||||
#include <glib-object.h>
 | 
			
		||||
#include <glib-unix.h>
 | 
			
		||||
#include <gdk/gdkx.h>
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
@@ -70,16 +73,12 @@
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
#include <clutter/x11/clutter-x11.h>
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_INTROSPECTION
 | 
			
		||||
#include <girepository.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "x11/session.h"
 | 
			
		||||
 | 
			
		||||
#include "wayland/meta-wayland.h"
 | 
			
		||||
#include "backends/meta-backend.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * The exit code we'll return to our parent process when we eventually die.
 | 
			
		||||
 */
 | 
			
		||||
@@ -191,7 +190,6 @@ static gboolean  opt_replace_wm;
 | 
			
		||||
static gboolean  opt_disable_sm;
 | 
			
		||||
static gboolean  opt_sync;
 | 
			
		||||
static gboolean  opt_wayland;
 | 
			
		||||
static gboolean  opt_display_server;
 | 
			
		||||
 | 
			
		||||
static GOptionEntry meta_options[] = {
 | 
			
		||||
  {
 | 
			
		||||
@@ -235,11 +233,6 @@ static GOptionEntry meta_options[] = {
 | 
			
		||||
    N_("Run as a wayland compositor"),
 | 
			
		||||
    NULL
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "display-server", 0, 0, G_OPTION_ARG_NONE,
 | 
			
		||||
    &opt_display_server,
 | 
			
		||||
    N_("Run as a full display server, rather than nested")
 | 
			
		||||
  },
 | 
			
		||||
  {NULL}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -266,6 +259,72 @@ meta_get_option_context (void)
 | 
			
		||||
  return ctx;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 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
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_clutter_init (void)
 | 
			
		||||
{
 | 
			
		||||
  clutter_x11_set_display (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
 | 
			
		||||
  clutter_x11_disable_event_retrieval ();
 | 
			
		||||
 | 
			
		||||
  if (CLUTTER_INIT_SUCCESS == clutter_init (NULL, NULL))
 | 
			
		||||
    {
 | 
			
		||||
      GSource *source = g_source_new (&event_funcs, sizeof (GSource));
 | 
			
		||||
      g_source_attach (source, NULL);
 | 
			
		||||
      g_source_unref (source);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
	  meta_fatal ("Unable to initialize Clutter.\n");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_select_display:
 | 
			
		||||
 *
 | 
			
		||||
@@ -284,8 +343,7 @@ meta_select_display (char *display_arg)
 | 
			
		||||
  else
 | 
			
		||||
    display_name = g_getenv ("MUTTER_DISPLAY");
 | 
			
		||||
 | 
			
		||||
  if (display_name)
 | 
			
		||||
    g_setenv ("DISPLAY", display_name, TRUE);
 | 
			
		||||
  g_setenv ("DISPLAY", display_name, TRUE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -342,7 +400,8 @@ meta_init (void)
 | 
			
		||||
  if (g_getenv ("MUTTER_DEBUG"))
 | 
			
		||||
    meta_set_debugging (TRUE);
 | 
			
		||||
 | 
			
		||||
  if (opt_display_server)
 | 
			
		||||
  /* We consider running from mutter-launch equivalent to running from bare metal. */
 | 
			
		||||
  if (getenv ("WESTON_LAUNCHER_SOCK"))
 | 
			
		||||
    clutter_set_windowing_backend (CLUTTER_WINDOWING_EGL);
 | 
			
		||||
 | 
			
		||||
  meta_set_is_wayland_compositor (opt_wayland);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										46
									
								
								src/core/meta-cursor-tracker-private.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/core/meta-cursor-tracker-private.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
/* -*- 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 <clutter/clutter.h>
 | 
			
		||||
 | 
			
		||||
gboolean meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
 | 
			
		||||
					    XEvent            *xevent);
 | 
			
		||||
 | 
			
		||||
void     meta_cursor_tracker_set_grab_cursor     (MetaCursorTracker  *tracker,
 | 
			
		||||
                                                  MetaCursor          cursor);
 | 
			
		||||
void     meta_cursor_tracker_set_window_cursor   (MetaCursorTracker  *tracker,
 | 
			
		||||
                                                  struct wl_resource *buffer,
 | 
			
		||||
                                                  int                 hot_x,
 | 
			
		||||
                                                  int                 hot_y);
 | 
			
		||||
void     meta_cursor_tracker_unset_window_cursor (MetaCursorTracker  *tracker);
 | 
			
		||||
void     meta_cursor_tracker_set_root_cursor     (MetaCursorTracker  *tracker,
 | 
			
		||||
                                                  MetaCursor          cursor);
 | 
			
		||||
 | 
			
		||||
void     meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
 | 
			
		||||
					      int                new_x,
 | 
			
		||||
					      int                new_y);
 | 
			
		||||
void     meta_cursor_tracker_paint           (MetaCursorTracker *tracker);
 | 
			
		||||
#endif
 | 
			
		||||
@@ -39,14 +39,76 @@
 | 
			
		||||
#include <gbm.h>
 | 
			
		||||
 | 
			
		||||
#include <gdk/gdk.h>
 | 
			
		||||
#include <gdk/gdkx.h>
 | 
			
		||||
 | 
			
		||||
#include "meta-cursor-private.h"
 | 
			
		||||
#include <X11/cursorfont.h>
 | 
			
		||||
#include <X11/extensions/Xfixes.h>
 | 
			
		||||
#include <X11/Xcursor/Xcursor.h>
 | 
			
		||||
 | 
			
		||||
#include "meta-cursor-tracker-private.h"
 | 
			
		||||
#include "screen-private.h"
 | 
			
		||||
#include "meta-monitor-manager.h"
 | 
			
		||||
#include "meta-wayland-private.h"
 | 
			
		||||
#include "monitor-private.h"
 | 
			
		||||
 | 
			
		||||
#include "wayland/meta-wayland-private.h"
 | 
			
		||||
#define META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_X 7
 | 
			
		||||
#define META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_Y 4
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  CoglTexture2D *texture;
 | 
			
		||||
  struct gbm_bo *bo;
 | 
			
		||||
  int hot_x, hot_y;
 | 
			
		||||
 | 
			
		||||
  int ref_count;
 | 
			
		||||
} MetaCursorReference;
 | 
			
		||||
 | 
			
		||||
struct _MetaCursorTracker {
 | 
			
		||||
  GObject parent_instance;
 | 
			
		||||
 | 
			
		||||
  MetaScreen *screen;
 | 
			
		||||
 | 
			
		||||
  gboolean is_showing;
 | 
			
		||||
  gboolean has_hw_cursor;
 | 
			
		||||
 | 
			
		||||
  /* The cursor tracker stores the cursor for the current grab
 | 
			
		||||
   * operation, the cursor for the window with pointer focus, and
 | 
			
		||||
   * the cursor for the root window, which contains either the
 | 
			
		||||
   * default arrow cursor or the 'busy' hourglass if we're launching
 | 
			
		||||
   * an app.
 | 
			
		||||
   *
 | 
			
		||||
   * We choose the first one available -- if there's a grab cursor,
 | 
			
		||||
   * we choose that cursor, if there's window cursor, we choose that,
 | 
			
		||||
   * otherwise we choose the root cursor.
 | 
			
		||||
   *
 | 
			
		||||
   * The displayed_cursor contains the chosen cursor.
 | 
			
		||||
   */
 | 
			
		||||
  MetaCursorReference *displayed_cursor;
 | 
			
		||||
 | 
			
		||||
  MetaCursorReference *grab_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;
 | 
			
		||||
 | 
			
		||||
  MetaCursorReference *default_cursors[META_CURSOR_LAST];
 | 
			
		||||
 | 
			
		||||
  int current_x, current_y;
 | 
			
		||||
  MetaRectangle current_rect;
 | 
			
		||||
  MetaRectangle previous_rect;
 | 
			
		||||
  gboolean previous_is_valid;
 | 
			
		||||
 | 
			
		||||
  CoglPipeline *pipeline;
 | 
			
		||||
  int drm_fd;
 | 
			
		||||
  struct gbm_device *gbm;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaCursorTrackerClass {
 | 
			
		||||
  GObjectClass parent_class;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT);
 | 
			
		||||
 | 
			
		||||
@@ -62,6 +124,360 @@ static void meta_cursor_tracker_set_crtc_has_hw_cursor (MetaCursorTracker *track
 | 
			
		||||
                                                        gboolean           has_hw_cursor);
 | 
			
		||||
static void sync_cursor (MetaCursorTracker *tracker);
 | 
			
		||||
 | 
			
		||||
static MetaCursorReference *
 | 
			
		||||
meta_cursor_reference_ref (MetaCursorReference *self)
 | 
			
		||||
{
 | 
			
		||||
  g_assert (self->ref_count > 0);
 | 
			
		||||
  self->ref_count++;
 | 
			
		||||
 | 
			
		||||
  return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_cursor_reference_unref (MetaCursorReference *self)
 | 
			
		||||
{
 | 
			
		||||
  self->ref_count--;
 | 
			
		||||
 | 
			
		||||
  if (self->ref_count == 0)
 | 
			
		||||
    {
 | 
			
		||||
      cogl_object_unref (self->texture);
 | 
			
		||||
      if (self->bo)
 | 
			
		||||
        gbm_bo_destroy (self->bo);
 | 
			
		||||
 | 
			
		||||
      g_slice_free (MetaCursorReference, self);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
translate_meta_cursor (MetaCursor   cursor,
 | 
			
		||||
                       guint       *glyph_out,
 | 
			
		||||
                       const char **name_out)
 | 
			
		||||
{
 | 
			
		||||
  guint glyph = XC_num_glyphs;
 | 
			
		||||
  const char *name = NULL;
 | 
			
		||||
 | 
			
		||||
  switch (cursor)
 | 
			
		||||
    {
 | 
			
		||||
    case META_CURSOR_DEFAULT:
 | 
			
		||||
      glyph = XC_left_ptr;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_NORTH_RESIZE:
 | 
			
		||||
      glyph = XC_top_side;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_SOUTH_RESIZE:
 | 
			
		||||
      glyph = XC_bottom_side;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_WEST_RESIZE:
 | 
			
		||||
      glyph = XC_left_side;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_EAST_RESIZE:
 | 
			
		||||
      glyph = XC_right_side;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_SE_RESIZE:
 | 
			
		||||
      glyph = XC_bottom_right_corner;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_SW_RESIZE:
 | 
			
		||||
      glyph = XC_bottom_left_corner;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_NE_RESIZE:
 | 
			
		||||
      glyph = XC_top_right_corner;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_NW_RESIZE:
 | 
			
		||||
      glyph = XC_top_left_corner;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_MOVE_OR_RESIZE_WINDOW:
 | 
			
		||||
      glyph = XC_fleur;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_BUSY:
 | 
			
		||||
      glyph = XC_watch;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_DND_IN_DRAG:
 | 
			
		||||
      name = "dnd-none";
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_DND_MOVE:
 | 
			
		||||
      name = "dnd-move";
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_DND_COPY:
 | 
			
		||||
      name = "dnd-copy";
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_DND_UNSUPPORTED_TARGET:
 | 
			
		||||
      name = "dnd-none";
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_POINTING_HAND:
 | 
			
		||||
      glyph = XC_hand2;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_CROSSHAIR:
 | 
			
		||||
      glyph = XC_crosshair;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_CURSOR_IBEAM:
 | 
			
		||||
      glyph = XC_xterm;
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
      g_assert_not_reached ();
 | 
			
		||||
      glyph = 0; /* silence compiler */
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  *glyph_out = glyph;
 | 
			
		||||
  *name_out = name;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Cursor
 | 
			
		||||
load_cursor_on_server (MetaDisplay *display,
 | 
			
		||||
                       MetaCursor   cursor)
 | 
			
		||||
{
 | 
			
		||||
  Cursor xcursor;
 | 
			
		||||
  guint glyph;
 | 
			
		||||
  const char *name;
 | 
			
		||||
 | 
			
		||||
  translate_meta_cursor (cursor, &glyph, &name);
 | 
			
		||||
 | 
			
		||||
  if (name != NULL)
 | 
			
		||||
    xcursor = XcursorLibraryLoadCursor (display->xdisplay, name);
 | 
			
		||||
  else
 | 
			
		||||
    xcursor = XCreateFontCursor (display->xdisplay, glyph);
 | 
			
		||||
 | 
			
		||||
  return xcursor;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Cursor
 | 
			
		||||
meta_display_create_x_cursor (MetaDisplay *display,
 | 
			
		||||
                              MetaCursor cursor)
 | 
			
		||||
{
 | 
			
		||||
  return load_cursor_on_server (display, cursor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static XcursorImage *
 | 
			
		||||
load_cursor_on_client (MetaDisplay *display,
 | 
			
		||||
                       MetaCursor   cursor)
 | 
			
		||||
{
 | 
			
		||||
  XcursorImage *image;
 | 
			
		||||
  guint glyph;
 | 
			
		||||
  const char *name;
 | 
			
		||||
  const char *theme = XcursorGetTheme (display->xdisplay);
 | 
			
		||||
  int size = XcursorGetDefaultSize (display->xdisplay);
 | 
			
		||||
 | 
			
		||||
  translate_meta_cursor (cursor, &glyph, &name);
 | 
			
		||||
 | 
			
		||||
  if (name != NULL)
 | 
			
		||||
    image = XcursorLibraryLoadImage (name, theme, size);
 | 
			
		||||
  else
 | 
			
		||||
    image = XcursorShapeLoadImage (glyph, theme, size);
 | 
			
		||||
 | 
			
		||||
  return image;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaCursorReference *
 | 
			
		||||
meta_cursor_reference_from_theme (MetaCursorTracker  *tracker,
 | 
			
		||||
                                  MetaCursor          cursor)
 | 
			
		||||
{
 | 
			
		||||
  XcursorImage *image;
 | 
			
		||||
  int width, height, rowstride;
 | 
			
		||||
  CoglPixelFormat cogl_format;
 | 
			
		||||
  uint32_t gbm_format;
 | 
			
		||||
  ClutterBackend *clutter_backend;
 | 
			
		||||
  CoglContext *cogl_context;
 | 
			
		||||
  MetaCursorReference *self;
 | 
			
		||||
 | 
			
		||||
  image = load_cursor_on_client (tracker->screen->display, cursor);
 | 
			
		||||
  if (!image)
 | 
			
		||||
    return NULL;
 | 
			
		||||
 | 
			
		||||
  width           = image->width;
 | 
			
		||||
  height          = 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
 | 
			
		||||
 | 
			
		||||
  self = g_slice_new0 (MetaCursorReference);
 | 
			
		||||
  self->ref_count = 1;
 | 
			
		||||
  self->hot_x = image->xhot;
 | 
			
		||||
  self->hot_y = image->yhot;
 | 
			
		||||
 | 
			
		||||
  clutter_backend = clutter_get_default_backend ();
 | 
			
		||||
  cogl_context = clutter_backend_get_cogl_context (clutter_backend);
 | 
			
		||||
  self->texture = cogl_texture_2d_new_from_data (cogl_context,
 | 
			
		||||
                                                 width, height,
 | 
			
		||||
                                                 cogl_format,
 | 
			
		||||
                                                 rowstride,
 | 
			
		||||
                                                 (uint8_t*)image->pixels,
 | 
			
		||||
                                                 NULL);
 | 
			
		||||
 | 
			
		||||
  if (tracker->gbm)
 | 
			
		||||
    {
 | 
			
		||||
      if (width > 64 || height > 64)
 | 
			
		||||
        {
 | 
			
		||||
          meta_warning ("Invalid theme cursor size (must be at most 64x64)\n");
 | 
			
		||||
          goto out;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (gbm_device_is_format_supported (tracker->gbm, gbm_format,
 | 
			
		||||
                                          GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE))
 | 
			
		||||
        {
 | 
			
		||||
          uint32_t buf[64 * 64];
 | 
			
		||||
          int i;
 | 
			
		||||
 | 
			
		||||
          self->bo = gbm_bo_create (tracker->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 * 64, image->pixels + i * width, width * 4);
 | 
			
		||||
 | 
			
		||||
          gbm_bo_write (self->bo, buf, 64 * 64 * 4);
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        meta_warning ("HW cursor for format %d not supported\n", gbm_format);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 out:
 | 
			
		||||
  XcursorImageDestroy (image);
 | 
			
		||||
 | 
			
		||||
  return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaCursorReference *
 | 
			
		||||
meta_cursor_reference_take_texture (CoglTexture2D *texture)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorReference *self;
 | 
			
		||||
 | 
			
		||||
  self = g_slice_new0 (MetaCursorReference);
 | 
			
		||||
  self->ref_count = 1;
 | 
			
		||||
 | 
			
		||||
  self->texture = texture;
 | 
			
		||||
 | 
			
		||||
  return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaCursorReference *
 | 
			
		||||
meta_cursor_reference_from_buffer (MetaCursorTracker  *tracker,
 | 
			
		||||
                                   struct wl_resource *buffer,
 | 
			
		||||
                                   int                 hot_x,
 | 
			
		||||
                                   int                 hot_y)
 | 
			
		||||
{
 | 
			
		||||
  ClutterBackend *backend;
 | 
			
		||||
  CoglContext *cogl_context;
 | 
			
		||||
  MetaCursorReference *self;
 | 
			
		||||
  CoglPixelFormat cogl_format;
 | 
			
		||||
  struct wl_shm_buffer *shm_buffer;
 | 
			
		||||
  uint32_t gbm_format;
 | 
			
		||||
 | 
			
		||||
  self = g_slice_new0 (MetaCursorReference);
 | 
			
		||||
  self->ref_count = 1;
 | 
			
		||||
  self->hot_x = hot_x;
 | 
			
		||||
  self->hot_y = hot_y;
 | 
			
		||||
 | 
			
		||||
  backend = clutter_get_default_backend ();
 | 
			
		||||
  cogl_context = clutter_backend_get_cogl_context (backend);
 | 
			
		||||
 | 
			
		||||
  shm_buffer = wl_shm_buffer_get (buffer);
 | 
			
		||||
  if (shm_buffer)
 | 
			
		||||
    {
 | 
			
		||||
      int rowstride = wl_shm_buffer_get_stride (shm_buffer);
 | 
			
		||||
      int width = wl_shm_buffer_get_width (shm_buffer);
 | 
			
		||||
      int height = wl_shm_buffer_get_height (shm_buffer);
 | 
			
		||||
 | 
			
		||||
      switch (wl_shm_buffer_get_format (shm_buffer))
 | 
			
		||||
        {
 | 
			
		||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
 | 
			
		||||
          case WL_SHM_FORMAT_ARGB8888:
 | 
			
		||||
            cogl_format = COGL_PIXEL_FORMAT_ARGB_8888_PRE;
 | 
			
		||||
            gbm_format = GBM_FORMAT_ARGB8888;
 | 
			
		||||
            break;
 | 
			
		||||
          case WL_SHM_FORMAT_XRGB8888:
 | 
			
		||||
            cogl_format = COGL_PIXEL_FORMAT_ARGB_8888;
 | 
			
		||||
            gbm_format = GBM_FORMAT_XRGB8888;
 | 
			
		||||
            break;
 | 
			
		||||
#else
 | 
			
		||||
          case WL_SHM_FORMAT_ARGB8888:
 | 
			
		||||
            cogl_format = COGL_PIXEL_FORMAT_BGRA_8888_PRE;
 | 
			
		||||
            gbm_format = GBM_FORMAT_ARGB8888;
 | 
			
		||||
            break;
 | 
			
		||||
          case WL_SHM_FORMAT_XRGB8888:
 | 
			
		||||
            cogl_format = COGL_PIXEL_FORMAT_BGRA_8888;
 | 
			
		||||
            gbm_format = GBM_FORMAT_XRGB8888;
 | 
			
		||||
            break;
 | 
			
		||||
#endif
 | 
			
		||||
          default:
 | 
			
		||||
            g_warn_if_reached ();
 | 
			
		||||
            cogl_format = COGL_PIXEL_FORMAT_ARGB_8888;
 | 
			
		||||
            gbm_format = GBM_FORMAT_ARGB8888;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      self->texture = cogl_texture_2d_new_from_data (cogl_context,
 | 
			
		||||
                                                     width, height,
 | 
			
		||||
                                                     cogl_format,
 | 
			
		||||
                                                     rowstride,
 | 
			
		||||
                                                     wl_shm_buffer_get_data (shm_buffer),
 | 
			
		||||
                                                     NULL);
 | 
			
		||||
 | 
			
		||||
      if (width > 64 || height > 64)
 | 
			
		||||
        {
 | 
			
		||||
          meta_warning ("Invalid cursor size (must be at most 64x64), falling back to software (GL) cursors\n");
 | 
			
		||||
          return self;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (tracker->gbm)
 | 
			
		||||
        {
 | 
			
		||||
          if (gbm_device_is_format_supported (tracker->gbm, gbm_format,
 | 
			
		||||
                                              GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE))
 | 
			
		||||
            {
 | 
			
		||||
              uint8_t *data;
 | 
			
		||||
              uint8_t buf[4 * 64 * 64];
 | 
			
		||||
              int i;
 | 
			
		||||
 | 
			
		||||
              self->bo = gbm_bo_create (tracker->gbm, 64, 64,
 | 
			
		||||
                                        gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
 | 
			
		||||
 | 
			
		||||
              data = wl_shm_buffer_get_data (shm_buffer);
 | 
			
		||||
              memset (buf, 0, sizeof(buf));
 | 
			
		||||
              for (i = 0; i < height; i++)
 | 
			
		||||
                memcpy (buf + i * 4 * 64, data + i * rowstride, 4 * width);
 | 
			
		||||
 | 
			
		||||
              gbm_bo_write (self->bo, buf, 64 * 64 * 4);
 | 
			
		||||
            }
 | 
			
		||||
          else
 | 
			
		||||
            meta_warning ("HW cursor for format %d not supported\n", gbm_format);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      int width, height;
 | 
			
		||||
 | 
			
		||||
      self->texture = cogl_wayland_texture_2d_new_from_buffer (cogl_context, buffer, NULL);
 | 
			
		||||
      width = cogl_texture_get_width (COGL_TEXTURE (self->texture));
 | 
			
		||||
      height = cogl_texture_get_height (COGL_TEXTURE (self->texture));
 | 
			
		||||
 | 
			
		||||
      /* 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 self;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (tracker->gbm)
 | 
			
		||||
        {
 | 
			
		||||
          self->bo = gbm_bo_import (tracker->gbm, GBM_BO_IMPORT_WL_BUFFER,
 | 
			
		||||
                                    buffer, GBM_BO_USE_CURSOR_64X64);
 | 
			
		||||
          if (!self->bo)
 | 
			
		||||
            meta_warning ("Importing HW cursor from wl_buffer failed\n");
 | 
			
		||||
        }
 | 
			
		||||
     }
 | 
			
		||||
 | 
			
		||||
  return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_cursor_tracker_init (MetaCursorTracker *self)
 | 
			
		||||
{
 | 
			
		||||
@@ -85,8 +501,8 @@ meta_cursor_tracker_finalize (GObject *object)
 | 
			
		||||
    meta_cursor_reference_unref (self->root_cursor);
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < META_CURSOR_LAST; i++)
 | 
			
		||||
    if (self->theme_cursors[i])
 | 
			
		||||
      meta_cursor_reference_unref (self->theme_cursors[i]);
 | 
			
		||||
    if (self->default_cursors[i])
 | 
			
		||||
      meta_cursor_reference_unref (self->default_cursors[i]);
 | 
			
		||||
 | 
			
		||||
  if (self->pipeline)
 | 
			
		||||
    cogl_object_unref (self->pipeline);
 | 
			
		||||
@@ -153,9 +569,6 @@ make_wayland_cursor_tracker (MetaScreen *screen)
 | 
			
		||||
 | 
			
		||||
  compositor = meta_wayland_compositor_get_default ();
 | 
			
		||||
  compositor->seat->cursor_tracker = self;
 | 
			
		||||
  meta_cursor_tracker_update_position (self,
 | 
			
		||||
                                       wl_fixed_to_int (compositor->seat->pointer.x),
 | 
			
		||||
                                       wl_fixed_to_int (compositor->seat->pointer.y));
 | 
			
		||||
 | 
			
		||||
#if defined(CLUTTER_WINDOWING_EGL)
 | 
			
		||||
  if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
 | 
			
		||||
@@ -244,22 +657,6 @@ meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
 | 
			
		||||
  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)
 | 
			
		||||
{
 | 
			
		||||
@@ -316,9 +713,10 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
 | 
			
		||||
 | 
			
		||||
  if (sprite != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      MetaCursorReference *cursor = meta_cursor_reference_take_texture (sprite,
 | 
			
		||||
                                                                        cursor_image->xhot,
 | 
			
		||||
                                                                        cursor_image->yhot);
 | 
			
		||||
      MetaCursorReference *cursor = meta_cursor_reference_take_texture (sprite);
 | 
			
		||||
      cursor->hot_x = cursor_image->xhot;
 | 
			
		||||
      cursor->hot_y = cursor_image->yhot;
 | 
			
		||||
 | 
			
		||||
      set_window_cursor (tracker, TRUE, cursor);
 | 
			
		||||
    }
 | 
			
		||||
  XFree (cursor_image);
 | 
			
		||||
@@ -338,7 +736,7 @@ meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker)
 | 
			
		||||
    ensure_xfixes_cursor (tracker);
 | 
			
		||||
 | 
			
		||||
  if (tracker->displayed_cursor)
 | 
			
		||||
    return meta_cursor_reference_get_cogl_texture (tracker->displayed_cursor, NULL, NULL);
 | 
			
		||||
    return COGL_TEXTURE (tracker->displayed_cursor->texture);
 | 
			
		||||
  else
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
@@ -361,7 +759,13 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
 | 
			
		||||
    ensure_xfixes_cursor (tracker);
 | 
			
		||||
 | 
			
		||||
  if (tracker->displayed_cursor)
 | 
			
		||||
    meta_cursor_reference_get_cogl_texture (tracker->displayed_cursor, x, y);
 | 
			
		||||
    {
 | 
			
		||||
      MetaCursorReference *displayed_cursor = tracker->displayed_cursor;
 | 
			
		||||
      if (x)
 | 
			
		||||
        *x = displayed_cursor->hot_x;
 | 
			
		||||
      if (y)
 | 
			
		||||
        *y = displayed_cursor->hot_y;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      if (x)
 | 
			
		||||
@@ -371,21 +775,43 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaCursorReference *
 | 
			
		||||
ensure_wayland_cursor (MetaCursorTracker *tracker,
 | 
			
		||||
                       MetaCursor         cursor)
 | 
			
		||||
{
 | 
			
		||||
  if (!tracker->default_cursors[cursor])
 | 
			
		||||
    {
 | 
			
		||||
      tracker->default_cursors[cursor] = meta_cursor_reference_from_theme (tracker, cursor);
 | 
			
		||||
      if (!tracker->default_cursors[cursor])
 | 
			
		||||
        meta_warning ("Failed to load cursor from theme\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return meta_cursor_reference_ref (tracker->default_cursors[cursor]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_cursor_tracker_set_grab_cursor (MetaCursorTracker   *tracker,
 | 
			
		||||
                                     MetaCursorReference *cursor)
 | 
			
		||||
meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker,
 | 
			
		||||
                                     MetaCursor         cursor)
 | 
			
		||||
{
 | 
			
		||||
  g_clear_pointer (&tracker->grab_cursor, meta_cursor_reference_unref);
 | 
			
		||||
  if (cursor)
 | 
			
		||||
    tracker->grab_cursor = meta_cursor_reference_ref (cursor);
 | 
			
		||||
 | 
			
		||||
  if (cursor != META_CURSOR_DEFAULT)
 | 
			
		||||
    tracker->grab_cursor = ensure_wayland_cursor (tracker, cursor);
 | 
			
		||||
  sync_cursor (tracker);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_cursor_tracker_set_window_cursor (MetaCursorTracker   *tracker,
 | 
			
		||||
                                       MetaCursorReference *cursor)
 | 
			
		||||
meta_cursor_tracker_set_window_cursor (MetaCursorTracker  *tracker,
 | 
			
		||||
                                       struct wl_resource *buffer,
 | 
			
		||||
                                       int                 hot_x,
 | 
			
		||||
                                       int                 hot_y)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorReference *cursor;
 | 
			
		||||
 | 
			
		||||
  if (buffer)
 | 
			
		||||
    cursor = meta_cursor_reference_from_buffer (tracker, buffer, hot_x, hot_y);
 | 
			
		||||
  else
 | 
			
		||||
    cursor = NULL;
 | 
			
		||||
 | 
			
		||||
  set_window_cursor (tracker, TRUE, cursor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -396,23 +822,26 @@ meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_cursor_tracker_set_root_cursor (MetaCursorTracker   *tracker,
 | 
			
		||||
                                     MetaCursorReference *cursor)
 | 
			
		||||
meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
 | 
			
		||||
                                     MetaCursor         cursor)
 | 
			
		||||
{
 | 
			
		||||
  g_clear_pointer (&tracker->root_cursor, meta_cursor_reference_unref);
 | 
			
		||||
  if (cursor)
 | 
			
		||||
    tracker->root_cursor = meta_cursor_reference_ref (cursor);
 | 
			
		||||
  Cursor xcursor;
 | 
			
		||||
  MetaDisplay *display = tracker->screen->display;
 | 
			
		||||
 | 
			
		||||
  sync_cursor (tracker);
 | 
			
		||||
}
 | 
			
		||||
  /* First create a cursor for X11 applications that don't specify their own */
 | 
			
		||||
  xcursor = meta_display_create_x_cursor (display, cursor);
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
should_have_hw_cursor (MetaCursorTracker *tracker)
 | 
			
		||||
{
 | 
			
		||||
  if (tracker->displayed_cursor)
 | 
			
		||||
    return (meta_cursor_reference_get_gbm_bo (tracker->displayed_cursor, NULL, NULL) != NULL);
 | 
			
		||||
  else
 | 
			
		||||
    return FALSE;
 | 
			
		||||
  XDefineCursor (display->xdisplay, tracker->screen->xroot, xcursor);
 | 
			
		||||
  XFlush (display->xdisplay);
 | 
			
		||||
  XFreeCursor (display->xdisplay, xcursor);
 | 
			
		||||
 | 
			
		||||
  /* Now update the real root cursor */
 | 
			
		||||
  if (meta_is_wayland_compositor ())
 | 
			
		||||
    {
 | 
			
		||||
      g_clear_pointer (&tracker->root_cursor, meta_cursor_reference_unref);
 | 
			
		||||
      tracker->root_cursor = ensure_wayland_cursor (tracker, cursor);
 | 
			
		||||
      sync_cursor (tracker);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -423,7 +852,7 @@ update_hw_cursor (MetaCursorTracker *tracker)
 | 
			
		||||
  unsigned int i, n_crtcs;
 | 
			
		||||
  gboolean enabled;
 | 
			
		||||
 | 
			
		||||
  enabled = should_have_hw_cursor (tracker);
 | 
			
		||||
  enabled = tracker->displayed_cursor && tracker->displayed_cursor->bo != NULL;
 | 
			
		||||
  tracker->has_hw_cursor = enabled;
 | 
			
		||||
 | 
			
		||||
  monitors = meta_monitor_manager_get ();
 | 
			
		||||
@@ -484,23 +913,6 @@ get_displayed_cursor (MetaCursorTracker *tracker)
 | 
			
		||||
  return tracker->root_cursor;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
update_displayed_cursor (MetaCursorTracker *tracker)
 | 
			
		||||
{
 | 
			
		||||
  if (meta_is_wayland_compositor ())
 | 
			
		||||
    {
 | 
			
		||||
      if (tracker->displayed_cursor)
 | 
			
		||||
        {
 | 
			
		||||
          CoglTexture *texture = meta_cursor_reference_get_cogl_texture (tracker->displayed_cursor, NULL, NULL);
 | 
			
		||||
          cogl_pipeline_set_layer_texture (tracker->pipeline, 0, texture);
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        cogl_pipeline_set_layer_texture (tracker->pipeline, 0, NULL);
 | 
			
		||||
 | 
			
		||||
      update_hw_cursor (tracker);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
sync_displayed_cursor (MetaCursorTracker *tracker)
 | 
			
		||||
{
 | 
			
		||||
@@ -513,7 +925,16 @@ sync_displayed_cursor (MetaCursorTracker *tracker)
 | 
			
		||||
  if (displayed_cursor)
 | 
			
		||||
    tracker->displayed_cursor = meta_cursor_reference_ref (displayed_cursor);
 | 
			
		||||
 | 
			
		||||
  update_displayed_cursor (tracker);
 | 
			
		||||
  if (meta_is_wayland_compositor ())
 | 
			
		||||
    {
 | 
			
		||||
      if (displayed_cursor)
 | 
			
		||||
        cogl_pipeline_set_layer_texture (tracker->pipeline, 0, COGL_TEXTURE (displayed_cursor->texture));
 | 
			
		||||
      else
 | 
			
		||||
        cogl_pipeline_set_layer_texture (tracker->pipeline, 0, NULL);
 | 
			
		||||
 | 
			
		||||
      update_hw_cursor (tracker);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_signal_emit (tracker, signals[CURSOR_CHANGED], 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -526,13 +947,14 @@ meta_cursor_tracker_queue_redraw (MetaCursorTracker *tracker)
 | 
			
		||||
 | 
			
		||||
  g_assert (meta_is_wayland_compositor ());
 | 
			
		||||
 | 
			
		||||
  /* Clear the location the cursor was at before, if we need to. */
 | 
			
		||||
  if (tracker->previous_is_valid)
 | 
			
		||||
    {
 | 
			
		||||
      clip.x = tracker->previous_rect.x;
 | 
			
		||||
      clip.y = tracker->previous_rect.y;
 | 
			
		||||
      clip.width = tracker->previous_rect.width;
 | 
			
		||||
      clip.height = tracker->previous_rect.height;
 | 
			
		||||
      cairo_rectangle_int_t clip = {
 | 
			
		||||
        .x = tracker->previous_rect.x,
 | 
			
		||||
        .y = tracker->previous_rect.y,
 | 
			
		||||
        .width = tracker->previous_rect.width,
 | 
			
		||||
        .height = tracker->previous_rect.height
 | 
			
		||||
      };
 | 
			
		||||
      clutter_actor_queue_redraw_with_clip (stage, &clip);
 | 
			
		||||
      tracker->previous_is_valid = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
@@ -557,15 +979,10 @@ sync_cursor (MetaCursorTracker *tracker)
 | 
			
		||||
 | 
			
		||||
  if (displayed_cursor)
 | 
			
		||||
    {
 | 
			
		||||
      CoglTexture *texture;
 | 
			
		||||
      int hot_x, hot_y;
 | 
			
		||||
 | 
			
		||||
      texture = meta_cursor_reference_get_cogl_texture (displayed_cursor, &hot_x, &hot_y);
 | 
			
		||||
 | 
			
		||||
      tracker->current_rect.x = tracker->current_x - hot_x;
 | 
			
		||||
      tracker->current_rect.y = tracker->current_y - hot_y;
 | 
			
		||||
      tracker->current_rect.width = cogl_texture_get_width (COGL_TEXTURE (texture));
 | 
			
		||||
      tracker->current_rect.height = cogl_texture_get_height (COGL_TEXTURE (texture));
 | 
			
		||||
      tracker->current_rect.x = tracker->current_x - displayed_cursor->hot_x;
 | 
			
		||||
      tracker->current_rect.y = tracker->current_y - displayed_cursor->hot_y;
 | 
			
		||||
      tracker->current_rect.width = cogl_texture_get_width (COGL_TEXTURE (displayed_cursor->texture));
 | 
			
		||||
      tracker->current_rect.height = cogl_texture_get_height (COGL_TEXTURE (displayed_cursor->texture));
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
@@ -626,16 +1043,15 @@ meta_cursor_tracker_set_crtc_has_hw_cursor (MetaCursorTracker *tracker,
 | 
			
		||||
  if (has)
 | 
			
		||||
    {
 | 
			
		||||
      MetaCursorReference *displayed_cursor = tracker->displayed_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 (displayed_cursor, &hot_x, &hot_y);
 | 
			
		||||
 | 
			
		||||
      handle = gbm_bo_get_handle (bo);
 | 
			
		||||
      width = gbm_bo_get_width (bo);
 | 
			
		||||
      height = gbm_bo_get_height (bo);
 | 
			
		||||
      handle = gbm_bo_get_handle (displayed_cursor->bo);
 | 
			
		||||
      width = gbm_bo_get_width (displayed_cursor->bo);
 | 
			
		||||
      height = gbm_bo_get_height (displayed_cursor->bo);
 | 
			
		||||
      hot_x = displayed_cursor->hot_x;
 | 
			
		||||
      hot_y = displayed_cursor->hot_y;
 | 
			
		||||
 | 
			
		||||
      drmModeSetCursor2 (tracker->drm_fd, crtc->crtc_id, handle.u32,
 | 
			
		||||
                         width, height, hot_x, hot_y);
 | 
			
		||||
@@ -658,13 +1074,12 @@ get_pointer_position_gdk (int         *x,
 | 
			
		||||
  GdkScreen *gscreen;
 | 
			
		||||
 | 
			
		||||
  gmanager = gdk_display_get_device_manager (gdk_display_get_default ());
 | 
			
		||||
  gdevice = gdk_x11_device_manager_lookup (gmanager, META_VIRTUAL_CORE_POINTER_ID);
 | 
			
		||||
  gdevice = gdk_device_manager_get_client_pointer (gmanager);
 | 
			
		||||
 | 
			
		||||
  gdk_device_get_position (gdevice, &gscreen, x, y);
 | 
			
		||||
  if (mods)
 | 
			
		||||
    gdk_device_get_state (gdevice,
 | 
			
		||||
                          gdk_screen_get_root_window (gscreen),
 | 
			
		||||
                          NULL, (GdkModifierType*)mods);
 | 
			
		||||
  gdk_device_get_state (gdevice,
 | 
			
		||||
                        gdk_screen_get_root_window (gscreen),
 | 
			
		||||
                        NULL, (GdkModifierType*)mods);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -680,12 +1095,9 @@ get_pointer_position_clutter (int         *x,
 | 
			
		||||
  cdevice = clutter_device_manager_get_core_device (cmanager, CLUTTER_POINTER_DEVICE);
 | 
			
		||||
 | 
			
		||||
  clutter_input_device_get_coords (cdevice, NULL, &point);
 | 
			
		||||
  if (x)
 | 
			
		||||
    *x = point.x;
 | 
			
		||||
  if (y)
 | 
			
		||||
    *y = point.y;
 | 
			
		||||
  if (mods)
 | 
			
		||||
    *mods = clutter_input_device_get_modifier_state (cdevice);
 | 
			
		||||
  *x = point.x;
 | 
			
		||||
  *y = point.y;
 | 
			
		||||
  *mods = clutter_input_device_get_modifier_state (cdevice);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -727,12 +1139,3 @@ meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker,
 | 
			
		||||
                          tracker->screen->xroot);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_cursor_tracker_force_update (MetaCursorTracker *tracker)
 | 
			
		||||
{
 | 
			
		||||
  g_assert (meta_is_wayland_compositor ());
 | 
			
		||||
 | 
			
		||||
  update_hw_cursor (tracker);
 | 
			
		||||
  sync_cursor (tracker);
 | 
			
		||||
}
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
/* -*- 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
 | 
			
		||||
@@ -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/>.
 | 
			
		||||
 *
 | 
			
		||||
@@ -20,9 +20,10 @@
 | 
			
		||||
 *         from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef META_IDLE_MONITOR_DBUS_H
 | 
			
		||||
#define META_IDLE_MONITOR_DBUS_H
 | 
			
		||||
#include <meta/meta-idle-monitor.h>
 | 
			
		||||
 | 
			
		||||
void meta_idle_monitor_handle_xevent_all (XEvent *xevent);
 | 
			
		||||
 | 
			
		||||
void meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor);
 | 
			
		||||
 | 
			
		||||
void meta_idle_monitor_init_dbus (void);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										994
									
								
								src/core/meta-idle-monitor.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										994
									
								
								src/core/meta-idle-monitor.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,994 @@
 | 
			
		||||
/* -*- 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 "display-private.h"
 | 
			
		||||
#include "meta-idle-monitor-private.h"
 | 
			
		||||
#include "meta-dbus-idle-monitor.h"
 | 
			
		||||
 | 
			
		||||
G_STATIC_ASSERT(sizeof(unsigned long) == sizeof(gpointer));
 | 
			
		||||
 | 
			
		||||
struct _MetaIdleMonitor
 | 
			
		||||
{
 | 
			
		||||
  GObject parent_instance;
 | 
			
		||||
 | 
			
		||||
  GHashTable  *watches;
 | 
			
		||||
  GHashTable  *alarms;
 | 
			
		||||
  int          device_id;
 | 
			
		||||
 | 
			
		||||
  /* X11 implementation */
 | 
			
		||||
  Display     *display;
 | 
			
		||||
  int          sync_event_base;
 | 
			
		||||
  XSyncCounter counter;
 | 
			
		||||
  XSyncAlarm   user_active_alarm;
 | 
			
		||||
 | 
			
		||||
  /* Wayland implementation */
 | 
			
		||||
  guint64      last_event_time;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaIdleMonitorClass
 | 
			
		||||
{
 | 
			
		||||
  GObjectClass parent_class;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitor          *monitor;
 | 
			
		||||
  guint	                    id;
 | 
			
		||||
  MetaIdleMonitorWatchFunc  callback;
 | 
			
		||||
  gpointer		    user_data;
 | 
			
		||||
  GDestroyNotify            notify;
 | 
			
		||||
  guint64                   timeout_msec;
 | 
			
		||||
 | 
			
		||||
  /* x11 */
 | 
			
		||||
  XSyncAlarm                xalarm;
 | 
			
		||||
  int                       idle_source_id;
 | 
			
		||||
 | 
			
		||||
  /* wayland */
 | 
			
		||||
  GSource                  *timeout_source;
 | 
			
		||||
} MetaIdleMonitorWatch;
 | 
			
		||||
 | 
			
		||||
enum
 | 
			
		||||
{
 | 
			
		||||
  PROP_0,
 | 
			
		||||
  PROP_DEVICE_ID,
 | 
			
		||||
  PROP_LAST,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static GParamSpec *obj_props[PROP_LAST];
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE (MetaIdleMonitor, meta_idle_monitor, G_TYPE_OBJECT)
 | 
			
		||||
 | 
			
		||||
static MetaIdleMonitor *device_monitors[256];
 | 
			
		||||
static int              device_id_max;
 | 
			
		||||
 | 
			
		||||
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 void
 | 
			
		||||
fire_watch (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 XSyncAlarm
 | 
			
		||||
_xsync_alarm_set (MetaIdleMonitor	*monitor,
 | 
			
		||||
		  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->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->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)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitorWatch *watch = data;
 | 
			
		||||
  XSyncAlarm alarm = (XSyncAlarm) user_data;
 | 
			
		||||
 | 
			
		||||
  if (watch->xalarm != alarm)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  fire_watch (watch);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_idle_monitor_handle_xevent (MetaIdleMonitor       *monitor,
 | 
			
		||||
                                 XSyncAlarmNotifyEvent *alarm_event)
 | 
			
		||||
{
 | 
			
		||||
  XSyncAlarm alarm;
 | 
			
		||||
  GList *watches;
 | 
			
		||||
  gboolean has_alarm;
 | 
			
		||||
 | 
			
		||||
  if (alarm_event->state != XSyncAlarmActive)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  alarm = alarm_event->alarm;
 | 
			
		||||
 | 
			
		||||
  has_alarm = FALSE;
 | 
			
		||||
 | 
			
		||||
  if (alarm == monitor->user_active_alarm)
 | 
			
		||||
    {
 | 
			
		||||
      set_alarm_enabled (monitor->display,
 | 
			
		||||
                         alarm,
 | 
			
		||||
                         FALSE);
 | 
			
		||||
      has_alarm = TRUE;
 | 
			
		||||
    }
 | 
			
		||||
  else if (g_hash_table_contains (monitor->alarms, (gpointer) alarm))
 | 
			
		||||
    {
 | 
			
		||||
      ensure_alarm_rescheduled (monitor->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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_idle_monitor_handle_xevent_all (XEvent *xevent)
 | 
			
		||||
{
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i <= device_id_max; i++)
 | 
			
		||||
    if (device_monitors[i])
 | 
			
		||||
      meta_idle_monitor_handle_xevent (device_monitors[i], (XSyncAlarmNotifyEvent*)xevent);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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 (MetaIdleMonitor *monitor)
 | 
			
		||||
{
 | 
			
		||||
  int		      i;
 | 
			
		||||
  int		      ncounters;
 | 
			
		||||
  XSyncSystemCounter *counters;
 | 
			
		||||
  XSyncCounter        counter = None;
 | 
			
		||||
  char               *counter_name;
 | 
			
		||||
 | 
			
		||||
  counter_name = counter_name_for_device (monitor->device_id);
 | 
			
		||||
  counters = XSyncListSystemCounters (monitor->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 guint32
 | 
			
		||||
get_next_watch_serial (void)
 | 
			
		||||
{
 | 
			
		||||
  static guint32 serial = 0;
 | 
			
		||||
  g_atomic_int_inc (&serial);
 | 
			
		||||
  return serial;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
idle_monitor_watch_free (MetaIdleMonitorWatch *watch)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitor *monitor;
 | 
			
		||||
 | 
			
		||||
  if (watch == NULL)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  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->xalarm != monitor->user_active_alarm &&
 | 
			
		||||
      watch->xalarm != None)
 | 
			
		||||
    {
 | 
			
		||||
      XSyncDestroyAlarm (monitor->display, watch->xalarm);
 | 
			
		||||
      g_hash_table_remove (monitor->alarms, (gpointer) watch->xalarm);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (watch->timeout_source != NULL)
 | 
			
		||||
    g_source_destroy (watch->timeout_source);
 | 
			
		||||
 | 
			
		||||
  g_object_unref (monitor);
 | 
			
		||||
  g_slice_free (MetaIdleMonitorWatch, watch);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
init_xsync (MetaIdleMonitor *monitor)
 | 
			
		||||
{
 | 
			
		||||
  monitor->counter = find_idletime_counter (monitor);
 | 
			
		||||
  /* IDLETIME counter not found? */
 | 
			
		||||
  if (monitor->counter == None)
 | 
			
		||||
    {
 | 
			
		||||
      meta_warning ("IDLETIME counter not found\n");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  monitor->user_active_alarm = _xsync_alarm_set (monitor, XSyncNegativeTransition, 1, FALSE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_idle_monitor_dispose (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitor *monitor;
 | 
			
		||||
 | 
			
		||||
  monitor = META_IDLE_MONITOR (object);
 | 
			
		||||
 | 
			
		||||
  g_clear_pointer (&monitor->watches, g_hash_table_destroy);
 | 
			
		||||
  g_clear_pointer (&monitor->alarms, g_hash_table_destroy);
 | 
			
		||||
 | 
			
		||||
  if (monitor->user_active_alarm != None)
 | 
			
		||||
    {
 | 
			
		||||
      XSyncDestroyAlarm (monitor->display, monitor->user_active_alarm);
 | 
			
		||||
      monitor->user_active_alarm = None;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  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_constructed (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
 | 
			
		||||
 | 
			
		||||
  if (!meta_is_wayland_compositor ())
 | 
			
		||||
    {
 | 
			
		||||
      monitor->display = meta_get_display ()->xdisplay;
 | 
			
		||||
      init_xsync (monitor);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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->constructed = meta_idle_monitor_constructed;
 | 
			
		||||
  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)
 | 
			
		||||
{
 | 
			
		||||
  monitor->watches = g_hash_table_new_full (NULL,
 | 
			
		||||
                                                  NULL,
 | 
			
		||||
                                                  NULL,
 | 
			
		||||
                                                  (GDestroyNotify)idle_monitor_watch_free);
 | 
			
		||||
 | 
			
		||||
  monitor->alarms = g_hash_table_new (NULL, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
ensure_device_monitor (int device_id)
 | 
			
		||||
{
 | 
			
		||||
  if (device_monitors[device_id])
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  device_monitors[device_id] = g_object_new (META_TYPE_IDLE_MONITOR, "device-id", device_id, NULL);
 | 
			
		||||
  device_id_max = MAX (device_id_max, device_id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 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)
 | 
			
		||||
{
 | 
			
		||||
  ensure_device_monitor (0);
 | 
			
		||||
  return device_monitors[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)
 | 
			
		||||
{
 | 
			
		||||
  g_return_val_if_fail (device_id > 0 && device_id < 256, NULL);
 | 
			
		||||
 | 
			
		||||
  ensure_device_monitor (device_id);
 | 
			
		||||
  return device_monitors[device_id];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
wayland_dispatch_timeout (GSource     *source,
 | 
			
		||||
                          GSourceFunc  callback,
 | 
			
		||||
                          gpointer     user_data)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitorWatch *watch = user_data;
 | 
			
		||||
 | 
			
		||||
  fire_watch (watch);
 | 
			
		||||
  g_source_set_ready_time (watch->timeout_source, -1);
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GSourceFuncs wayland_source_funcs = {
 | 
			
		||||
  NULL, /* prepare */
 | 
			
		||||
  NULL, /* check */
 | 
			
		||||
  wayland_dispatch_timeout,
 | 
			
		||||
  NULL, /* finalize */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
fire_watch_idle (gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitorWatch *watch = data;
 | 
			
		||||
 | 
			
		||||
  watch->idle_source_id = 0;
 | 
			
		||||
  fire_watch (watch);
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaIdleMonitorWatch *
 | 
			
		||||
make_watch (MetaIdleMonitor           *monitor,
 | 
			
		||||
            guint64                    timeout_msec,
 | 
			
		||||
	    MetaIdleMonitorWatchFunc   callback,
 | 
			
		||||
	    gpointer                   user_data,
 | 
			
		||||
	    GDestroyNotify             notify)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitorWatch *watch;
 | 
			
		||||
 | 
			
		||||
  watch = g_slice_new0 (MetaIdleMonitorWatch);
 | 
			
		||||
  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 (meta_is_wayland_compositor ())
 | 
			
		||||
    {
 | 
			
		||||
      if (timeout_msec != 0)
 | 
			
		||||
        {
 | 
			
		||||
          GSource *source = g_source_new (&wayland_source_funcs, sizeof (GSource));
 | 
			
		||||
 | 
			
		||||
          g_source_set_callback (source, NULL, watch, NULL);
 | 
			
		||||
          g_source_set_ready_time (source, monitor->last_event_time + timeout_msec * 1000);
 | 
			
		||||
          g_source_attach (source, NULL);
 | 
			
		||||
          g_source_unref (source);
 | 
			
		||||
 | 
			
		||||
          watch->timeout_source = source;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  else if (monitor->user_active_alarm != None)
 | 
			
		||||
    {
 | 
			
		||||
      if (timeout_msec != 0)
 | 
			
		||||
        {
 | 
			
		||||
          watch->xalarm = _xsync_alarm_set (monitor, XSyncPositiveTransition, timeout_msec, TRUE);
 | 
			
		||||
 | 
			
		||||
          g_hash_table_add (monitor->alarms, (gpointer) watch->xalarm);
 | 
			
		||||
 | 
			
		||||
          if (meta_idle_monitor_get_idletime (monitor) > (gint64)timeout_msec)
 | 
			
		||||
            watch->idle_source_id = g_idle_add (fire_watch_idle, watch);
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          watch->xalarm = monitor->user_active_alarm;
 | 
			
		||||
 | 
			
		||||
          set_alarm_enabled (monitor->display, monitor->user_active_alarm, TRUE);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  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: (allow-none): The callback to call when the user has
 | 
			
		||||
 *     accumulated @interval_msec milliseconds of idle time.
 | 
			
		||||
 * @user_data: (allow-none): 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: (allow-none): The callback to call when the user is
 | 
			
		||||
 *     active again.
 | 
			
		||||
 * @user_data: (allow-none): 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_hash_table_remove (monitor->watches,
 | 
			
		||||
                       GUINT_TO_POINTER (id));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 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)
 | 
			
		||||
{
 | 
			
		||||
  XSyncValue value;
 | 
			
		||||
 | 
			
		||||
  if (meta_is_wayland_compositor ())
 | 
			
		||||
    {
 | 
			
		||||
      return (g_get_monotonic_time () - monitor->last_event_time) / 1000;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      if (!XSyncQueryCounter (monitor->display, monitor->counter, &value))
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
      return _xsyncvalue_to_int64 (value);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  MetaIdleMonitor *monitor;
 | 
			
		||||
  GList *fired_watches;
 | 
			
		||||
} CheckWaylandClosure;
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
check_wayland_watch (gpointer key,
 | 
			
		||||
                     gpointer value,
 | 
			
		||||
                     gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitorWatch *watch = value;
 | 
			
		||||
  CheckWaylandClosure *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->timeout_source,
 | 
			
		||||
                               closure->monitor->last_event_time +
 | 
			
		||||
                               watch->timeout_msec * 1000);
 | 
			
		||||
      steal = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return steal;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
fire_wayland_watch (gpointer watch,
 | 
			
		||||
                    gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  fire_watch (watch);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor)
 | 
			
		||||
{
 | 
			
		||||
  CheckWaylandClosure closure;
 | 
			
		||||
 | 
			
		||||
  monitor->last_event_time = g_get_monotonic_time ();
 | 
			
		||||
 | 
			
		||||
  closure.monitor = monitor;
 | 
			
		||||
  closure.fired_watches = NULL;
 | 
			
		||||
  g_hash_table_foreach_steal (monitor->watches, check_wayland_watch, &closure);
 | 
			
		||||
 | 
			
		||||
  g_list_foreach (closure.fired_watches, fire_wayland_watch, NULL);
 | 
			
		||||
  g_list_free (closure.fired_watches);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
 | 
			
		||||
  g_clear_object (&device_monitors[device_id]);
 | 
			
		||||
  if (device_id == device_id_max)
 | 
			
		||||
    device_id_max--;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -16,7 +16,7 @@
 | 
			
		||||
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* This file is shared between mutter (src/core/meta-display-config-shared.h)
 | 
			
		||||
/* This file is shared between mutter (src/core/meta-xrandr-shared.h)
 | 
			
		||||
   and gnome-desktop (libgnome-desktop/meta-xrandr-shared.h).
 | 
			
		||||
 | 
			
		||||
   The canonical place for all changes is mutter.
 | 
			
		||||
@@ -24,8 +24,8 @@
 | 
			
		||||
   There should be no includes in this file.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef META_DISPLAY_CONFIG_SHARED_H
 | 
			
		||||
#define META_DISPLAY_CONFIG_SHARED_H
 | 
			
		||||
#ifndef META_XRANDR_SHARED_H
 | 
			
		||||
#define META_XRANDR_SHARED_H
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
  META_POWER_SAVE_UNSUPPORTED = -1,
 | 
			
		||||
@@ -35,4 +35,4 @@ typedef enum {
 | 
			
		||||
  META_POWER_SAVE_OFF,
 | 
			
		||||
} MetaPowerSave;
 | 
			
		||||
 | 
			
		||||
#endif /* META_DISPLAY_CONFIG_SHARED_H */
 | 
			
		||||
#endif
 | 
			
		||||
@@ -34,14 +34,13 @@
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include "meta-monitor-config.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
#include <libupower-glib/upower.h>
 | 
			
		||||
 | 
			
		||||
#include <meta/main.h>
 | 
			
		||||
#include <meta/errors.h>
 | 
			
		||||
#include "monitor-private.h"
 | 
			
		||||
 | 
			
		||||
/* These structures represent the intended/persistent configuration,
 | 
			
		||||
   as stored in the monitors.xml file.
 | 
			
		||||
@@ -23,8 +23,6 @@
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include "meta-monitor-manager-kms.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
@@ -38,6 +36,7 @@
 | 
			
		||||
 | 
			
		||||
#include <meta/main.h>
 | 
			
		||||
#include <meta/errors.h>
 | 
			
		||||
#include "monitor-private.h"
 | 
			
		||||
#include "edid.h"
 | 
			
		||||
 | 
			
		||||
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
 | 
			
		||||
@@ -651,7 +650,7 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
 | 
			
		||||
    state = DRM_MODE_DPMS_SUSPEND;
 | 
			
		||||
    break;
 | 
			
		||||
  case META_POWER_SAVE_OFF:
 | 
			
		||||
    state = DRM_MODE_DPMS_OFF;
 | 
			
		||||
    state = DRM_MODE_DPMS_SUSPEND;
 | 
			
		||||
    break;
 | 
			
		||||
  default:
 | 
			
		||||
    return;
 | 
			
		||||
@@ -43,9 +43,9 @@
 | 
			
		||||
#include "stack-tracker.h"
 | 
			
		||||
#include "ui.h"
 | 
			
		||||
#include <wayland-server.h>
 | 
			
		||||
#include "meta-xrandr-shared.h"
 | 
			
		||||
 | 
			
		||||
#include "meta-display-config-shared.h"
 | 
			
		||||
#include "meta-dbus-display-config.h"
 | 
			
		||||
#include "meta-dbus-xrandr.h"
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaMonitorManagerClass    MetaMonitorManagerClass;
 | 
			
		||||
typedef struct _MetaMonitorManager         MetaMonitorManager;
 | 
			
		||||
@@ -227,6 +227,8 @@ struct _MetaMonitorManager
 | 
			
		||||
     CRTCs refer to stuff that can drive outputs
 | 
			
		||||
     (like encoders, but less tied to the HW),
 | 
			
		||||
     while monitor_infos refer to logical ones.
 | 
			
		||||
 | 
			
		||||
     See also the comment in monitor-private.h
 | 
			
		||||
  */
 | 
			
		||||
  MetaOutput *outputs;
 | 
			
		||||
  unsigned int n_outputs;
 | 
			
		||||
@@ -333,6 +335,57 @@ void                meta_monitor_manager_apply_configuration (MetaMonitorManager
 | 
			
		||||
void                meta_monitor_manager_confirm_configuration (MetaMonitorManager *manager,
 | 
			
		||||
                                                                gboolean            ok);
 | 
			
		||||
 | 
			
		||||
#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);
 | 
			
		||||
 | 
			
		||||
#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);
 | 
			
		||||
 | 
			
		||||
#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);
 | 
			
		||||
 | 
			
		||||
void               meta_crtc_info_free   (MetaCRTCInfo   *info);
 | 
			
		||||
void               meta_output_info_free (MetaOutputInfo *info);
 | 
			
		||||
 | 
			
		||||
@@ -25,8 +25,6 @@
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include "meta-monitor-manager-xrandr.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
@@ -38,8 +36,9 @@
 | 
			
		||||
 | 
			
		||||
#include <meta/main.h>
 | 
			
		||||
#include <meta/errors.h>
 | 
			
		||||
#include "monitor-private.h"
 | 
			
		||||
 | 
			
		||||
#include "edid.h"
 | 
			
		||||
#include "meta-monitor-config.h"
 | 
			
		||||
 | 
			
		||||
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
 | 
			
		||||
 | 
			
		||||
@@ -25,8 +25,6 @@
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include "meta-monitor-manager.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
@@ -35,10 +33,12 @@
 | 
			
		||||
#include <meta/main.h>
 | 
			
		||||
#include "util-private.h"
 | 
			
		||||
#include <meta/errors.h>
 | 
			
		||||
#include "meta-monitor-config.h"
 | 
			
		||||
#include "backends/native/meta-monitor-manager-kms.h"
 | 
			
		||||
#include "backends/x11/meta-monitor-manager-xrandr.h"
 | 
			
		||||
#include "meta-monitor-manager-dummy.h"
 | 
			
		||||
#include "monitor-private.h"
 | 
			
		||||
#include "meta-wayland-private.h"
 | 
			
		||||
 | 
			
		||||
#include "meta-dbus-xrandr.h"
 | 
			
		||||
 | 
			
		||||
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
  CONFIRM_DISPLAY_CHANGE,
 | 
			
		||||
@@ -55,11 +55,196 @@ static int signals[SIGNALS_LAST];
 | 
			
		||||
 | 
			
		||||
static void meta_monitor_manager_display_config_init (MetaDBusDisplayConfigIface *iface);
 | 
			
		||||
 | 
			
		||||
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaMonitorManager, meta_monitor_manager, META_DBUS_TYPE_DISPLAY_CONFIG_SKELETON,
 | 
			
		||||
                                  G_IMPLEMENT_INTERFACE (META_DBUS_TYPE_DISPLAY_CONFIG, meta_monitor_manager_display_config_init));
 | 
			
		||||
G_DEFINE_TYPE_WITH_CODE (MetaMonitorManager, meta_monitor_manager, META_DBUS_TYPE_DISPLAY_CONFIG_SKELETON,
 | 
			
		||||
                         G_IMPLEMENT_INTERFACE (META_DBUS_TYPE_DISPLAY_CONFIG, meta_monitor_manager_display_config_init));
 | 
			
		||||
 | 
			
		||||
static void initialize_dbus_interface (MetaMonitorManager *manager);
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
read_current_dummy (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
 | 
			
		||||
apply_config_dummy (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 GBytes *
 | 
			
		||||
read_edid_dummy (MetaMonitorManager *manager,
 | 
			
		||||
                 MetaOutput         *output)
 | 
			
		||||
{
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char *
 | 
			
		||||
get_edid_file_dummy (MetaMonitorManager *manager,
 | 
			
		||||
                     MetaOutput         *output)
 | 
			
		||||
{
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_init (MetaMonitorManager *manager)
 | 
			
		||||
{
 | 
			
		||||
@@ -183,7 +368,7 @@ get_default_backend (void)
 | 
			
		||||
       * we're a nested configuration, so return the dummy
 | 
			
		||||
       * monitor setup. */
 | 
			
		||||
      if (meta_is_wayland_compositor ())
 | 
			
		||||
        return META_TYPE_MONITOR_MANAGER_DUMMY;
 | 
			
		||||
        return META_TYPE_MONITOR_MANAGER;
 | 
			
		||||
      else
 | 
			
		||||
        return META_TYPE_MONITOR_MANAGER_XRANDR;
 | 
			
		||||
    }
 | 
			
		||||
@@ -195,7 +380,7 @@ get_default_backend (void)
 | 
			
		||||
      /* Use the dummy implementation on Wayland for now.
 | 
			
		||||
       * In the future, we should support wl_fullscreen_output
 | 
			
		||||
       * which will have CRTC management in the protocol. */
 | 
			
		||||
      return META_TYPE_MONITOR_MANAGER_DUMMY;
 | 
			
		||||
      return META_TYPE_MONITOR_MANAGER;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@@ -389,20 +574,6 @@ meta_monitor_manager_get_property (GObject      *object,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GBytes *
 | 
			
		||||
meta_monitor_manager_real_read_edid (MetaMonitorManager *manager,
 | 
			
		||||
                                     MetaOutput         *output)
 | 
			
		||||
{
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char *
 | 
			
		||||
meta_monitor_manager_real_get_edid_file (MetaMonitorManager *manager,
 | 
			
		||||
                                         MetaOutput         *output)
 | 
			
		||||
{
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_class_init (MetaMonitorManagerClass *klass)
 | 
			
		||||
{
 | 
			
		||||
@@ -414,8 +585,10 @@ meta_monitor_manager_class_init (MetaMonitorManagerClass *klass)
 | 
			
		||||
  object_class->dispose = meta_monitor_manager_dispose;
 | 
			
		||||
  object_class->finalize = meta_monitor_manager_finalize;
 | 
			
		||||
 | 
			
		||||
  klass->get_edid_file = meta_monitor_manager_real_get_edid_file;
 | 
			
		||||
  klass->read_edid = meta_monitor_manager_real_read_edid;
 | 
			
		||||
  klass->read_current = read_current_dummy;
 | 
			
		||||
  klass->apply_configuration = apply_config_dummy;
 | 
			
		||||
  klass->get_edid_file = get_edid_file_dummy;
 | 
			
		||||
  klass->read_edid = read_edid_dummy;
 | 
			
		||||
 | 
			
		||||
  signals[CONFIRM_DISPLAY_CHANGE] =
 | 
			
		||||
    g_signal_new ("confirm-display-change",
 | 
			
		||||
@@ -344,7 +344,7 @@ avoid_being_obscured_as_second_modal_dialog (MetaWindow *window,
 | 
			
		||||
  /* denied_focus_and_not_transient is only set when focus_window != NULL */
 | 
			
		||||
 | 
			
		||||
  if (window->denied_focus_and_not_transient &&
 | 
			
		||||
      window->type == META_WINDOW_MODAL_DIALOG &&
 | 
			
		||||
      window->wm_state_modal && /* FIXME: Maybe do this for all transients? */
 | 
			
		||||
      meta_window_same_application (window, focus_window) &&
 | 
			
		||||
      window_overlaps_focus_window (window))
 | 
			
		||||
    {
 | 
			
		||||
@@ -610,7 +610,7 @@ meta_window_place (MetaWindow        *window,
 | 
			
		||||
  meta_topic (META_DEBUG_PLACEMENT, "Placing window %s\n", window->desc);
 | 
			
		||||
 | 
			
		||||
  windows = NULL;
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
  switch (window->type)
 | 
			
		||||
    {
 | 
			
		||||
      /* Run placement algorithm on these. */
 | 
			
		||||
@@ -638,7 +638,7 @@ meta_window_place (MetaWindow        *window,
 | 
			
		||||
    case META_WINDOW_OVERRIDE_OTHER:
 | 
			
		||||
      goto done_no_constraints;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
  if (meta_prefs_get_disable_workarounds ())
 | 
			
		||||
    {
 | 
			
		||||
      switch (window->type)
 | 
			
		||||
@@ -699,11 +699,18 @@ meta_window_place (MetaWindow        *window,
 | 
			
		||||
          goto done_no_constraints;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (window->type == META_WINDOW_DIALOG ||
 | 
			
		||||
      window->type == META_WINDOW_MODAL_DIALOG)
 | 
			
		||||
  
 | 
			
		||||
  if ((window->type == META_WINDOW_DIALOG ||
 | 
			
		||||
       window->type == META_WINDOW_MODAL_DIALOG) &&
 | 
			
		||||
      window->xtransient_for != None)
 | 
			
		||||
    {
 | 
			
		||||
      MetaWindow *parent = meta_window_get_transient_for (window);
 | 
			
		||||
      /* Center horizontally, at top of parent vertically */
 | 
			
		||||
 | 
			
		||||
      MetaWindow *parent;
 | 
			
		||||
          
 | 
			
		||||
      parent =
 | 
			
		||||
        meta_display_lookup_x_window (window->display,
 | 
			
		||||
                                      window->xtransient_for);
 | 
			
		||||
 | 
			
		||||
      if (parent)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -57,6 +57,7 @@
 | 
			
		||||
 | 
			
		||||
#define KEY_OVERLAY_KEY "overlay-key"
 | 
			
		||||
#define KEY_WORKSPACES_ONLY_ON_PRIMARY "workspaces-only-on-primary"
 | 
			
		||||
#define KEY_NO_TAB_POPUP "no-tab-popup"
 | 
			
		||||
 | 
			
		||||
/* These are the different schemas we are keeping
 | 
			
		||||
 * a GSettings instance for */
 | 
			
		||||
@@ -111,6 +112,8 @@ static char **workspace_names = NULL;
 | 
			
		||||
 | 
			
		||||
static gboolean workspaces_only_on_primary = FALSE;
 | 
			
		||||
 | 
			
		||||
static gboolean no_tab_popup = FALSE;
 | 
			
		||||
 | 
			
		||||
static char *iso_next_group_option = NULL;
 | 
			
		||||
 | 
			
		||||
static void handle_preference_update_enum (GSettings *settings,
 | 
			
		||||
@@ -362,6 +365,13 @@ static MetaBoolPreference preferences_bool[] =
 | 
			
		||||
      },
 | 
			
		||||
      &workspaces_only_on_primary,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      { KEY_NO_TAB_POPUP,
 | 
			
		||||
        SCHEMA_MUTTER,
 | 
			
		||||
        META_PREF_NO_TAB_POPUP,
 | 
			
		||||
      },
 | 
			
		||||
      &no_tab_popup,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      { "auto-maximize",
 | 
			
		||||
        SCHEMA_MUTTER,
 | 
			
		||||
@@ -1803,6 +1813,9 @@ meta_preference_to_string (MetaPreference pref)
 | 
			
		||||
    case META_PREF_WORKSPACES_ONLY_ON_PRIMARY:
 | 
			
		||||
      return "WORKSPACES_ONLY_ON_PRIMARY";
 | 
			
		||||
 | 
			
		||||
    case META_PREF_NO_TAB_POPUP:
 | 
			
		||||
      return "NO_TAB_POPUP";
 | 
			
		||||
 | 
			
		||||
    case META_PREF_DRAGGABLE_BORDER_WIDTH:
 | 
			
		||||
      return "DRAGGABLE_BORDER_WIDTH";
 | 
			
		||||
 | 
			
		||||
@@ -1856,7 +1869,7 @@ init_bindings (void)
 | 
			
		||||
  pref = g_new0 (MetaKeyPref, 1);
 | 
			
		||||
  pref->name = g_strdup ("overlay-key");
 | 
			
		||||
  pref->action = META_KEYBINDING_ACTION_OVERLAY_KEY;
 | 
			
		||||
  pref->combos = g_slist_prepend (pref->combos, &overlay_key_combo);
 | 
			
		||||
  pref->bindings = g_slist_prepend (pref->bindings, &overlay_key_combo);
 | 
			
		||||
  pref->builtin = 1;
 | 
			
		||||
 | 
			
		||||
  g_hash_table_insert (key_bindings, g_strdup ("overlay-key"), pref);
 | 
			
		||||
@@ -1866,7 +1879,7 @@ static gboolean
 | 
			
		||||
update_binding (MetaKeyPref *binding,
 | 
			
		||||
                gchar      **strokes)
 | 
			
		||||
{
 | 
			
		||||
  GSList *old_combos, *a, *b;
 | 
			
		||||
  GSList *old_bindings, *a, *b;
 | 
			
		||||
  gboolean changed;
 | 
			
		||||
  unsigned int keysym;
 | 
			
		||||
  unsigned int keycode;
 | 
			
		||||
@@ -1878,8 +1891,8 @@ update_binding (MetaKeyPref *binding,
 | 
			
		||||
              "Binding \"%s\" has new GSettings value\n",
 | 
			
		||||
              binding->name);
 | 
			
		||||
 | 
			
		||||
  old_combos = binding->combos;
 | 
			
		||||
  binding->combos = NULL;
 | 
			
		||||
  old_bindings = binding->bindings;
 | 
			
		||||
  binding->bindings = NULL;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; strokes && strokes[i]; i++)
 | 
			
		||||
    {
 | 
			
		||||
@@ -1920,17 +1933,17 @@ update_binding (MetaKeyPref *binding,
 | 
			
		||||
      combo->keysym = keysym;
 | 
			
		||||
      combo->keycode = keycode;
 | 
			
		||||
      combo->modifiers = mods;
 | 
			
		||||
      binding->combos = g_slist_prepend (binding->combos, combo);
 | 
			
		||||
      binding->bindings = g_slist_prepend (binding->bindings, combo);
 | 
			
		||||
 | 
			
		||||
      meta_topic (META_DEBUG_KEYBINDINGS,
 | 
			
		||||
                      "New keybinding for \"%s\" is keysym = 0x%x keycode = 0x%x mods = 0x%x\n",
 | 
			
		||||
                      binding->name, keysym, keycode, mods);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  binding->combos = g_slist_reverse (binding->combos);
 | 
			
		||||
  binding->bindings = g_slist_reverse (binding->bindings);
 | 
			
		||||
 | 
			
		||||
  a = old_combos;
 | 
			
		||||
  b = binding->combos;
 | 
			
		||||
  a = old_bindings;
 | 
			
		||||
  b = binding->bindings;
 | 
			
		||||
  while (TRUE)
 | 
			
		||||
    {
 | 
			
		||||
      if ((!a && b) || (a && !b))
 | 
			
		||||
@@ -1955,7 +1968,7 @@ update_binding (MetaKeyPref *binding,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_slist_free_full (old_combos, g_free);
 | 
			
		||||
  g_slist_free_full (old_bindings, g_free);
 | 
			
		||||
 | 
			
		||||
  return changed;
 | 
			
		||||
}
 | 
			
		||||
@@ -2090,7 +2103,7 @@ meta_prefs_add_keybinding (const char           *name,
 | 
			
		||||
  pref->name = g_strdup (name);
 | 
			
		||||
  pref->settings = g_object_ref (settings);
 | 
			
		||||
  pref->action = action;
 | 
			
		||||
  pref->combos = NULL;
 | 
			
		||||
  pref->bindings = NULL;
 | 
			
		||||
  pref->add_shift = (flags & META_KEY_BINDING_REVERSES) != 0;
 | 
			
		||||
  pref->per_window = (flags & META_KEY_BINDING_PER_WINDOW) != 0;
 | 
			
		||||
  pref->builtin = (flags & META_KEY_BINDING_BUILTIN) != 0;
 | 
			
		||||
@@ -2154,6 +2167,11 @@ meta_prefs_remove_keybinding (const char *name)
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_prefs_get_keybindings:
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: (element-type MetaKeyPref) (transfer container):
 | 
			
		||||
 */
 | 
			
		||||
GList *
 | 
			
		||||
meta_prefs_get_keybindings ()
 | 
			
		||||
{
 | 
			
		||||
@@ -2254,7 +2272,7 @@ meta_prefs_get_window_binding (const char          *name,
 | 
			
		||||
 | 
			
		||||
  if (pref->per_window)
 | 
			
		||||
    {
 | 
			
		||||
      GSList *s = pref->combos;
 | 
			
		||||
      GSList *s = pref->bindings;
 | 
			
		||||
 | 
			
		||||
      while (s)
 | 
			
		||||
        {
 | 
			
		||||
@@ -2302,6 +2320,25 @@ meta_prefs_get_workspaces_only_on_primary (void)
 | 
			
		||||
  return workspaces_only_on_primary;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_prefs_get_no_tab_popup (void)
 | 
			
		||||
{
 | 
			
		||||
  return no_tab_popup;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_prefs_set_no_tab_popup (gboolean whether)
 | 
			
		||||
{
 | 
			
		||||
  MetaBasePreference *pref;
 | 
			
		||||
 | 
			
		||||
  if (find_pref (preferences_bool, sizeof(MetaBoolPreference),
 | 
			
		||||
                 KEY_NO_TAB_POPUP, &pref))
 | 
			
		||||
    {
 | 
			
		||||
      g_settings_set_boolean (SETTINGS (pref->schema), KEY_NO_TAB_POPUP, whether);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
meta_prefs_get_draggable_border_width (void)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -36,7 +36,7 @@
 | 
			
		||||
#include <X11/Xutil.h>
 | 
			
		||||
#include "stack-tracker.h"
 | 
			
		||||
#include "ui.h"
 | 
			
		||||
#include "meta-monitor-manager.h"
 | 
			
		||||
#include "monitor-private.h"
 | 
			
		||||
 | 
			
		||||
typedef void (* MetaScreenWindowFunc) (MetaScreen *screen, MetaWindow *window,
 | 
			
		||||
                                       gpointer user_data);
 | 
			
		||||
@@ -64,6 +64,8 @@ struct _MetaScreen
 | 
			
		||||
  Visual *default_xvisual;
 | 
			
		||||
  MetaRectangle rect;  /* Size of screen; rect.x & rect.y are always 0 */
 | 
			
		||||
  MetaUI *ui;
 | 
			
		||||
  MetaTabPopup *tab_popup, *ws_popup;
 | 
			
		||||
  MetaTilePreview *tile_preview;
 | 
			
		||||
 | 
			
		||||
  guint tile_preview_timeout_id;
 | 
			
		||||
 | 
			
		||||
@@ -82,6 +84,8 @@ struct _MetaScreen
 | 
			
		||||
  MetaCursorTracker *cursor_tracker;
 | 
			
		||||
  MetaCursor current_cursor;
 | 
			
		||||
 | 
			
		||||
  Window flash_window;
 | 
			
		||||
 | 
			
		||||
  Window wm_sn_selection_window;
 | 
			
		||||
  Atom wm_sn_atom;
 | 
			
		||||
  guint32 wm_sn_timestamp;
 | 
			
		||||
@@ -116,6 +120,9 @@ struct _MetaScreen
 | 
			
		||||
  guint all_keys_grabbed : 1;
 | 
			
		||||
  
 | 
			
		||||
  int closing;
 | 
			
		||||
 | 
			
		||||
  /* Managed by compositor.c */
 | 
			
		||||
  gpointer compositor_data;
 | 
			
		||||
  
 | 
			
		||||
  /* Instead of unmapping withdrawn windows we can leave them mapped
 | 
			
		||||
   * and restack them below a guard window. When using a compositor
 | 
			
		||||
@@ -144,9 +151,25 @@ void          meta_screen_foreach_window      (MetaScreen                 *scree
 | 
			
		||||
 | 
			
		||||
void          meta_screen_update_cursor       (MetaScreen                 *screen);
 | 
			
		||||
 | 
			
		||||
void          meta_screen_update_tile_preview          (MetaScreen    *screen,
 | 
			
		||||
void          meta_screen_tab_popup_create       (MetaScreen              *screen,
 | 
			
		||||
                                                  MetaTabList              list_type,
 | 
			
		||||
                                                  MetaTabShowType          show_type,
 | 
			
		||||
                                                  MetaWindow              *initial_window);
 | 
			
		||||
void          meta_screen_tab_popup_forward      (MetaScreen              *screen);
 | 
			
		||||
void          meta_screen_tab_popup_backward     (MetaScreen              *screen);
 | 
			
		||||
MetaWindow*   meta_screen_tab_popup_get_selected (MetaScreen              *screen);
 | 
			
		||||
void          meta_screen_tab_popup_destroy      (MetaScreen              *screen);
 | 
			
		||||
 | 
			
		||||
void          meta_screen_workspace_popup_create       (MetaScreen    *screen,
 | 
			
		||||
                                                        MetaWorkspace *initial_selection);
 | 
			
		||||
void          meta_screen_workspace_popup_select       (MetaScreen    *screen,
 | 
			
		||||
                                                        MetaWorkspace *workspace);
 | 
			
		||||
MetaWorkspace*meta_screen_workspace_popup_get_selected (MetaScreen    *screen);
 | 
			
		||||
void          meta_screen_workspace_popup_destroy      (MetaScreen    *screen);
 | 
			
		||||
 | 
			
		||||
void          meta_screen_tile_preview_update          (MetaScreen    *screen,
 | 
			
		||||
                                                        gboolean       delay);
 | 
			
		||||
void          meta_screen_hide_tile_preview            (MetaScreen    *screen);
 | 
			
		||||
void          meta_screen_tile_preview_hide            (MetaScreen    *screen);
 | 
			
		||||
 | 
			
		||||
MetaWindow*   meta_screen_get_mouse_window     (MetaScreen                 *screen,
 | 
			
		||||
                                                MetaWindow                 *not_this_one);
 | 
			
		||||
 
 | 
			
		||||
@@ -39,9 +39,11 @@
 | 
			
		||||
#include "workspace-private.h"
 | 
			
		||||
#include "keybindings-private.h"
 | 
			
		||||
#include "stack.h"
 | 
			
		||||
#include "xprops.h"
 | 
			
		||||
#include <meta/compositor.h>
 | 
			
		||||
#include "mutter-enum-types.h"
 | 
			
		||||
#include "core.h"
 | 
			
		||||
#include "meta-wayland-private.h"
 | 
			
		||||
#include "meta-cursor-tracker-private.h"
 | 
			
		||||
 | 
			
		||||
#include <X11/extensions/Xinerama.h>
 | 
			
		||||
@@ -52,8 +54,6 @@
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
#include "x11/xprops.h"
 | 
			
		||||
 | 
			
		||||
static char* get_screen_name (MetaDisplay *display,
 | 
			
		||||
                              int          number);
 | 
			
		||||
 | 
			
		||||
@@ -308,8 +308,6 @@ set_supported_hint (MetaScreen *screen)
 | 
			
		||||
#include <meta/atomnames.h>
 | 
			
		||||
#undef item
 | 
			
		||||
#undef EWMH_ATOMS_ONLY
 | 
			
		||||
 | 
			
		||||
    screen->display->atom__GTK_FRAME_EXTENTS,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  XChangeProperty (screen->display->xdisplay, screen->xroot,
 | 
			
		||||
@@ -560,7 +558,7 @@ meta_screen_new (MetaDisplay *display,
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      /* We want to find out when the current selection owner dies */
 | 
			
		||||
      meta_error_trap_push (display);
 | 
			
		||||
      meta_error_trap_push_with_return (display);
 | 
			
		||||
      attrs.event_mask = StructureNotifyMask;
 | 
			
		||||
      XChangeWindowAttributes (xdisplay,
 | 
			
		||||
                               current_wm_sn_owner, CWEventMask, &attrs);
 | 
			
		||||
@@ -619,7 +617,7 @@ meta_screen_new (MetaDisplay *display,
 | 
			
		||||
    }
 | 
			
		||||
  
 | 
			
		||||
  /* select our root window events */
 | 
			
		||||
  meta_error_trap_push (display);
 | 
			
		||||
  meta_error_trap_push_with_return (display);
 | 
			
		||||
 | 
			
		||||
  /* We need to or with the existing event mask since
 | 
			
		||||
   * gtk+ may be interested in other events.
 | 
			
		||||
@@ -690,6 +688,7 @@ meta_screen_new (MetaDisplay *display,
 | 
			
		||||
  screen->current_cursor = -1; /* invalid/unset */
 | 
			
		||||
  screen->default_xvisual = DefaultVisualOfScreen (screen->xscreen);
 | 
			
		||||
  screen->default_depth = DefaultDepthOfScreen (screen->xscreen);
 | 
			
		||||
  screen->flash_window = None;
 | 
			
		||||
 | 
			
		||||
  screen->wm_sn_selection_window = new_wm_sn_owner;
 | 
			
		||||
  screen->wm_sn_atom = wm_sn_atom;
 | 
			
		||||
@@ -707,6 +706,7 @@ meta_screen_new (MetaDisplay *display,
 | 
			
		||||
  screen->columns_of_workspaces = -1;
 | 
			
		||||
  screen->vertical_workspaces = FALSE;
 | 
			
		||||
  screen->starting_corner = META_SCREEN_TOPLEFT;
 | 
			
		||||
  screen->compositor_data = NULL;
 | 
			
		||||
  screen->guard_window = None;
 | 
			
		||||
 | 
			
		||||
  reload_monitor_infos (screen);
 | 
			
		||||
@@ -757,7 +757,12 @@ meta_screen_new (MetaDisplay *display,
 | 
			
		||||
  screen->keys_grabbed = FALSE;
 | 
			
		||||
  meta_screen_grab_keys (screen);
 | 
			
		||||
 | 
			
		||||
  screen->ui = meta_ui_new ();
 | 
			
		||||
  screen->ui = meta_ui_new (screen->display->xdisplay,
 | 
			
		||||
                            screen->xscreen);
 | 
			
		||||
 | 
			
		||||
  screen->tab_popup = NULL;
 | 
			
		||||
  screen->ws_popup = NULL;
 | 
			
		||||
  screen->tile_preview = NULL;
 | 
			
		||||
 | 
			
		||||
  screen->tile_preview_timeout_id = 0;
 | 
			
		||||
 | 
			
		||||
@@ -806,7 +811,11 @@ meta_screen_free (MetaScreen *screen,
 | 
			
		||||
  
 | 
			
		||||
  meta_display_grab (display);
 | 
			
		||||
 | 
			
		||||
  meta_compositor_unmanage (screen->display->compositor);
 | 
			
		||||
  if (screen->display->compositor)
 | 
			
		||||
    {
 | 
			
		||||
      meta_compositor_unmanage_screen (screen->display->compositor,
 | 
			
		||||
				       screen);
 | 
			
		||||
    }
 | 
			
		||||
  
 | 
			
		||||
  meta_display_unmanage_windows_for_screen (display, screen, timestamp);
 | 
			
		||||
  
 | 
			
		||||
@@ -837,7 +846,7 @@ meta_screen_free (MetaScreen *screen,
 | 
			
		||||
  meta_stack_free (screen->stack);
 | 
			
		||||
  meta_stack_tracker_free (screen->stack_tracker);
 | 
			
		||||
 | 
			
		||||
  meta_error_trap_push (screen->display);
 | 
			
		||||
  meta_error_trap_push_with_return (screen->display);
 | 
			
		||||
  XSelectInput (screen->display->xdisplay, screen->xroot, 0);
 | 
			
		||||
  if (meta_error_trap_pop_with_return (screen->display) != Success)
 | 
			
		||||
    meta_warning ("Could not release screen %d on display \"%s\"\n",
 | 
			
		||||
@@ -859,6 +868,9 @@ meta_screen_free (MetaScreen *screen,
 | 
			
		||||
  if (screen->tile_preview_timeout_id)
 | 
			
		||||
    g_source_remove (screen->tile_preview_timeout_id);
 | 
			
		||||
 | 
			
		||||
  if (screen->tile_preview)
 | 
			
		||||
    meta_tile_preview_free (screen->tile_preview);
 | 
			
		||||
  
 | 
			
		||||
  g_free (screen->screen_name);
 | 
			
		||||
 | 
			
		||||
  g_object_unref (screen);
 | 
			
		||||
@@ -897,6 +909,28 @@ meta_screen_manage_all_windows (MetaScreen *screen)
 | 
			
		||||
  meta_stack_thaw (screen->stack);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_screen_for_x_screen:
 | 
			
		||||
 * @xscreen: an X screen structure.
 | 
			
		||||
 *
 | 
			
		||||
 * Gets the #MetaScreen corresponding to an X screen structure.
 | 
			
		||||
 *
 | 
			
		||||
 * Return value: (transfer none): the #MetaScreen for the X screen
 | 
			
		||||
 *   %NULL if Metacity is not managing the screen.
 | 
			
		||||
 */
 | 
			
		||||
MetaScreen*
 | 
			
		||||
meta_screen_for_x_screen (Screen *xscreen)
 | 
			
		||||
{
 | 
			
		||||
  MetaDisplay *display;
 | 
			
		||||
  
 | 
			
		||||
  display = meta_display_for_x_display (DisplayOfScreen (xscreen));
 | 
			
		||||
 | 
			
		||||
  if (display == NULL)
 | 
			
		||||
    return NULL;
 | 
			
		||||
  
 | 
			
		||||
  return meta_display_screen_for_x_screen (display, xscreen);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
prefs_changed_callback (MetaPreference pref,
 | 
			
		||||
                        gpointer       data)
 | 
			
		||||
@@ -1380,26 +1414,6 @@ update_focus_mode (MetaScreen *screen)
 | 
			
		||||
  /* nothing to do anymore */ ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_screen_update_cursor (MetaScreen *screen)
 | 
			
		||||
{
 | 
			
		||||
  MetaDisplay *display = screen->display;
 | 
			
		||||
  MetaCursor cursor = screen->current_cursor;
 | 
			
		||||
  Cursor xcursor;
 | 
			
		||||
  MetaCursorReference *cursor_ref;
 | 
			
		||||
 | 
			
		||||
  cursor_ref = meta_cursor_reference_from_theme (screen->cursor_tracker, cursor);
 | 
			
		||||
  meta_cursor_tracker_set_root_cursor (screen->cursor_tracker, cursor_ref);
 | 
			
		||||
  meta_cursor_reference_unref (cursor_ref);
 | 
			
		||||
 | 
			
		||||
  /* Set a cursor for X11 applications that don't specify their own */
 | 
			
		||||
  xcursor = meta_display_create_x_cursor (display, cursor);
 | 
			
		||||
 | 
			
		||||
  XDefineCursor (display->xdisplay, screen->xroot, xcursor);
 | 
			
		||||
  XFlush (display->xdisplay);
 | 
			
		||||
  XFreeCursor (display->xdisplay, xcursor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_screen_set_cursor (MetaScreen *screen,
 | 
			
		||||
                        MetaCursor  cursor)
 | 
			
		||||
@@ -1408,11 +1422,265 @@ meta_screen_set_cursor (MetaScreen *screen,
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  screen->current_cursor = cursor;
 | 
			
		||||
  meta_screen_update_cursor (screen);
 | 
			
		||||
  meta_cursor_tracker_set_root_cursor (screen->cursor_tracker, cursor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_screen_update_cursor (MetaScreen *screen)
 | 
			
		||||
{
 | 
			
		||||
  meta_cursor_tracker_set_root_cursor (screen->cursor_tracker,
 | 
			
		||||
                                       screen->current_cursor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_screen_tab_popup_create (MetaScreen      *screen,
 | 
			
		||||
                              MetaTabList      list_type,
 | 
			
		||||
                              MetaTabShowType  show_type,
 | 
			
		||||
                              MetaWindow      *initial_selection)
 | 
			
		||||
{
 | 
			
		||||
  MetaTabEntry *entries;
 | 
			
		||||
  GList *tab_list;
 | 
			
		||||
  GList *tmp;
 | 
			
		||||
  int len;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  if (screen->tab_popup)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  tab_list = meta_display_get_tab_list (screen->display,
 | 
			
		||||
                                        list_type,
 | 
			
		||||
                                        screen,
 | 
			
		||||
                                        screen->active_workspace);
 | 
			
		||||
 | 
			
		||||
  len = g_list_length (tab_list);
 | 
			
		||||
 | 
			
		||||
  entries = g_new (MetaTabEntry, len + 1);
 | 
			
		||||
  entries[len].key = NULL;
 | 
			
		||||
  entries[len].title = NULL;
 | 
			
		||||
  entries[len].icon = NULL;
 | 
			
		||||
 | 
			
		||||
  i = 0;
 | 
			
		||||
  tmp = tab_list;
 | 
			
		||||
  while (i < len)
 | 
			
		||||
    {
 | 
			
		||||
      MetaWindow *window;
 | 
			
		||||
      MetaRectangle r;
 | 
			
		||||
 | 
			
		||||
      window = tmp->data;
 | 
			
		||||
 | 
			
		||||
      entries[i].key = (MetaTabEntryKey) window;
 | 
			
		||||
      entries[i].title = window->title;
 | 
			
		||||
      entries[i].icon = g_object_ref (window->icon);
 | 
			
		||||
      entries[i].blank = FALSE;
 | 
			
		||||
      entries[i].hidden = !meta_window_showing_on_its_workspace (window);
 | 
			
		||||
      entries[i].demands_attention = window->wm_state_demands_attention;
 | 
			
		||||
 | 
			
		||||
      if (show_type == META_TAB_SHOW_INSTANTLY ||
 | 
			
		||||
          !entries[i].hidden                   ||
 | 
			
		||||
          !meta_window_get_icon_geometry (window, &r))
 | 
			
		||||
        meta_window_get_frame_rect (window, &r);
 | 
			
		||||
 | 
			
		||||
      entries[i].rect = r;
 | 
			
		||||
 | 
			
		||||
      /* Find inside of highlight rectangle to be used when window is
 | 
			
		||||
       * outlined for tabbing.  This should be the size of the
 | 
			
		||||
       * east/west frame, and the size of the south frame, on those
 | 
			
		||||
       * sides.  On the top it should be the size of the south frame
 | 
			
		||||
       * edge.
 | 
			
		||||
       */
 | 
			
		||||
#define OUTLINE_WIDTH 5
 | 
			
		||||
      /* Top side */
 | 
			
		||||
      if (!entries[i].hidden &&
 | 
			
		||||
          window->frame && window->frame->bottom_height > 0 &&
 | 
			
		||||
          window->frame->child_y >= window->frame->bottom_height)
 | 
			
		||||
        entries[i].inner_rect.y = window->frame->bottom_height;
 | 
			
		||||
      else
 | 
			
		||||
        entries[i].inner_rect.y = OUTLINE_WIDTH;
 | 
			
		||||
 | 
			
		||||
      /* Bottom side */
 | 
			
		||||
      if (!entries[i].hidden &&
 | 
			
		||||
          window->frame && window->frame->bottom_height != 0)
 | 
			
		||||
        entries[i].inner_rect.height = r.height
 | 
			
		||||
          - entries[i].inner_rect.y - window->frame->bottom_height;
 | 
			
		||||
      else
 | 
			
		||||
        entries[i].inner_rect.height = r.height
 | 
			
		||||
          - entries[i].inner_rect.y - OUTLINE_WIDTH;
 | 
			
		||||
 | 
			
		||||
      /* Left side */
 | 
			
		||||
      if (!entries[i].hidden && window->frame && window->frame->child_x != 0)
 | 
			
		||||
        entries[i].inner_rect.x = window->frame->child_x;
 | 
			
		||||
      else
 | 
			
		||||
        entries[i].inner_rect.x = OUTLINE_WIDTH;
 | 
			
		||||
 | 
			
		||||
      /* Right side */
 | 
			
		||||
      if (!entries[i].hidden &&
 | 
			
		||||
          window->frame && window->frame->right_width != 0)
 | 
			
		||||
        entries[i].inner_rect.width = r.width
 | 
			
		||||
          - entries[i].inner_rect.x - window->frame->right_width;
 | 
			
		||||
      else
 | 
			
		||||
        entries[i].inner_rect.width = r.width
 | 
			
		||||
          - entries[i].inner_rect.x - OUTLINE_WIDTH;
 | 
			
		||||
 | 
			
		||||
      ++i;
 | 
			
		||||
      tmp = tmp->next;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (!meta_prefs_get_no_tab_popup ())
 | 
			
		||||
    screen->tab_popup = meta_ui_tab_popup_new (entries,
 | 
			
		||||
                                               screen->number,
 | 
			
		||||
                                               len,
 | 
			
		||||
                                               5, /* FIXME */
 | 
			
		||||
                                               TRUE);
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < len; i++)
 | 
			
		||||
    g_object_unref (entries[i].icon);
 | 
			
		||||
 | 
			
		||||
  g_free (entries);
 | 
			
		||||
 | 
			
		||||
  g_list_free (tab_list);
 | 
			
		||||
 | 
			
		||||
  meta_ui_tab_popup_select (screen->tab_popup,
 | 
			
		||||
                            (MetaTabEntryKey) initial_selection);
 | 
			
		||||
 | 
			
		||||
  if (show_type != META_TAB_SHOW_INSTANTLY)
 | 
			
		||||
    meta_ui_tab_popup_set_showing (screen->tab_popup, TRUE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_screen_tab_popup_forward (MetaScreen *screen)
 | 
			
		||||
{
 | 
			
		||||
  g_return_if_fail (screen->tab_popup != NULL);
 | 
			
		||||
 | 
			
		||||
  meta_ui_tab_popup_forward (screen->tab_popup);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_screen_tab_popup_backward (MetaScreen *screen)
 | 
			
		||||
{
 | 
			
		||||
  g_return_if_fail (screen->tab_popup != NULL);
 | 
			
		||||
 | 
			
		||||
  meta_ui_tab_popup_backward (screen->tab_popup);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetaWindow *
 | 
			
		||||
meta_screen_tab_popup_get_selected (MetaScreen *screen)
 | 
			
		||||
{
 | 
			
		||||
  g_return_val_if_fail (screen->tab_popup != NULL, NULL);
 | 
			
		||||
 | 
			
		||||
  return (MetaWindow *) meta_ui_tab_popup_get_selected (screen->tab_popup);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_screen_tab_popup_destroy (MetaScreen *screen)
 | 
			
		||||
{
 | 
			
		||||
  if (screen->tab_popup)
 | 
			
		||||
    {
 | 
			
		||||
      meta_ui_tab_popup_free (screen->tab_popup);
 | 
			
		||||
      screen->tab_popup = NULL;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_screen_workspace_popup_create (MetaScreen    *screen,
 | 
			
		||||
                                    MetaWorkspace *initial_selection)
 | 
			
		||||
{
 | 
			
		||||
  MetaTabEntry *entries;
 | 
			
		||||
  int len;
 | 
			
		||||
  int i;
 | 
			
		||||
  MetaWorkspaceLayout layout;
 | 
			
		||||
  int n_workspaces;
 | 
			
		||||
  int current_workspace;
 | 
			
		||||
 | 
			
		||||
  if (screen->ws_popup || meta_prefs_get_no_tab_popup ())
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  current_workspace = meta_workspace_index (screen->active_workspace);
 | 
			
		||||
  n_workspaces = meta_screen_get_n_workspaces (screen);
 | 
			
		||||
 | 
			
		||||
  meta_screen_calc_workspace_layout (screen, n_workspaces,
 | 
			
		||||
                                     current_workspace, &layout);
 | 
			
		||||
 | 
			
		||||
  len = layout.grid_area;
 | 
			
		||||
  
 | 
			
		||||
  entries = g_new (MetaTabEntry, len + 1);
 | 
			
		||||
  entries[len].key = NULL;
 | 
			
		||||
  entries[len].title = NULL;
 | 
			
		||||
  entries[len].icon = NULL;
 | 
			
		||||
 | 
			
		||||
  i = 0;
 | 
			
		||||
  while (i < len)
 | 
			
		||||
    {
 | 
			
		||||
      if (layout.grid[i] >= 0)
 | 
			
		||||
        {
 | 
			
		||||
          MetaWorkspace *workspace;
 | 
			
		||||
          
 | 
			
		||||
          workspace = meta_screen_get_workspace_by_index (screen,
 | 
			
		||||
                                                          layout.grid[i]);
 | 
			
		||||
          
 | 
			
		||||
          entries[i].key = (MetaTabEntryKey) workspace;
 | 
			
		||||
          entries[i].title = meta_workspace_get_name (workspace);
 | 
			
		||||
          entries[i].icon = NULL;
 | 
			
		||||
          entries[i].blank = FALSE;
 | 
			
		||||
          
 | 
			
		||||
          g_assert (entries[i].title != NULL);
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          entries[i].key = NULL;
 | 
			
		||||
          entries[i].title = NULL;
 | 
			
		||||
          entries[i].icon = NULL;
 | 
			
		||||
          entries[i].blank = TRUE;
 | 
			
		||||
        }
 | 
			
		||||
      entries[i].hidden = FALSE;
 | 
			
		||||
      entries[i].demands_attention = FALSE;
 | 
			
		||||
 | 
			
		||||
      ++i;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  screen->ws_popup = meta_ui_tab_popup_new (entries,
 | 
			
		||||
                                            screen->number,
 | 
			
		||||
                                            len,
 | 
			
		||||
                                            layout.cols,
 | 
			
		||||
                                            FALSE);
 | 
			
		||||
 | 
			
		||||
  g_free (entries);
 | 
			
		||||
  meta_screen_free_workspace_layout (&layout);
 | 
			
		||||
 | 
			
		||||
  meta_ui_tab_popup_select (screen->ws_popup,
 | 
			
		||||
                            (MetaTabEntryKey) initial_selection);
 | 
			
		||||
  meta_ui_tab_popup_set_showing (screen->ws_popup, TRUE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_screen_workspace_popup_select (MetaScreen    *screen,
 | 
			
		||||
                                    MetaWorkspace *workspace)
 | 
			
		||||
{
 | 
			
		||||
  g_return_if_fail (screen->ws_popup != NULL);
 | 
			
		||||
 | 
			
		||||
  meta_ui_tab_popup_select (screen->ws_popup,
 | 
			
		||||
                            (MetaTabEntryKey) workspace);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetaWorkspace *
 | 
			
		||||
meta_screen_workspace_popup_get_selected (MetaScreen *screen)
 | 
			
		||||
{
 | 
			
		||||
  g_return_val_if_fail (screen->ws_popup != NULL, NULL);
 | 
			
		||||
 | 
			
		||||
  return (MetaWorkspace *) meta_ui_tab_popup_get_selected (screen->ws_popup);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_screen_workspace_popup_destroy (MetaScreen *screen)
 | 
			
		||||
{
 | 
			
		||||
  if (screen->ws_popup)
 | 
			
		||||
    {
 | 
			
		||||
      meta_ui_tab_popup_free (screen->ws_popup);
 | 
			
		||||
      screen->ws_popup = NULL;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
meta_screen_update_tile_preview_timeout (gpointer data)
 | 
			
		||||
meta_screen_tile_preview_update_timeout (gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  MetaScreen *screen = data;
 | 
			
		||||
  MetaWindow *window = screen->display->grab_window;
 | 
			
		||||
@@ -1420,6 +1688,22 @@ meta_screen_update_tile_preview_timeout (gpointer data)
 | 
			
		||||
 | 
			
		||||
  screen->tile_preview_timeout_id = 0;
 | 
			
		||||
 | 
			
		||||
  if (!screen->tile_preview)
 | 
			
		||||
    {
 | 
			
		||||
      Window xwindow;
 | 
			
		||||
      gulong create_serial;
 | 
			
		||||
      MetaStackWindow stack_window;
 | 
			
		||||
 | 
			
		||||
      screen->tile_preview = meta_tile_preview_new (screen->number);
 | 
			
		||||
      xwindow = meta_tile_preview_get_xwindow (screen->tile_preview,
 | 
			
		||||
                                               &create_serial);
 | 
			
		||||
      stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
 | 
			
		||||
      stack_window.x11.xwindow = xwindow;
 | 
			
		||||
      meta_stack_tracker_record_add (screen->stack_tracker,
 | 
			
		||||
                                     &stack_window,
 | 
			
		||||
                                     create_serial);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (window)
 | 
			
		||||
    {
 | 
			
		||||
      switch (window->tile_mode)
 | 
			
		||||
@@ -1444,15 +1728,12 @@ meta_screen_update_tile_preview_timeout (gpointer data)
 | 
			
		||||
  if (needs_preview)
 | 
			
		||||
    {
 | 
			
		||||
      MetaRectangle tile_rect;
 | 
			
		||||
      int monitor;
 | 
			
		||||
 | 
			
		||||
      monitor = meta_window_get_current_tile_monitor_number (window);
 | 
			
		||||
      meta_window_get_current_tile_area (window, &tile_rect);
 | 
			
		||||
      meta_compositor_show_tile_preview (screen->display->compositor,
 | 
			
		||||
                                         window, &tile_rect, monitor);
 | 
			
		||||
      meta_tile_preview_show (screen->tile_preview, &tile_rect);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    meta_compositor_hide_tile_preview (screen->display->compositor);
 | 
			
		||||
    meta_tile_preview_hide (screen->tile_preview);
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
@@ -1460,7 +1741,7 @@ meta_screen_update_tile_preview_timeout (gpointer data)
 | 
			
		||||
#define TILE_PREVIEW_TIMEOUT_MS 200
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_screen_update_tile_preview (MetaScreen *screen,
 | 
			
		||||
meta_screen_tile_preview_update (MetaScreen *screen,
 | 
			
		||||
                                 gboolean    delay)
 | 
			
		||||
{
 | 
			
		||||
  if (delay)
 | 
			
		||||
@@ -1470,7 +1751,7 @@ meta_screen_update_tile_preview (MetaScreen *screen,
 | 
			
		||||
 | 
			
		||||
      screen->tile_preview_timeout_id =
 | 
			
		||||
        g_timeout_add (TILE_PREVIEW_TIMEOUT_MS,
 | 
			
		||||
                       meta_screen_update_tile_preview_timeout,
 | 
			
		||||
                       meta_screen_tile_preview_update_timeout,
 | 
			
		||||
                       screen);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
@@ -1478,17 +1759,18 @@ meta_screen_update_tile_preview (MetaScreen *screen,
 | 
			
		||||
      if (screen->tile_preview_timeout_id > 0)
 | 
			
		||||
        g_source_remove (screen->tile_preview_timeout_id);
 | 
			
		||||
 | 
			
		||||
      meta_screen_update_tile_preview_timeout ((gpointer)screen);
 | 
			
		||||
      meta_screen_tile_preview_update_timeout ((gpointer)screen);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_screen_hide_tile_preview (MetaScreen *screen)
 | 
			
		||||
meta_screen_tile_preview_hide (MetaScreen *screen)
 | 
			
		||||
{
 | 
			
		||||
  if (screen->tile_preview_timeout_id > 0)
 | 
			
		||||
    g_source_remove (screen->tile_preview_timeout_id);
 | 
			
		||||
 | 
			
		||||
  meta_compositor_hide_tile_preview (screen->display->compositor);
 | 
			
		||||
  if (screen->tile_preview)
 | 
			
		||||
    meta_tile_preview_hide (screen->tile_preview);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetaWindow*
 | 
			
		||||
@@ -1496,19 +1778,38 @@ meta_screen_get_mouse_window (MetaScreen  *screen,
 | 
			
		||||
                              MetaWindow  *not_this_one)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindow *window;
 | 
			
		||||
  int x, y;
 | 
			
		||||
  Window root_return, child_return;
 | 
			
		||||
  double root_x_return, root_y_return;
 | 
			
		||||
  double win_x_return, win_y_return;
 | 
			
		||||
  XIButtonState buttons;
 | 
			
		||||
  XIModifierState mods;
 | 
			
		||||
  XIGroupState group;
 | 
			
		||||
 | 
			
		||||
  if (not_this_one)
 | 
			
		||||
    meta_topic (META_DEBUG_FOCUS,
 | 
			
		||||
                "Focusing mouse window excluding %s\n", not_this_one->desc);
 | 
			
		||||
 | 
			
		||||
  meta_cursor_tracker_get_pointer (screen->cursor_tracker,
 | 
			
		||||
                                   &x, &y, NULL);
 | 
			
		||||
  meta_error_trap_push (screen->display);
 | 
			
		||||
  XIQueryPointer (screen->display->xdisplay,
 | 
			
		||||
                  META_VIRTUAL_CORE_POINTER_ID,
 | 
			
		||||
                  screen->xroot,
 | 
			
		||||
                  &root_return,
 | 
			
		||||
                  &child_return,
 | 
			
		||||
                  &root_x_return,
 | 
			
		||||
                  &root_y_return,
 | 
			
		||||
                  &win_x_return,
 | 
			
		||||
                  &win_y_return,
 | 
			
		||||
                  &buttons,
 | 
			
		||||
                  &mods,
 | 
			
		||||
                  &group);
 | 
			
		||||
  meta_error_trap_pop (screen->display);
 | 
			
		||||
  free (buttons.mask);
 | 
			
		||||
 | 
			
		||||
  window = meta_stack_get_default_focus_window_at_point (screen->stack,
 | 
			
		||||
                                                         screen->active_workspace,
 | 
			
		||||
                                                         not_this_one,
 | 
			
		||||
                                                         x, y);
 | 
			
		||||
                                                         root_x_return,
 | 
			
		||||
                                                         root_y_return);
 | 
			
		||||
 | 
			
		||||
  return window;
 | 
			
		||||
}
 | 
			
		||||
@@ -1790,11 +2091,28 @@ meta_screen_get_current_monitor (MetaScreen *screen)
 | 
			
		||||
  
 | 
			
		||||
  if (screen->display->monitor_cache_invalidated)
 | 
			
		||||
    {
 | 
			
		||||
      int x, y;
 | 
			
		||||
      Window root_return, child_return;
 | 
			
		||||
      double win_x_return, win_y_return;
 | 
			
		||||
      double root_x_return, root_y_return;
 | 
			
		||||
      XIButtonState buttons;
 | 
			
		||||
      XIModifierState mods;
 | 
			
		||||
      XIGroupState group;
 | 
			
		||||
 | 
			
		||||
      meta_cursor_tracker_get_pointer (screen->cursor_tracker,
 | 
			
		||||
                                       &x, &y, NULL);
 | 
			
		||||
      meta_screen_get_current_monitor_for_pos (screen, x, y);
 | 
			
		||||
      XIQueryPointer (screen->display->xdisplay,
 | 
			
		||||
                      META_VIRTUAL_CORE_POINTER_ID,
 | 
			
		||||
                      screen->xroot,
 | 
			
		||||
                      &root_return,
 | 
			
		||||
                      &child_return,
 | 
			
		||||
                      &root_x_return,
 | 
			
		||||
                      &root_y_return,
 | 
			
		||||
                      &win_x_return,
 | 
			
		||||
                      &win_y_return,
 | 
			
		||||
                      &buttons,
 | 
			
		||||
                      &mods,
 | 
			
		||||
                      &group);
 | 
			
		||||
      free (buttons.mask);
 | 
			
		||||
 | 
			
		||||
      meta_screen_get_current_monitor_for_pos (screen, root_x_return, root_y_return);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return screen->last_monitor_index;
 | 
			
		||||
@@ -2505,8 +2823,10 @@ on_monitors_changed (MetaMonitorManager *manager,
 | 
			
		||||
                       &changes);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_compositor_sync_screen_size (screen->display->compositor,
 | 
			
		||||
                                    screen->rect.width, screen->rect.height);
 | 
			
		||||
  if (screen->display->compositor)
 | 
			
		||||
    meta_compositor_sync_screen_size (screen->display->compositor,
 | 
			
		||||
				      screen,
 | 
			
		||||
                                      screen->rect.width, screen->rect.height);
 | 
			
		||||
 | 
			
		||||
  /* Queue a resize on all the windows */
 | 
			
		||||
  meta_screen_foreach_window (screen, meta_screen_resize_func, 0);
 | 
			
		||||
@@ -3046,6 +3366,24 @@ meta_screen_get_size (MetaScreen *screen,
 | 
			
		||||
    *height = screen->rect.height;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_screen_get_compositor_data: (skip)
 | 
			
		||||
 * @screen: A #MetaScreen
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
gpointer
 | 
			
		||||
meta_screen_get_compositor_data (MetaScreen *screen)
 | 
			
		||||
{
 | 
			
		||||
  return screen->compositor_data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_screen_set_compositor_data (MetaScreen *screen,
 | 
			
		||||
                                 gpointer    compositor)
 | 
			
		||||
{
 | 
			
		||||
  screen->compositor_data = compositor;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_screen_set_cm_selection (MetaScreen *screen)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -1816,7 +1816,7 @@ warn_about_lame_clients_and_finish_interact (gboolean shutdown)
 | 
			
		||||
                           "and will have to be restarted manually next time "
 | 
			
		||||
                           "you log in."),
 | 
			
		||||
                         "240",
 | 
			
		||||
                         meta_get_display()->screen->screen_name,
 | 
			
		||||
                         meta_get_display()->active_screen->screen_name,
 | 
			
		||||
                         NULL, NULL, NULL,
 | 
			
		||||
                         None,
 | 
			
		||||
                         columns,
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user