Compare commits
	
		
			1 Commits
		
	
	
		
			3.11.92-wa
			...
			wip/resize
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					32cc8fffb3 | 
							
								
								
									
										19
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										19
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -78,12 +78,12 @@ src/stamp-mutter-marshal.h
 | 
			
		||||
src/meta-dbus-xrandr.[ch]
 | 
			
		||||
src/meta-dbus-idle-monitor.[ch]
 | 
			
		||||
src/mutter-plugins.pc
 | 
			
		||||
src/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,10 +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
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								NEWS
									
									
									
									
									
								
							@@ -1,14 +1,3 @@
 | 
			
		||||
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]
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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) || {
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@ AC_CONFIG_MACRO_DIR([m4])
 | 
			
		||||
 | 
			
		||||
m4_define([mutter_major_version], [3])
 | 
			
		||||
m4_define([mutter_minor_version], [11])
 | 
			
		||||
m4_define([mutter_micro_version], [92])
 | 
			
		||||
m4_define([mutter_micro_version], [91])
 | 
			
		||||
 | 
			
		||||
m4_define([mutter_version],
 | 
			
		||||
          [mutter_major_version.mutter_minor_version.mutter_micro_version])
 | 
			
		||||
@@ -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
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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,87 +275,113 @@
 | 
			
		||||
      <arg name="output" type="object" interface="wl_output" allow-null="true"/>
 | 
			
		||||
    </request>
 | 
			
		||||
 | 
			
		||||
    <enum name="state">
 | 
			
		||||
      <description summary="types of state on the surface">
 | 
			
		||||
        The different state values used on the surface. This is designed for
 | 
			
		||||
        state values like maximized, fullscreen. It is paired with the
 | 
			
		||||
        request_change_state event to ensure that both the client and the
 | 
			
		||||
        compositor setting the state can be synchronized.
 | 
			
		||||
 | 
			
		||||
        States set in this way are double-buffered. They will get applied on
 | 
			
		||||
        the next commit.
 | 
			
		||||
 | 
			
		||||
        Desktop environments may extend this enum by taking up a range of
 | 
			
		||||
        values and documenting the range they chose in this description.
 | 
			
		||||
        They are not required to document the values for the range that they
 | 
			
		||||
        chose. Ideally, any good extensions from a desktop environment should
 | 
			
		||||
        make its way into standardization into this enum.
 | 
			
		||||
 | 
			
		||||
        The current reserved ranges are:
 | 
			
		||||
 | 
			
		||||
        0x0000 - 0x0FFF: xdg-shell core values, documented below.
 | 
			
		||||
        0x1000 - 0x1FFF: GNOME
 | 
			
		||||
    <event name="request_set_fullscreen">
 | 
			
		||||
      <description summary="server requests that the client set fullscreen">
 | 
			
		||||
	Event sent from the compositor to the client requesting that the client
 | 
			
		||||
	goes to a fullscreen state. It's the client job to call set_fullscreen
 | 
			
		||||
	and really trigger the fullscreen state.
 | 
			
		||||
      </description>
 | 
			
		||||
      <entry name="maximized" value="1" summary="the surface is maximized">
 | 
			
		||||
        A non-zero value indicates the surface is maximized. Otherwise,
 | 
			
		||||
        the surface is unmaximized.
 | 
			
		||||
      </entry>
 | 
			
		||||
      <entry name="fullscreen" value="2" summary="the surface is fullscreen">
 | 
			
		||||
        A non-zero value indicates the surface is fullscreen. Otherwise,
 | 
			
		||||
        the surface is not fullscreen.
 | 
			
		||||
      </entry>
 | 
			
		||||
    </enum>
 | 
			
		||||
 | 
			
		||||
    <request name="request_change_state">
 | 
			
		||||
      <description summary="client requests to change a surface's state">
 | 
			
		||||
        This asks the compositor to change the state. If the compositor wants
 | 
			
		||||
        to change the state, it will send a change_state event with the same
 | 
			
		||||
        state_type, value, and serial, and the event flow continues as if it
 | 
			
		||||
        it was initiated by the compositor.
 | 
			
		||||
 | 
			
		||||
        If the compositor does not want to change the state, it will send a
 | 
			
		||||
        change_state to the client with the old value of the state.
 | 
			
		||||
      </description>
 | 
			
		||||
      <arg name="state_type" type="uint" summary="the state to set"/>
 | 
			
		||||
      <arg name="value" type="uint" summary="the value to change the state to"/>
 | 
			
		||||
      <arg name="serial" type="uint" summary="an event serial">
 | 
			
		||||
        This serial is so the client can know which change_state event corresponds
 | 
			
		||||
        to which request_change_state request it sent out.
 | 
			
		||||
      </arg>
 | 
			
		||||
    </request>
 | 
			
		||||
 | 
			
		||||
    <event name="change_state">
 | 
			
		||||
      <description summary="compositor wants to change a surface's state">
 | 
			
		||||
        This event tells the client to change a surface's state. The client
 | 
			
		||||
        should respond with an ack_change_state request to the compositor to
 | 
			
		||||
        guarantee that the compositor knows that the client has seen it.
 | 
			
		||||
      </description>
 | 
			
		||||
 | 
			
		||||
      <arg name="state_type" type="uint" summary="the state to set"/>
 | 
			
		||||
      <arg name="value" type="uint" summary="the value to change the state to"/>
 | 
			
		||||
      <arg name="serial" type="uint" summary="a serial for the compositor's own tracking"/>
 | 
			
		||||
    </event>
 | 
			
		||||
 | 
			
		||||
    <request name="ack_change_state">
 | 
			
		||||
      <description summary="ack a change_state event">
 | 
			
		||||
        When a change_state event is received, a client should then ack it
 | 
			
		||||
        using the ack_change_state request to ensure that the compositor
 | 
			
		||||
        knows the client has seen the event.
 | 
			
		||||
 | 
			
		||||
        By this point, the state is confirmed, and the next attach should
 | 
			
		||||
        contain the buffer drawn for the new state value.
 | 
			
		||||
 | 
			
		||||
        The values here need to be the same as the values in the cooresponding
 | 
			
		||||
        change_state event.
 | 
			
		||||
    <event name="request_unset_fullscreen">
 | 
			
		||||
      <description summary="server requests that the client unset fullscreen">
 | 
			
		||||
	Event sent from the compositor to the client requesting that the client
 | 
			
		||||
	leaves the fullscreen state. It's the client job to call
 | 
			
		||||
	unset_fullscreen and really leave the fullscreen state.
 | 
			
		||||
      </description>
 | 
			
		||||
    </event>
 | 
			
		||||
 | 
			
		||||
    <request name="set_fullscreen">
 | 
			
		||||
      <description summary="set the surface state as fullscreen">
 | 
			
		||||
	Set the surface as fullscreen.
 | 
			
		||||
 | 
			
		||||
	After this request, the compositor should send a configure event
 | 
			
		||||
	informing the output size.
 | 
			
		||||
 | 
			
		||||
	This request informs the compositor that the next attached buffer
 | 
			
		||||
	committed will be in a fullscreen state. The buffer size should be the
 | 
			
		||||
	same size as the size informed in the configure event, if the client
 | 
			
		||||
	doesn't want to leave any empty area.
 | 
			
		||||
 | 
			
		||||
	In other words: the next attached buffer after set_maximized is the new
 | 
			
		||||
	maximized buffer. And the surface will be positioned at the maximized
 | 
			
		||||
	position on commit.
 | 
			
		||||
 | 
			
		||||
	A simple way to synchronize and wait for the correct configure event is
 | 
			
		||||
	to use a wl_display.sync request right after the set_fullscreen
 | 
			
		||||
	request. When the sync callback returns, the last configure event
 | 
			
		||||
	received just before it will be the correct one, and should contain the
 | 
			
		||||
	right size for the surface to maximize.
 | 
			
		||||
 | 
			
		||||
	Setting one state won't unset another state. Use
 | 
			
		||||
	xdg_surface.unset_fullscreen for unsetting it.
 | 
			
		||||
      </description>
 | 
			
		||||
    </request>
 | 
			
		||||
 | 
			
		||||
    <request name="unset_fullscreen">
 | 
			
		||||
      <description summary="unset the surface state as fullscreen">
 | 
			
		||||
	Unset the surface fullscreen state.
 | 
			
		||||
 | 
			
		||||
	Same negotiation as set_fullscreen must be used.
 | 
			
		||||
      </description>
 | 
			
		||||
    </request>
 | 
			
		||||
 | 
			
		||||
    <event name="request_set_maximized">
 | 
			
		||||
      <description summary="server requests that the client set maximized">
 | 
			
		||||
	Event sent from the compositor to the client requesting that the client
 | 
			
		||||
	goes to a maximized state. It's the client job to call set_maximized
 | 
			
		||||
	and really trigger the maximized state.
 | 
			
		||||
      </description>
 | 
			
		||||
    </event>
 | 
			
		||||
 | 
			
		||||
    <event name="request_unset_maximized">
 | 
			
		||||
      <description summary="server requests that the client unset maximized">
 | 
			
		||||
	Event sent from the compositor to the client requesting that the client
 | 
			
		||||
	leaves the maximized state. It's the client job to call unset_maximized
 | 
			
		||||
	and really leave the maximized state.
 | 
			
		||||
      </description>
 | 
			
		||||
    </event>
 | 
			
		||||
 | 
			
		||||
    <request name="set_maximized">
 | 
			
		||||
      <description summary="set the surface state as maximized">
 | 
			
		||||
	Set the surface as maximized.
 | 
			
		||||
 | 
			
		||||
	After this request, the compositor will send a configure event
 | 
			
		||||
	informing the output size minus panel and other MW decorations.
 | 
			
		||||
 | 
			
		||||
	This request informs the compositor that the next attached buffer
 | 
			
		||||
	committed will be in a maximized state. The buffer size should be the
 | 
			
		||||
	same size as the size informed in the configure event, if the client
 | 
			
		||||
	doesn't want to leave any empty area.
 | 
			
		||||
 | 
			
		||||
	In other words: the next attached buffer after set_maximized is the new
 | 
			
		||||
	maximized buffer. And the surface will be positioned at the maximized
 | 
			
		||||
	position on commit.
 | 
			
		||||
 | 
			
		||||
	A simple way to synchronize and wait for the correct configure event is
 | 
			
		||||
	to use a wl_display.sync request right after the set_maximized request.
 | 
			
		||||
	When the sync callback returns, the last configure event received just
 | 
			
		||||
	before it will be the correct one, and should contain the right size
 | 
			
		||||
	for the surface to maximize.
 | 
			
		||||
 | 
			
		||||
	Setting one state won't unset another state. Use
 | 
			
		||||
	xdg_surface.unset_maximized for unsetting it.
 | 
			
		||||
      </description>
 | 
			
		||||
    </request>
 | 
			
		||||
 | 
			
		||||
    <request name="unset_maximized">
 | 
			
		||||
      <description summary="unset the surface state as maximized">
 | 
			
		||||
	Unset the surface maximized state.
 | 
			
		||||
 | 
			
		||||
	Same negotiation as set_maximized must be used.
 | 
			
		||||
      </description>
 | 
			
		||||
      <arg name="state_type" type="uint" summary="the state to set"/>
 | 
			
		||||
      <arg name="value" type="uint" summary="the value to change the state to"/>
 | 
			
		||||
      <arg name="serial" type="uint" summary="a serial to pass to change_state"/>
 | 
			
		||||
    </request>
 | 
			
		||||
 | 
			
		||||
    <request name="set_minimized">
 | 
			
		||||
      <description summary="minimize the surface">
 | 
			
		||||
        Minimize the surface.
 | 
			
		||||
      <description summary="set the surface state as minimized">
 | 
			
		||||
	Set the surface minimized state.
 | 
			
		||||
 | 
			
		||||
	Setting one state won't unset another state.
 | 
			
		||||
      </description>
 | 
			
		||||
    </request>
 | 
			
		||||
 | 
			
		||||
@@ -29,7 +29,11 @@ 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 = \
 | 
			
		||||
@@ -37,20 +41,16 @@ mutter_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		\
 | 
			
		||||
	xserver-protocol.c			\
 | 
			
		||||
	xserver-server-protocol.h
 | 
			
		||||
 | 
			
		||||
wayland_protocols = \
 | 
			
		||||
	wayland/protocol/gtk-shell.xml		\
 | 
			
		||||
	wayland/protocol/xdg-shell.xml		\
 | 
			
		||||
	wayland/protocol/xserver.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 =			\
 | 
			
		||||
	core/above-tab-keycode.c		\
 | 
			
		||||
	core/async-getprop.c			\
 | 
			
		||||
	core/async-getprop.h			\
 | 
			
		||||
	core/barrier.c				\
 | 
			
		||||
	meta/barrier.h				\
 | 
			
		||||
	core/bell.c				\
 | 
			
		||||
@@ -105,6 +105,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				\
 | 
			
		||||
@@ -122,6 +123,13 @@ libmutter_wayland_la_SOURCES =			\
 | 
			
		||||
	core/frame.h				\
 | 
			
		||||
	ui/gradient.c				\
 | 
			
		||||
	meta/gradient.h				\
 | 
			
		||||
	core/group-private.h			\
 | 
			
		||||
	core/group-props.c			\
 | 
			
		||||
	core/group-props.h			\
 | 
			
		||||
	core/group.c				\
 | 
			
		||||
	meta/group.h				\
 | 
			
		||||
	core/iconcache.c			\
 | 
			
		||||
	core/iconcache.h			\
 | 
			
		||||
	core/keybindings.c			\
 | 
			
		||||
	core/keybindings-private.h		\
 | 
			
		||||
	core/main.c				\
 | 
			
		||||
@@ -144,6 +152,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			\
 | 
			
		||||
@@ -151,11 +161,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					\
 | 
			
		||||
@@ -172,24 +188,6 @@ libmutter_wayland_la_SOURCES =			\
 | 
			
		||||
	meta/theme.h				\
 | 
			
		||||
	ui/theme-private.h			\
 | 
			
		||||
	ui/ui.c					\
 | 
			
		||||
	x11/iconcache.c				\
 | 
			
		||||
	x11/iconcache.h				\
 | 
			
		||||
	x11/async-getprop.c			\
 | 
			
		||||
	x11/async-getprop.h			\
 | 
			
		||||
	x11/group-private.h			\
 | 
			
		||||
	x11/group-props.c			\
 | 
			
		||||
	x11/group-props.h			\
 | 
			
		||||
	x11/group.c				\
 | 
			
		||||
	meta/group.h				\
 | 
			
		||||
	x11/session.c				\
 | 
			
		||||
	x11/session.h				\
 | 
			
		||||
	x11/window-props.c			\
 | 
			
		||||
	x11/window-props.h			\
 | 
			
		||||
	x11/window-x11.c			\
 | 
			
		||||
	x11/window-x11.h			\
 | 
			
		||||
	x11/window-x11-private.h		\
 | 
			
		||||
	x11/xprops.c				\
 | 
			
		||||
	x11/xprops.h				\
 | 
			
		||||
	wayland/meta-wayland.c			\
 | 
			
		||||
	wayland/meta-wayland.h			\
 | 
			
		||||
	wayland/meta-wayland-private.h		\
 | 
			
		||||
@@ -311,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
 | 
			
		||||
 | 
			
		||||
@@ -362,7 +360,6 @@ 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 \
 | 
			
		||||
@@ -412,7 +409,9 @@ $(dbus_idle_built_sources) : Makefile.am idle-monitor.xml
 | 
			
		||||
		--c-generate-object-manager						\
 | 
			
		||||
		$(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 < $< > $@
 | 
			
		||||
 
 | 
			
		||||
@@ -19,10 +19,16 @@ struct _MetaCompositor
 | 
			
		||||
 | 
			
		||||
  guint           repaint_func_id;
 | 
			
		||||
 | 
			
		||||
  ClutterActor   *shadow_src;
 | 
			
		||||
 | 
			
		||||
  MetaPlugin     *modal_plugin;
 | 
			
		||||
 | 
			
		||||
  gint64          server_time_query_time;
 | 
			
		||||
  gint64          server_time_offset;
 | 
			
		||||
 | 
			
		||||
  guint           server_time_is_monotonic_time : 1;
 | 
			
		||||
  guint           show_redraw : 1;
 | 
			
		||||
  guint           debug       : 1;
 | 
			
		||||
  guint           no_mipmaps  : 1;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -30,9 +36,10 @@ struct _MetaCompScreen
 | 
			
		||||
{
 | 
			
		||||
  MetaScreen            *screen;
 | 
			
		||||
 | 
			
		||||
  ClutterActor          *stage, *window_group, *top_window_group;
 | 
			
		||||
  ClutterActor          *stage, *window_group, *top_window_group, *overlay_group;
 | 
			
		||||
  ClutterActor          *background_actor;
 | 
			
		||||
  GList                 *windows;
 | 
			
		||||
  GHashTable            *windows_by_xid;
 | 
			
		||||
  Window                 output;
 | 
			
		||||
 | 
			
		||||
  CoglOnscreen          *onscreen;
 | 
			
		||||
@@ -63,4 +70,6 @@ void     meta_end_modal_for_plugin   (MetaScreen       *screen,
 | 
			
		||||
gint64 meta_compositor_monotonic_time_to_server_time (MetaDisplay *display,
 | 
			
		||||
                                                      gint64       monotonic_time);
 | 
			
		||||
 | 
			
		||||
void meta_check_end_modal (MetaScreen *screen);
 | 
			
		||||
 | 
			
		||||
#endif /* META_COMPOSITOR_PRIVATE_H */
 | 
			
		||||
 
 | 
			
		||||
@@ -65,6 +65,7 @@
 | 
			
		||||
#include <meta/window.h>
 | 
			
		||||
#include "compositor-private.h"
 | 
			
		||||
#include <meta/compositor-mutter.h>
 | 
			
		||||
#include "xprops.h"
 | 
			
		||||
#include <meta/prefs.h>
 | 
			
		||||
#include <meta/main.h>
 | 
			
		||||
#include <meta/meta-background-actor.h>
 | 
			
		||||
@@ -76,16 +77,14 @@
 | 
			
		||||
#include "display-private.h" /* for meta_display_lookup_x_window() */
 | 
			
		||||
#include "util-private.h"
 | 
			
		||||
#include "frame.h"
 | 
			
		||||
#include "meta-wayland-private.h"
 | 
			
		||||
#include "meta-wayland-pointer.h"
 | 
			
		||||
#include "meta-wayland-keyboard.h"
 | 
			
		||||
#include <X11/extensions/shape.h>
 | 
			
		||||
#include <X11/extensions/Xcomposite.h>
 | 
			
		||||
 | 
			
		||||
#include "wayland/meta-wayland-private.h"
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
is_modal (MetaDisplay *display)
 | 
			
		||||
{
 | 
			
		||||
  return display->grab_op == META_GRAB_OP_COMPOSITOR;
 | 
			
		||||
}
 | 
			
		||||
/* #define DEBUG_TRACE g_print */
 | 
			
		||||
#define DEBUG_TRACE(X)
 | 
			
		||||
 | 
			
		||||
static inline gboolean
 | 
			
		||||
composite_at_least_version (MetaDisplay *display, int maj, int min)
 | 
			
		||||
@@ -110,8 +109,13 @@ meta_finish_workspace_switch (MetaCompScreen *info)
 | 
			
		||||
  for (l = info->windows; l; l = l->next)
 | 
			
		||||
    meta_window_actor_sync_visibility (l->data);
 | 
			
		||||
 | 
			
		||||
  /* Fix up stacking order. */
 | 
			
		||||
  /*
 | 
			
		||||
   * Fix up stacking order in case the plugin messed it up.
 | 
			
		||||
   */
 | 
			
		||||
  sync_actor_stacking (info);
 | 
			
		||||
 | 
			
		||||
/*   printf ("... FINISHED DESKTOP SWITCH\n"); */
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -137,12 +141,33 @@ meta_compositor_destroy (MetaCompositor *compositor)
 | 
			
		||||
  clutter_threads_remove_repaint_func (compositor->repaint_func_id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
add_win (MetaWindow *window)
 | 
			
		||||
{
 | 
			
		||||
  MetaScreen		*screen = meta_window_get_screen (window);
 | 
			
		||||
  MetaCompScreen        *info = meta_screen_get_compositor_data (screen);
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (info != NULL);
 | 
			
		||||
 | 
			
		||||
  meta_window_actor_new (window);
 | 
			
		||||
 | 
			
		||||
  sync_actor_stacking (info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
process_damage (MetaCompositor     *compositor,
 | 
			
		||||
                XDamageNotifyEvent *event,
 | 
			
		||||
                MetaWindow         *window)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
 | 
			
		||||
  MetaWindowActor *window_actor;
 | 
			
		||||
 | 
			
		||||
  if (window == NULL)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
 | 
			
		||||
  if (window_actor == NULL)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  meta_window_actor_process_x11_damage (window_actor, event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -347,6 +372,7 @@ begin_modal_x11 (MetaScreen       *screen,
 | 
			
		||||
  Display        *xdpy        = meta_display_get_xdisplay (display);
 | 
			
		||||
  MetaCompScreen *info        = meta_screen_get_compositor_data (screen);
 | 
			
		||||
  Window          grab_window = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
 | 
			
		||||
  Cursor          cursor      = None;
 | 
			
		||||
  int             result;
 | 
			
		||||
  gboolean        pointer_grabbed = FALSE;
 | 
			
		||||
  gboolean        keyboard_grabbed = FALSE;
 | 
			
		||||
@@ -366,7 +392,7 @@ begin_modal_x11 (MetaScreen       *screen,
 | 
			
		||||
                             META_VIRTUAL_CORE_POINTER_ID,
 | 
			
		||||
                             grab_window,
 | 
			
		||||
                             timestamp,
 | 
			
		||||
                             None,
 | 
			
		||||
                             cursor,
 | 
			
		||||
                             XIGrabModeAsync, XIGrabModeAsync,
 | 
			
		||||
                             False, /* owner_events */
 | 
			
		||||
                             &mask);
 | 
			
		||||
@@ -410,6 +436,45 @@ begin_modal_x11 (MetaScreen       *screen,
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
begin_modal_wayland (MetaScreen       *screen,
 | 
			
		||||
                     MetaPlugin       *plugin,
 | 
			
		||||
                     MetaModalOptions  options,
 | 
			
		||||
                     guint32           timestamp)
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandCompositor *compositor;
 | 
			
		||||
  gboolean pointer_grabbed = FALSE;
 | 
			
		||||
  gboolean keyboard_grabbed = FALSE;
 | 
			
		||||
 | 
			
		||||
  compositor = meta_wayland_compositor_get_default ();
 | 
			
		||||
 | 
			
		||||
  if ((options & META_MODAL_POINTER_ALREADY_GRABBED) == 0)
 | 
			
		||||
    {
 | 
			
		||||
      if (!meta_wayland_pointer_begin_modal (&compositor->seat->pointer))
 | 
			
		||||
        goto fail;
 | 
			
		||||
 | 
			
		||||
      pointer_grabbed = TRUE;
 | 
			
		||||
    }
 | 
			
		||||
  if ((options & META_MODAL_KEYBOARD_ALREADY_GRABBED) == 0)
 | 
			
		||||
    {
 | 
			
		||||
      if (!meta_wayland_keyboard_begin_modal (&compositor->seat->keyboard,
 | 
			
		||||
                                              timestamp))
 | 
			
		||||
        goto fail;
 | 
			
		||||
 | 
			
		||||
      keyboard_grabbed = TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
 | 
			
		||||
 fail:
 | 
			
		||||
  if (pointer_grabbed)
 | 
			
		||||
    meta_wayland_pointer_end_modal (&compositor->seat->pointer);
 | 
			
		||||
  if (keyboard_grabbed)
 | 
			
		||||
    meta_wayland_keyboard_end_modal (&compositor->seat->keyboard, timestamp);
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_begin_modal_for_plugin (MetaScreen       *screen,
 | 
			
		||||
                             MetaPlugin       *plugin,
 | 
			
		||||
@@ -420,14 +485,15 @@ meta_begin_modal_for_plugin (MetaScreen       *screen,
 | 
			
		||||
   * are significant differences in how we handle grabs that make it difficult to
 | 
			
		||||
   * merge the two.
 | 
			
		||||
   */
 | 
			
		||||
  MetaDisplay *display = meta_screen_get_display (screen);
 | 
			
		||||
  MetaDisplay    *display    = meta_screen_get_display (screen);
 | 
			
		||||
  MetaCompositor *compositor = display->compositor;
 | 
			
		||||
  gboolean ok;
 | 
			
		||||
 | 
			
		||||
  if (is_modal (display) || display->grab_op != META_GRAB_OP_NONE)
 | 
			
		||||
  if (compositor->modal_plugin != NULL || display->grab_op != META_GRAB_OP_NONE)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  if (meta_is_wayland_compositor ())
 | 
			
		||||
    ok = TRUE;
 | 
			
		||||
    ok = begin_modal_wayland (screen, plugin, options, timestamp);
 | 
			
		||||
  else
 | 
			
		||||
    ok = begin_modal_x11 (screen, plugin, options, timestamp);
 | 
			
		||||
  if (!ok)
 | 
			
		||||
@@ -439,6 +505,8 @@ meta_begin_modal_for_plugin (MetaScreen       *screen,
 | 
			
		||||
  display->grab_have_pointer = TRUE;
 | 
			
		||||
  display->grab_have_keyboard = TRUE;
 | 
			
		||||
 | 
			
		||||
  compositor->modal_plugin = plugin;
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -447,12 +515,21 @@ meta_end_modal_for_plugin (MetaScreen     *screen,
 | 
			
		||||
                           MetaPlugin     *plugin,
 | 
			
		||||
                           guint32         timestamp)
 | 
			
		||||
{
 | 
			
		||||
  MetaDisplay *display = meta_screen_get_display (screen);
 | 
			
		||||
  Display *xdpy = meta_display_get_xdisplay (display);
 | 
			
		||||
  MetaDisplay    *display    = meta_screen_get_display (screen);
 | 
			
		||||
  Display        *xdpy = meta_display_get_xdisplay (display);
 | 
			
		||||
  MetaCompositor *compositor = display->compositor;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (is_modal (display));
 | 
			
		||||
  g_return_if_fail (compositor->modal_plugin == plugin);
 | 
			
		||||
 | 
			
		||||
  if (!meta_is_wayland_compositor ())
 | 
			
		||||
  if (meta_is_wayland_compositor ())
 | 
			
		||||
    {
 | 
			
		||||
      MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
 | 
			
		||||
 | 
			
		||||
      meta_wayland_pointer_end_modal (&compositor->seat->pointer);
 | 
			
		||||
      meta_wayland_keyboard_end_modal (&compositor->seat->keyboard,
 | 
			
		||||
                                       timestamp);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      XIUngrabDevice (xdpy, META_VIRTUAL_CORE_POINTER_ID, timestamp);
 | 
			
		||||
      XIUngrabDevice (xdpy, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
 | 
			
		||||
@@ -463,6 +540,27 @@ meta_end_modal_for_plugin (MetaScreen     *screen,
 | 
			
		||||
  display->grab_screen = NULL;
 | 
			
		||||
  display->grab_have_pointer = FALSE;
 | 
			
		||||
  display->grab_have_keyboard = FALSE;
 | 
			
		||||
 | 
			
		||||
  compositor->modal_plugin = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This is used when reloading plugins to make sure we don't have
 | 
			
		||||
 * a left-over modal grab for this screen.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
meta_check_end_modal (MetaScreen *screen)
 | 
			
		||||
{
 | 
			
		||||
  MetaDisplay    *display    = meta_screen_get_display (screen);
 | 
			
		||||
  MetaCompositor *compositor = display->compositor;
 | 
			
		||||
 | 
			
		||||
  if (compositor->modal_plugin &&
 | 
			
		||||
      meta_plugin_get_screen (compositor->modal_plugin) == screen)
 | 
			
		||||
    {
 | 
			
		||||
      meta_end_modal_for_plugin (screen,
 | 
			
		||||
                                   compositor->modal_plugin,
 | 
			
		||||
 | 
			
		||||
                                 CurrentTime);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -664,25 +762,18 @@ meta_compositor_unmanage_screen (MetaCompositor *compositor,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_shape_cow_for_window:
 | 
			
		||||
 * @screen: A #MetaScreen
 | 
			
		||||
 * @window: (allow-none): A #MetaWindow to shape the COW for
 | 
			
		||||
 *
 | 
			
		||||
 * Sets an bounding shape on the COW so that the given window
 | 
			
		||||
 * is exposed. If @window is %NULL it clears the shape again.
 | 
			
		||||
 *
 | 
			
		||||
 * Used so we can unredirect windows, by shaping away the part
 | 
			
		||||
 * of the COW, letting the raw window be seen through below.
 | 
			
		||||
/*
 | 
			
		||||
 * Shapes the cow so that the given window is exposed,
 | 
			
		||||
 * when metaWindow is NULL it clears the shape again
 | 
			
		||||
 */
 | 
			
		||||
static void
 | 
			
		||||
meta_shape_cow_for_window (MetaScreen *screen,
 | 
			
		||||
                           MetaWindow *window)
 | 
			
		||||
                           MetaWindow *metaWindow)
 | 
			
		||||
{
 | 
			
		||||
  MetaCompScreen *info = meta_screen_get_compositor_data (screen);
 | 
			
		||||
  Display *xdisplay = meta_display_get_xdisplay (meta_screen_get_display (screen));
 | 
			
		||||
 | 
			
		||||
  if (window == NULL)
 | 
			
		||||
  if (metaWindow == NULL)
 | 
			
		||||
      XFixesSetWindowShapeRegion (xdisplay, info->output, ShapeBounding, 0, 0, None);
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
@@ -691,7 +782,7 @@ meta_shape_cow_for_window (MetaScreen *screen,
 | 
			
		||||
      int width, height;
 | 
			
		||||
      MetaRectangle rect;
 | 
			
		||||
 | 
			
		||||
      meta_window_get_frame_rect (window, &rect);
 | 
			
		||||
      meta_window_get_frame_rect (metaWindow, &rect);
 | 
			
		||||
 | 
			
		||||
      window_bounds.x = rect.x;
 | 
			
		||||
      window_bounds.y = rect.y;
 | 
			
		||||
@@ -742,12 +833,11 @@ meta_compositor_add_window (MetaCompositor    *compositor,
 | 
			
		||||
{
 | 
			
		||||
  MetaScreen *screen = meta_window_get_screen (window);
 | 
			
		||||
  MetaDisplay *display = meta_screen_get_display (screen);
 | 
			
		||||
  MetaCompScreen *info = meta_screen_get_compositor_data (screen);
 | 
			
		||||
 | 
			
		||||
  DEBUG_TRACE ("meta_compositor_add_window\n");
 | 
			
		||||
  meta_error_trap_push (display);
 | 
			
		||||
 | 
			
		||||
  meta_window_actor_new (window);
 | 
			
		||||
  sync_actor_stacking (info);
 | 
			
		||||
  add_win (window);
 | 
			
		||||
 | 
			
		||||
  meta_error_trap_pop (display);
 | 
			
		||||
}
 | 
			
		||||
@@ -756,9 +846,17 @@ void
 | 
			
		||||
meta_compositor_remove_window (MetaCompositor *compositor,
 | 
			
		||||
                               MetaWindow     *window)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
 | 
			
		||||
  MetaScreen *screen = meta_window_get_screen (window);
 | 
			
		||||
  MetaCompScreen *info = meta_screen_get_compositor_data (screen);
 | 
			
		||||
  MetaWindowActor         *window_actor     = NULL;
 | 
			
		||||
  MetaScreen *screen;
 | 
			
		||||
  MetaCompScreen *info;
 | 
			
		||||
 | 
			
		||||
  DEBUG_TRACE ("meta_compositor_remove_window\n");
 | 
			
		||||
  window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
 | 
			
		||||
  if (!window_actor)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  screen = meta_window_get_screen (window);
 | 
			
		||||
  info = meta_screen_get_compositor_data (screen);
 | 
			
		||||
 | 
			
		||||
  if (info->unredirected_window == window)
 | 
			
		||||
    set_unredirected_window (info, NULL);
 | 
			
		||||
@@ -771,7 +869,13 @@ meta_compositor_set_updates_frozen (MetaCompositor *compositor,
 | 
			
		||||
                                    MetaWindow     *window,
 | 
			
		||||
                                    gboolean        updates_frozen)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
 | 
			
		||||
  MetaWindowActor *window_actor;
 | 
			
		||||
 | 
			
		||||
  DEBUG_TRACE ("meta_compositor_set_updates_frozen\n");
 | 
			
		||||
  window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
 | 
			
		||||
  if (!window_actor)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  meta_window_actor_set_updates_frozen (window_actor, updates_frozen);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -780,7 +884,13 @@ meta_compositor_queue_frame_drawn (MetaCompositor *compositor,
 | 
			
		||||
                                   MetaWindow     *window,
 | 
			
		||||
                                   gboolean        no_delay_frame)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
 | 
			
		||||
  MetaWindowActor *window_actor;
 | 
			
		||||
 | 
			
		||||
  DEBUG_TRACE ("meta_compositor_queue_frame_drawn\n");
 | 
			
		||||
  window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
 | 
			
		||||
  if (!window_actor)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  meta_window_actor_queue_frame_drawn (window_actor, no_delay_frame);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -960,9 +1070,9 @@ meta_compositor_process_event (MetaCompositor *compositor,
 | 
			
		||||
 | 
			
		||||
  info = meta_screen_get_compositor_data (screen);
 | 
			
		||||
 | 
			
		||||
  if (is_modal (display) && is_grabbed_event (compositor->display, event))
 | 
			
		||||
  if (compositor->modal_plugin && is_grabbed_event (compositor->display, event))
 | 
			
		||||
    {
 | 
			
		||||
      meta_plugin_manager_xevent_filter (info->plugin_mgr, event);
 | 
			
		||||
      _meta_plugin_xevent_filter (compositor->modal_plugin, event);
 | 
			
		||||
 | 
			
		||||
      /* We always consume events even if the plugin says it didn't handle them;
 | 
			
		||||
       * exclusive is exclusive */
 | 
			
		||||
@@ -973,7 +1083,10 @@ meta_compositor_process_event (MetaCompositor *compositor,
 | 
			
		||||
    maybe_spoof_event_as_stage_event (info, window, event);
 | 
			
		||||
 | 
			
		||||
  if (meta_plugin_manager_xevent_filter (info->plugin_mgr, event))
 | 
			
		||||
    return TRUE;
 | 
			
		||||
    {
 | 
			
		||||
      DEBUG_TRACE ("meta_compositor_process_event (filtered,window==NULL)\n");
 | 
			
		||||
      return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (!meta_is_wayland_compositor () &&
 | 
			
		||||
      event->type == meta_display_get_damage_event_base (compositor->display) + XDamageNotify)
 | 
			
		||||
@@ -987,6 +1100,7 @@ meta_compositor_process_event (MetaCompositor *compositor,
 | 
			
		||||
          window = meta_display_lookup_x_window (compositor->display, xwin);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      DEBUG_TRACE ("meta_compositor_process_event (process_damage)\n");
 | 
			
		||||
      process_damage (compositor, (XDamageNotifyEvent *) event, window);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1008,7 +1122,11 @@ meta_compositor_filter_keybinding (MetaCompositor *compositor,
 | 
			
		||||
                                   MetaKeyBinding *binding)
 | 
			
		||||
{
 | 
			
		||||
  MetaCompScreen *info = meta_screen_get_compositor_data (screen);
 | 
			
		||||
  return meta_plugin_manager_filter_keybinding (info->plugin_mgr, binding);
 | 
			
		||||
 | 
			
		||||
  if (info->plugin_mgr)
 | 
			
		||||
    return meta_plugin_manager_filter_keybinding (info->plugin_mgr, binding);
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -1017,7 +1135,11 @@ meta_compositor_show_window (MetaCompositor *compositor,
 | 
			
		||||
                             MetaCompEffect  effect)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
 | 
			
		||||
 meta_window_actor_show (window_actor, effect);
 | 
			
		||||
  DEBUG_TRACE ("meta_compositor_show_window\n");
 | 
			
		||||
  if (!window_actor)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  meta_window_actor_show (window_actor, effect);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -1026,6 +1148,10 @@ meta_compositor_hide_window (MetaCompositor *compositor,
 | 
			
		||||
                             MetaCompEffect  effect)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
 | 
			
		||||
  DEBUG_TRACE ("meta_compositor_hide_window\n");
 | 
			
		||||
  if (!window_actor)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  meta_window_actor_hide (window_actor, effect);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1036,6 +1162,10 @@ meta_compositor_maximize_window (MetaCompositor    *compositor,
 | 
			
		||||
				 MetaRectangle	   *new_rect)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
 | 
			
		||||
  DEBUG_TRACE ("meta_compositor_maximize_window\n");
 | 
			
		||||
  if (!window_actor)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  meta_window_actor_maximize (window_actor, old_rect, new_rect);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1046,6 +1176,10 @@ meta_compositor_unmaximize_window (MetaCompositor    *compositor,
 | 
			
		||||
				   MetaRectangle     *new_rect)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
 | 
			
		||||
  DEBUG_TRACE ("meta_compositor_unmaximize_window\n");
 | 
			
		||||
  if (!window_actor)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  meta_window_actor_unmaximize (window_actor, old_rect, new_rect);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1063,14 +1197,18 @@ meta_compositor_switch_workspace (MetaCompositor     *compositor,
 | 
			
		||||
  to_indx   = meta_workspace_index (to);
 | 
			
		||||
  from_indx = meta_workspace_index (from);
 | 
			
		||||
 | 
			
		||||
  DEBUG_TRACE ("meta_compositor_switch_workspace\n");
 | 
			
		||||
 | 
			
		||||
  if (!info) /* During startup before manage_screen() */
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  info->switch_workspace_in_progress++;
 | 
			
		||||
 | 
			
		||||
  if (!meta_plugin_manager_switch_workspace (info->plugin_mgr,
 | 
			
		||||
                                             from_indx, to_indx,
 | 
			
		||||
                                             direction))
 | 
			
		||||
  if (!info->plugin_mgr ||
 | 
			
		||||
      !meta_plugin_manager_switch_workspace (info->plugin_mgr,
 | 
			
		||||
					       from_indx,
 | 
			
		||||
					       to_indx,
 | 
			
		||||
					       direction))
 | 
			
		||||
    {
 | 
			
		||||
      info->switch_workspace_in_progress--;
 | 
			
		||||
 | 
			
		||||
@@ -1179,6 +1317,8 @@ meta_compositor_sync_stack (MetaCompositor  *compositor,
 | 
			
		||||
  GList *old_stack;
 | 
			
		||||
  MetaCompScreen *info = meta_screen_get_compositor_data (screen);
 | 
			
		||||
 | 
			
		||||
  DEBUG_TRACE ("meta_compositor_sync_stack\n");
 | 
			
		||||
 | 
			
		||||
  /* This is painful because hidden windows that we are in the process
 | 
			
		||||
   * of animating out of existence. They'll be at the bottom of the
 | 
			
		||||
   * stack of X windows, but we want to leave them in their old position
 | 
			
		||||
@@ -1267,6 +1407,15 @@ meta_compositor_sync_window_geometry (MetaCompositor *compositor,
 | 
			
		||||
                                      gboolean did_placement)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
 | 
			
		||||
  MetaScreen      *screen = meta_window_get_screen (window);
 | 
			
		||||
  MetaCompScreen  *info = meta_screen_get_compositor_data (screen);
 | 
			
		||||
 | 
			
		||||
  DEBUG_TRACE ("meta_compositor_sync_window_geometry\n");
 | 
			
		||||
  g_return_if_fail (info);
 | 
			
		||||
 | 
			
		||||
  if (!window_actor)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  meta_window_actor_sync_actor_geometry (window_actor, did_placement);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1298,6 +1447,7 @@ meta_compositor_sync_screen_size (MetaCompositor  *compositor,
 | 
			
		||||
      Display        *xdisplay;
 | 
			
		||||
      Window          xwin;
 | 
			
		||||
 | 
			
		||||
      DEBUG_TRACE ("meta_compositor_sync_screen_size\n");
 | 
			
		||||
      g_return_if_fail (info);
 | 
			
		||||
 | 
			
		||||
      xdisplay = meta_display_get_xdisplay (display);
 | 
			
		||||
@@ -1601,6 +1751,10 @@ meta_compositor_show_tile_preview (MetaCompositor *compositor,
 | 
			
		||||
                                   int             tile_monitor_number)
 | 
			
		||||
{
 | 
			
		||||
  MetaCompScreen *info = meta_screen_get_compositor_data (screen);
 | 
			
		||||
 | 
			
		||||
  if (!info->plugin_mgr)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  meta_plugin_manager_show_tile_preview (info->plugin_mgr,
 | 
			
		||||
                                         window, tile_rect, tile_monitor_number);
 | 
			
		||||
}
 | 
			
		||||
@@ -1610,5 +1764,9 @@ meta_compositor_hide_tile_preview (MetaCompositor *compositor,
 | 
			
		||||
                                   MetaScreen     *screen)
 | 
			
		||||
{
 | 
			
		||||
  MetaCompScreen *info = meta_screen_get_compositor_data (screen);
 | 
			
		||||
 | 
			
		||||
  if (!info->plugin_mgr)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  meta_plugin_manager_hide_tile_preview (info->plugin_mgr);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -100,9 +100,7 @@ meta_plugin_manager_new (MetaScreen *screen)
 | 
			
		||||
 | 
			
		||||
  plugin_mgr = g_new0 (MetaPluginManager, 1);
 | 
			
		||||
  plugin_mgr->screen = screen;
 | 
			
		||||
  plugin_mgr->plugin = plugin = g_object_new (plugin_type, NULL);
 | 
			
		||||
 | 
			
		||||
  _meta_plugin_set_screen (plugin, screen);
 | 
			
		||||
  plugin_mgr->plugin = plugin = g_object_new (plugin_type, "screen", screen, NULL);
 | 
			
		||||
 | 
			
		||||
  klass = META_PLUGIN_GET_CLASS (plugin);
 | 
			
		||||
 | 
			
		||||
@@ -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;
 | 
			
		||||
@@ -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);
 | 
			
		||||
@@ -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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -47,15 +47,91 @@ G_DEFINE_ABSTRACT_TYPE (MetaPlugin, meta_plugin, G_TYPE_OBJECT);
 | 
			
		||||
#define META_PLUGIN_GET_PRIVATE(obj) \
 | 
			
		||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_PLUGIN, MetaPluginPrivate))
 | 
			
		||||
 | 
			
		||||
enum
 | 
			
		||||
{
 | 
			
		||||
  PROP_0,
 | 
			
		||||
  PROP_SCREEN,
 | 
			
		||||
  PROP_DEBUG_MODE,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaPluginPrivate
 | 
			
		||||
{
 | 
			
		||||
  MetaScreen *screen;
 | 
			
		||||
  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 +140,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 +167,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)
 | 
			
		||||
@@ -101,8 +208,15 @@ void
 | 
			
		||||
meta_plugin_switch_workspace_completed (MetaPlugin *plugin)
 | 
			
		||||
{
 | 
			
		||||
  MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
 | 
			
		||||
 | 
			
		||||
  MetaScreen *screen = priv->screen;
 | 
			
		||||
 | 
			
		||||
  if (priv->running-- < 0)
 | 
			
		||||
    {
 | 
			
		||||
      g_warning ("Error in running effect accounting, adjusting.");
 | 
			
		||||
      priv->running = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_switch_workspace_completed (screen);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -111,6 +225,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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -205,7 +339,9 @@ meta_plugin_end_modal (MetaPlugin *plugin,
 | 
			
		||||
 * 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
 | 
			
		||||
 */
 | 
			
		||||
@@ -217,15 +353,6 @@ meta_plugin_get_screen (MetaPlugin *plugin)
 | 
			
		||||
  return priv->screen;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
_meta_plugin_set_screen (MetaPlugin *plugin,
 | 
			
		||||
                         MetaScreen *screen)
 | 
			
		||||
{
 | 
			
		||||
  MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
 | 
			
		||||
 | 
			
		||||
  priv->screen = screen;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_plugin_complete_display_change (MetaPlugin *plugin,
 | 
			
		||||
                                     gboolean    ok)
 | 
			
		||||
 
 | 
			
		||||
@@ -28,8 +28,7 @@
 | 
			
		||||
 | 
			
		||||
#include <cogl/cogl-wayland-server.h>
 | 
			
		||||
#include "meta-shaped-texture-private.h"
 | 
			
		||||
 | 
			
		||||
#include "wayland/meta-wayland-private.h"
 | 
			
		||||
#include "meta-wayland-private.h"
 | 
			
		||||
 | 
			
		||||
struct _MetaSurfaceActorWaylandPrivate
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,7 @@
 | 
			
		||||
 | 
			
		||||
#include "meta-surface-actor.h"
 | 
			
		||||
 | 
			
		||||
#include "wayland/meta-wayland.h"
 | 
			
		||||
#include "meta-wayland.h"
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,7 @@
 | 
			
		||||
#include "frame.h"
 | 
			
		||||
#include <meta/window.h>
 | 
			
		||||
#include <meta/meta-shaped-texture.h>
 | 
			
		||||
#include "xprops.h"
 | 
			
		||||
 | 
			
		||||
#include "compositor-private.h"
 | 
			
		||||
#include "meta-shaped-texture-private.h"
 | 
			
		||||
@@ -29,12 +30,11 @@
 | 
			
		||||
#include "region-utils.h"
 | 
			
		||||
#include "monitor-private.h"
 | 
			
		||||
#include "meta-cullable.h"
 | 
			
		||||
#include "meta-wayland-private.h"
 | 
			
		||||
 | 
			
		||||
#include "meta-surface-actor.h"
 | 
			
		||||
#include "meta-surface-actor-x11.h"
 | 
			
		||||
 | 
			
		||||
#include "wayland/meta-wayland-surface.h"
 | 
			
		||||
 | 
			
		||||
struct _MetaWindowActorPrivate
 | 
			
		||||
{
 | 
			
		||||
  MetaWindow       *window;
 | 
			
		||||
@@ -714,7 +714,7 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
 | 
			
		||||
  /* Leaving out shadows for maximized and fullscreen windows is an effeciency
 | 
			
		||||
   * win and also prevents the unsightly effect of the shadow of maximized
 | 
			
		||||
   * window appearing on an adjacent window */
 | 
			
		||||
  if ((meta_window_get_maximized (priv->window) == META_MAXIMIZE_BOTH) ||
 | 
			
		||||
  if ((meta_window_get_maximized (priv->window) == (META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL)) ||
 | 
			
		||||
      meta_window_is_fullscreen (priv->window))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
@@ -968,6 +968,9 @@ start_simple_effect (MetaWindowActor *self,
 | 
			
		||||
  gint *counter = NULL;
 | 
			
		||||
  gboolean use_freeze_thaw = FALSE;
 | 
			
		||||
 | 
			
		||||
  if (!info->plugin_mgr)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  switch (event)
 | 
			
		||||
  {
 | 
			
		||||
  case META_PLUGIN_MINIMIZE:
 | 
			
		||||
@@ -1296,7 +1299,8 @@ meta_window_actor_maximize (MetaWindowActor    *self,
 | 
			
		||||
  self->priv->maximize_in_progress++;
 | 
			
		||||
  meta_window_actor_freeze (self);
 | 
			
		||||
 | 
			
		||||
  if (!meta_plugin_manager_event_maximize (info->plugin_mgr,
 | 
			
		||||
  if (!info->plugin_mgr ||
 | 
			
		||||
      !meta_plugin_manager_event_maximize (info->plugin_mgr,
 | 
			
		||||
                                           self,
 | 
			
		||||
                                           META_PLUGIN_MAXIMIZE,
 | 
			
		||||
                                           new_rect->x, new_rect->y,
 | 
			
		||||
@@ -1324,7 +1328,8 @@ meta_window_actor_unmaximize (MetaWindowActor   *self,
 | 
			
		||||
  self->priv->unmaximize_in_progress++;
 | 
			
		||||
  meta_window_actor_freeze (self);
 | 
			
		||||
 | 
			
		||||
  if (!meta_plugin_manager_event_maximize (info->plugin_mgr,
 | 
			
		||||
  if (!info->plugin_mgr ||
 | 
			
		||||
      !meta_plugin_manager_event_maximize (info->plugin_mgr,
 | 
			
		||||
                                           self,
 | 
			
		||||
                                           META_PLUGIN_UNMAXIMIZE,
 | 
			
		||||
                                           new_rect->x, new_rect->y,
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -82,7 +164,12 @@ bell_flash_fullscreen (MetaDisplay *display,
 | 
			
		||||
    {
 | 
			
		||||
      screen = meta_display_screen_for_xwindow (display, xkb_bell_ev->window);
 | 
			
		||||
      if (screen)
 | 
			
		||||
        meta_compositor_flash_screen (display->compositor, screen);
 | 
			
		||||
        {
 | 
			
		||||
          if (display->compositor)
 | 
			
		||||
            meta_compositor_flash_screen (display->compositor, screen);
 | 
			
		||||
          else
 | 
			
		||||
            bell_flash_screen (display, screen);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  else 
 | 
			
		||||
    {
 | 
			
		||||
@@ -90,7 +177,10 @@ bell_flash_fullscreen (MetaDisplay *display,
 | 
			
		||||
      while (screen_list) 
 | 
			
		||||
	{
 | 
			
		||||
	  screen = (MetaScreen *) screen_list->data;
 | 
			
		||||
          meta_compositor_flash_screen (display->compositor, screen);
 | 
			
		||||
          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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -718,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);
 | 
			
		||||
@@ -261,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);
 | 
			
		||||
 
 | 
			
		||||
@@ -36,11 +36,15 @@
 | 
			
		||||
#include <meta/main.h>
 | 
			
		||||
#include "screen-private.h"
 | 
			
		||||
#include "window-private.h"
 | 
			
		||||
#include "window-x11.h"
 | 
			
		||||
#include "window-props.h"
 | 
			
		||||
#include "group-props.h"
 | 
			
		||||
#include "frame.h"
 | 
			
		||||
#include <meta/errors.h>
 | 
			
		||||
#include "keybindings-private.h"
 | 
			
		||||
#include <meta/prefs.h>
 | 
			
		||||
#include "resizepopup.h"
 | 
			
		||||
#include "xprops.h"
 | 
			
		||||
#include "workspace-private.h"
 | 
			
		||||
#include "bell.h"
 | 
			
		||||
#include <meta/compositor.h>
 | 
			
		||||
@@ -68,12 +72,7 @@
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include "x11/window-x11.h"
 | 
			
		||||
#include "x11/window-props.h"
 | 
			
		||||
#include "x11/group-props.h"
 | 
			
		||||
#include "x11/xprops.h"
 | 
			
		||||
 | 
			
		||||
#include "wayland/meta-xwayland-private.h"
 | 
			
		||||
#include "meta-xwayland-private.h"
 | 
			
		||||
#include "meta-surface-actor-wayland.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@@ -176,6 +175,8 @@ static void    prefs_changed_callback    (MetaPreference pref,
 | 
			
		||||
 | 
			
		||||
static void    sanity_check_timestamps   (MetaDisplay *display,
 | 
			
		||||
                                          guint32      known_good_timestamp);
 | 
			
		||||
 
 | 
			
		||||
MetaGroup*     get_focussed_group (MetaDisplay *display);
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_display_get_property(GObject         *object,
 | 
			
		||||
@@ -1294,6 +1295,10 @@ meta_get_display (void)
 | 
			
		||||
  return the_display;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef WITH_VERBOSE_MODE
 | 
			
		||||
static gboolean dump_events = TRUE;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
grab_op_is_mouse_only (MetaGrabOp op)
 | 
			
		||||
{
 | 
			
		||||
@@ -1413,20 +1418,6 @@ meta_grab_op_is_moving (MetaGrabOp op)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
grab_op_should_block_mouse_events (MetaGrabOp op)
 | 
			
		||||
{
 | 
			
		||||
  switch (op)
 | 
			
		||||
    {
 | 
			
		||||
    case META_GRAB_OP_WAYLAND_CLIENT:
 | 
			
		||||
    case META_GRAB_OP_COMPOSITOR:
 | 
			
		||||
      return TRUE;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_display_xserver_time_is_before:
 | 
			
		||||
 * @display: a #MetaDisplay
 | 
			
		||||
@@ -2063,7 +2054,7 @@ meta_display_handle_event (MetaDisplay        *display,
 | 
			
		||||
  switch (event->type)
 | 
			
		||||
    {
 | 
			
		||||
    case CLUTTER_BUTTON_PRESS:
 | 
			
		||||
      if (grab_op_should_block_mouse_events (display->grab_op))
 | 
			
		||||
      if (display->grab_op == META_GRAB_OP_COMPOSITOR)
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      display->overlay_key_only_pressed = FALSE;
 | 
			
		||||
@@ -2235,7 +2226,7 @@ meta_display_handle_event (MetaDisplay        *display,
 | 
			
		||||
        }
 | 
			
		||||
      break;
 | 
			
		||||
    case CLUTTER_BUTTON_RELEASE:
 | 
			
		||||
      if (grab_op_should_block_mouse_events (display->grab_op))
 | 
			
		||||
      if (display->grab_op == META_GRAB_OP_COMPOSITOR)
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      display->overlay_key_only_pressed = FALSE;
 | 
			
		||||
@@ -2249,7 +2240,7 @@ meta_display_handle_event (MetaDisplay        *display,
 | 
			
		||||
        }
 | 
			
		||||
      break;
 | 
			
		||||
    case CLUTTER_MOTION:
 | 
			
		||||
      if (grab_op_should_block_mouse_events (display->grab_op))
 | 
			
		||||
      if (display->grab_op == META_GRAB_OP_COMPOSITOR)
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
      if (display->grab_window == window &&
 | 
			
		||||
@@ -2283,10 +2274,6 @@ meta_display_handle_event (MetaDisplay        *display,
 | 
			
		||||
  if (display->grab_op == META_GRAB_OP_COMPOSITOR)
 | 
			
		||||
    bypass_wayland = TRUE;
 | 
			
		||||
 | 
			
		||||
  /* If a Wayland client has a grab, don't pass that through to Clutter */
 | 
			
		||||
  if (display->grab_op == META_GRAB_OP_WAYLAND_CLIENT)
 | 
			
		||||
    bypass_clutter = TRUE;
 | 
			
		||||
 | 
			
		||||
  if (compositor && !bypass_wayland)
 | 
			
		||||
    {
 | 
			
		||||
      if (meta_wayland_compositor_handle_event (compositor, event))
 | 
			
		||||
@@ -2620,7 +2607,7 @@ handle_other_xevent (MetaDisplay *display,
 | 
			
		||||
      /* NB: override redirect windows wont cause a map request so we
 | 
			
		||||
       * watch out for map notifies against any root windows too if a
 | 
			
		||||
       * compositor is enabled: */
 | 
			
		||||
      if (window == NULL
 | 
			
		||||
      if (display->compositor && window == NULL
 | 
			
		||||
          && meta_display_screen_for_root (display, event->xmap.event))
 | 
			
		||||
        {
 | 
			
		||||
          window = meta_window_x11_new (display, event->xmap.window,
 | 
			
		||||
@@ -2675,7 +2662,7 @@ handle_other_xevent (MetaDisplay *display,
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (window && window->override_redirect)
 | 
			
		||||
        meta_window_x11_configure_notify (window, &event->xconfigure);
 | 
			
		||||
        meta_window_configure_notify (window, &event->xconfigure);
 | 
			
		||||
 | 
			
		||||
      break;
 | 
			
		||||
    case ConfigureRequest:
 | 
			
		||||
@@ -2987,8 +2974,9 @@ meta_display_handle_xevent (MetaDisplay *display,
 | 
			
		||||
  MetaMonitorManager *monitor;
 | 
			
		||||
  MetaScreen *screen;
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
  meta_spew_event (display, event);
 | 
			
		||||
#ifdef WITH_VERBOSE_MODE
 | 
			
		||||
  if (dump_events)
 | 
			
		||||
    meta_spew_event (display, event);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_STARTUP_NOTIFICATION
 | 
			
		||||
@@ -3084,7 +3072,7 @@ meta_display_handle_xevent (MetaDisplay *display,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 out:
 | 
			
		||||
  if (!bypass_compositor)
 | 
			
		||||
  if (display->compositor && !bypass_compositor)
 | 
			
		||||
    {
 | 
			
		||||
      MetaWindow *window = modified != None ? meta_display_lookup_x_window (display, modified) : NULL;
 | 
			
		||||
 | 
			
		||||
@@ -3264,7 +3252,8 @@ event_get_time (MetaDisplay *display,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
G_GNUC_UNUSED const char*
 | 
			
		||||
#ifdef WITH_VERBOSE_MODE
 | 
			
		||||
const char*
 | 
			
		||||
meta_event_detail_to_string (int d)
 | 
			
		||||
{
 | 
			
		||||
  const char *detail = "???";
 | 
			
		||||
@@ -3300,8 +3289,10 @@ meta_event_detail_to_string (int d)
 | 
			
		||||
 | 
			
		||||
  return detail;
 | 
			
		||||
}
 | 
			
		||||
#endif /* WITH_VERBOSE_MODE */
 | 
			
		||||
 | 
			
		||||
G_GNUC_UNUSED const char*
 | 
			
		||||
#ifdef WITH_VERBOSE_MODE
 | 
			
		||||
const char*
 | 
			
		||||
meta_event_mode_to_string (int m)
 | 
			
		||||
{
 | 
			
		||||
  const char *mode = "???";
 | 
			
		||||
@@ -3323,8 +3314,10 @@ meta_event_mode_to_string (int m)
 | 
			
		||||
 | 
			
		||||
  return mode;
 | 
			
		||||
}
 | 
			
		||||
#endif /* WITH_VERBOSE_MODE */
 | 
			
		||||
 | 
			
		||||
G_GNUC_UNUSED static const char*
 | 
			
		||||
#ifdef WITH_VERBOSE_MODE
 | 
			
		||||
static const char*
 | 
			
		||||
stack_mode_to_string (int mode)
 | 
			
		||||
{
 | 
			
		||||
  switch (mode)
 | 
			
		||||
@@ -3343,9 +3336,11 @@ stack_mode_to_string (int mode)
 | 
			
		||||
 | 
			
		||||
  return "Unknown";
 | 
			
		||||
}
 | 
			
		||||
#endif /* WITH_VERBOSE_MODE */
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_XSYNC
 | 
			
		||||
G_GNUC_UNUSED static gint64
 | 
			
		||||
#ifdef WITH_VERBOSE_MODE
 | 
			
		||||
static gint64
 | 
			
		||||
sync_value_to_64 (const XSyncValue *value)
 | 
			
		||||
{
 | 
			
		||||
  gint64 v;
 | 
			
		||||
@@ -3355,8 +3350,10 @@ sync_value_to_64 (const XSyncValue *value)
 | 
			
		||||
  
 | 
			
		||||
  return v;
 | 
			
		||||
}
 | 
			
		||||
#endif /* WITH_VERBOSE_MODE */
 | 
			
		||||
 | 
			
		||||
G_GNUC_UNUSED static const char*
 | 
			
		||||
#ifdef WITH_VERBOSE_MODE
 | 
			
		||||
static const char*
 | 
			
		||||
alarm_state_to_string (XSyncAlarmState state)
 | 
			
		||||
{
 | 
			
		||||
  switch (state)
 | 
			
		||||
@@ -3371,9 +3368,12 @@ alarm_state_to_string (XSyncAlarmState state)
 | 
			
		||||
      return "(unknown)";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif /* WITH_VERBOSE_MODE */
 | 
			
		||||
 | 
			
		||||
#endif /* HAVE_XSYNC */
 | 
			
		||||
 | 
			
		||||
G_GNUC_UNUSED static void
 | 
			
		||||
#ifdef WITH_VERBOSE_MODE
 | 
			
		||||
static void
 | 
			
		||||
meta_spew_xi2_event (MetaDisplay *display,
 | 
			
		||||
                     XIEvent     *input_event,
 | 
			
		||||
                     const char **name_p,
 | 
			
		||||
@@ -3433,7 +3433,7 @@ meta_spew_xi2_event (MetaDisplay *display,
 | 
			
		||||
  *extra_p = extra;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
G_GNUC_UNUSED static void
 | 
			
		||||
static void
 | 
			
		||||
meta_spew_core_event (MetaDisplay *display,
 | 
			
		||||
                      XEvent      *event,
 | 
			
		||||
                      const char **name_p,
 | 
			
		||||
@@ -3657,7 +3657,7 @@ meta_spew_core_event (MetaDisplay *display,
 | 
			
		||||
  *extra_p = extra;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
G_GNUC_UNUSED static void
 | 
			
		||||
static void
 | 
			
		||||
meta_spew_event (MetaDisplay *display,
 | 
			
		||||
                 XEvent      *event)
 | 
			
		||||
{
 | 
			
		||||
@@ -3666,6 +3666,9 @@ meta_spew_event (MetaDisplay *display,
 | 
			
		||||
  char *winname;
 | 
			
		||||
  MetaScreen *screen;
 | 
			
		||||
  XIEvent *input_event;
 | 
			
		||||
 | 
			
		||||
  if (!meta_is_verbose())
 | 
			
		||||
    return;
 | 
			
		||||
  
 | 
			
		||||
  /* filter overnumerous events */
 | 
			
		||||
  if (event->type == Expose || event->type == MotionNotify ||
 | 
			
		||||
@@ -3695,16 +3698,18 @@ meta_spew_event (MetaDisplay *display,
 | 
			
		||||
  else
 | 
			
		||||
    winname = g_strdup_printf ("0x%lx", event->xany.window);
 | 
			
		||||
 | 
			
		||||
  g_print ("%s on %s%s %s %sserial %lu\n", name, winname,
 | 
			
		||||
           extra ? ":" : "", extra ? extra : "",
 | 
			
		||||
           event->xany.send_event ? "SEND " : "",
 | 
			
		||||
           event->xany.serial);
 | 
			
		||||
  meta_topic (META_DEBUG_EVENTS,
 | 
			
		||||
              "%s on %s%s %s %sserial %lu\n", name, winname,
 | 
			
		||||
              extra ? ":" : "", extra ? extra : "",
 | 
			
		||||
              event->xany.send_event ? "SEND " : "",
 | 
			
		||||
              event->xany.serial);
 | 
			
		||||
 | 
			
		||||
  g_free (winname);
 | 
			
		||||
 | 
			
		||||
  if (extra)
 | 
			
		||||
    g_free (extra);
 | 
			
		||||
}
 | 
			
		||||
#endif /* WITH_VERBOSE_MODE */
 | 
			
		||||
 | 
			
		||||
MetaWindow*
 | 
			
		||||
meta_display_lookup_x_window (MetaDisplay *display,
 | 
			
		||||
@@ -4775,8 +4780,8 @@ meta_display_pong_for_serial (MetaDisplay    *display,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaGroup *
 | 
			
		||||
get_focused_group (MetaDisplay *display)
 | 
			
		||||
MetaGroup*
 | 
			
		||||
get_focussed_group (MetaDisplay *display)
 | 
			
		||||
{
 | 
			
		||||
  if (display->focus_window)
 | 
			
		||||
    return display->focus_window->group;
 | 
			
		||||
@@ -4786,7 +4791,7 @@ get_focused_group (MetaDisplay *display)
 | 
			
		||||
 | 
			
		||||
#define IN_TAB_CHAIN(w,t) (((t) == META_TAB_LIST_NORMAL && META_WINDOW_IN_NORMAL_TAB_CHAIN (w)) \
 | 
			
		||||
    || ((t) == META_TAB_LIST_DOCKS && META_WINDOW_IN_DOCK_TAB_CHAIN (w)) \
 | 
			
		||||
    || ((t) == META_TAB_LIST_GROUP && META_WINDOW_IN_GROUP_TAB_CHAIN (w, get_focused_group (w->display))) \
 | 
			
		||||
    || ((t) == META_TAB_LIST_GROUP && META_WINDOW_IN_GROUP_TAB_CHAIN (w, get_focussed_group(w->display))) \
 | 
			
		||||
    || ((t) == META_TAB_LIST_NORMAL_ALL && META_WINDOW_IN_NORMAL_TAB_CHAIN_TYPE (w)))
 | 
			
		||||
 | 
			
		||||
static MetaWindow*
 | 
			
		||||
 
 | 
			
		||||
@@ -41,6 +41,7 @@
 | 
			
		||||
#include "screen-private.h"
 | 
			
		||||
#include <meta/prefs.h>
 | 
			
		||||
#include "util-private.h"
 | 
			
		||||
#include "meta-wayland.h"
 | 
			
		||||
 | 
			
		||||
#include <X11/keysym.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
@@ -51,8 +52,6 @@
 | 
			
		||||
#include <X11/XKBlib.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "wayland/meta-wayland.h"
 | 
			
		||||
 | 
			
		||||
#define SCHEMA_COMMON_KEYBINDINGS "org.gnome.desktop.wm.keybindings"
 | 
			
		||||
#define SCHEMA_MUTTER_KEYBINDINGS "org.gnome.mutter.keybindings"
 | 
			
		||||
#define SCHEMA_MUTTER_WAYLAND_KEYBINDINGS "org.gnome.mutter.wayland.keybindings"
 | 
			
		||||
@@ -1976,7 +1975,9 @@ process_mouse_move_resize_grab (MetaDisplay     *display,
 | 
			
		||||
       * moveresize now to get the position back to the original.
 | 
			
		||||
       */
 | 
			
		||||
      if (window->shaken_loose || window->tile_mode == META_TILE_MAXIMIZED)
 | 
			
		||||
        meta_window_maximize (window, META_MAXIMIZE_BOTH);
 | 
			
		||||
        meta_window_maximize (window,
 | 
			
		||||
                              META_MAXIMIZE_HORIZONTAL |
 | 
			
		||||
                              META_MAXIMIZE_VERTICAL);
 | 
			
		||||
      else if (window->tile_mode != META_TILE_NONE)
 | 
			
		||||
        meta_window_tile (window);
 | 
			
		||||
      else
 | 
			
		||||
@@ -2037,7 +2038,9 @@ process_keyboard_move_grab (MetaDisplay     *display,
 | 
			
		||||
       * now to get the position back to the original.
 | 
			
		||||
       */
 | 
			
		||||
      if (window->shaken_loose)
 | 
			
		||||
        meta_window_maximize (window, META_MAXIMIZE_BOTH);
 | 
			
		||||
        meta_window_maximize (window,
 | 
			
		||||
                              META_MAXIMIZE_HORIZONTAL |
 | 
			
		||||
                              META_MAXIMIZE_VERTICAL);
 | 
			
		||||
      else
 | 
			
		||||
        meta_window_move_resize (display->grab_window,
 | 
			
		||||
                                 TRUE,
 | 
			
		||||
@@ -2898,9 +2901,11 @@ handle_toggle_tiled (MetaDisplay     *display,
 | 
			
		||||
        : META_TILE_NONE;
 | 
			
		||||
 | 
			
		||||
      if (window->saved_maximize)
 | 
			
		||||
        meta_window_maximize (window, META_MAXIMIZE_BOTH);
 | 
			
		||||
        meta_window_maximize (window, META_MAXIMIZE_VERTICAL |
 | 
			
		||||
                              META_MAXIMIZE_HORIZONTAL);
 | 
			
		||||
      else
 | 
			
		||||
        meta_window_unmaximize (window, META_MAXIMIZE_BOTH);
 | 
			
		||||
        meta_window_unmaximize (window, META_MAXIMIZE_VERTICAL |
 | 
			
		||||
                                META_MAXIMIZE_HORIZONTAL);
 | 
			
		||||
    }
 | 
			
		||||
  else if (meta_window_can_tile_side_by_side (window))
 | 
			
		||||
    {
 | 
			
		||||
@@ -2926,9 +2931,13 @@ handle_toggle_maximized    (MetaDisplay     *display,
 | 
			
		||||
                            gpointer         dummy)
 | 
			
		||||
{
 | 
			
		||||
  if (META_WINDOW_MAXIMIZED (window))
 | 
			
		||||
    meta_window_unmaximize (window, META_MAXIMIZE_BOTH);
 | 
			
		||||
    meta_window_unmaximize (window,
 | 
			
		||||
                            META_MAXIMIZE_HORIZONTAL |
 | 
			
		||||
                            META_MAXIMIZE_VERTICAL);
 | 
			
		||||
  else if (window->has_maximize_func)
 | 
			
		||||
    meta_window_maximize (window, META_MAXIMIZE_BOTH);
 | 
			
		||||
    meta_window_maximize (window,
 | 
			
		||||
                          META_MAXIMIZE_HORIZONTAL |
 | 
			
		||||
                          META_MAXIMIZE_VERTICAL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -2940,7 +2949,9 @@ handle_maximize           (MetaDisplay     *display,
 | 
			
		||||
                           gpointer         dummy)
 | 
			
		||||
{
 | 
			
		||||
  if (window->has_maximize_func)
 | 
			
		||||
    meta_window_maximize (window, META_MAXIMIZE_BOTH);
 | 
			
		||||
    meta_window_maximize (window,
 | 
			
		||||
                          META_MAXIMIZE_HORIZONTAL |
 | 
			
		||||
                          META_MAXIMIZE_VERTICAL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -2952,7 +2963,9 @@ handle_unmaximize         (MetaDisplay     *display,
 | 
			
		||||
                           gpointer         dummy)
 | 
			
		||||
{
 | 
			
		||||
  if (window->maximized_vertically || window->maximized_horizontally)
 | 
			
		||||
    meta_window_unmaximize (window, META_MAXIMIZE_BOTH);
 | 
			
		||||
    meta_window_unmaximize (window,
 | 
			
		||||
                            META_MAXIMIZE_HORIZONTAL |
 | 
			
		||||
                            META_MAXIMIZE_VERTICAL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -3903,7 +3916,6 @@ init_builtin_key_bindings (MetaDisplay *display)
 | 
			
		||||
 | 
			
		||||
  g_object_unref (common_keybindings);
 | 
			
		||||
  g_object_unref (mutter_keybindings);
 | 
			
		||||
  g_object_unref (mutter_wayland_keybindings);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
 
 | 
			
		||||
@@ -50,8 +50,10 @@
 | 
			
		||||
#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.h"
 | 
			
		||||
 | 
			
		||||
#include <glib-object.h>
 | 
			
		||||
#include <glib-unix.h>
 | 
			
		||||
@@ -77,10 +79,6 @@
 | 
			
		||||
#include <girepository.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "x11/session.h"
 | 
			
		||||
 | 
			
		||||
#include "wayland/meta-wayland.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * The exit code we'll return to our parent process when we eventually die.
 | 
			
		||||
 */
 | 
			
		||||
@@ -192,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[] = {
 | 
			
		||||
  {
 | 
			
		||||
@@ -236,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}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -409,7 +401,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);
 | 
			
		||||
@@ -504,32 +497,6 @@ meta_register_with_session (void)
 | 
			
		||||
  g_free (opt_client_id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_activate_session:
 | 
			
		||||
 *
 | 
			
		||||
 * Tells mutter to activate the session. When mutter is a
 | 
			
		||||
 * Wayland compositor, this tells logind to switch over to
 | 
			
		||||
 * the new session.
 | 
			
		||||
 */
 | 
			
		||||
gboolean
 | 
			
		||||
meta_activate_session (void)
 | 
			
		||||
{
 | 
			
		||||
  if (meta_is_wayland_compositor ())
 | 
			
		||||
    {
 | 
			
		||||
      MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
 | 
			
		||||
      GError *error = NULL;
 | 
			
		||||
 | 
			
		||||
      if (!meta_wayland_compositor_activate_session (compositor, &error))
 | 
			
		||||
        {
 | 
			
		||||
          g_warning ("Could not activate session: %s\n", error->message);
 | 
			
		||||
          g_error_free (error);
 | 
			
		||||
          return FALSE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_run: (skip)
 | 
			
		||||
 *
 | 
			
		||||
 
 | 
			
		||||
@@ -43,7 +43,4 @@ void     meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
 | 
			
		||||
					      int                new_x,
 | 
			
		||||
					      int                new_y);
 | 
			
		||||
void     meta_cursor_tracker_paint           (MetaCursorTracker *tracker);
 | 
			
		||||
 | 
			
		||||
void     meta_cursor_tracker_force_update (MetaCursorTracker *tracker);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -39,7 +39,6 @@
 | 
			
		||||
#include <gbm.h>
 | 
			
		||||
 | 
			
		||||
#include <gdk/gdk.h>
 | 
			
		||||
#include <gdk/gdkx.h>
 | 
			
		||||
 | 
			
		||||
#include <X11/cursorfont.h>
 | 
			
		||||
#include <X11/extensions/Xfixes.h>
 | 
			
		||||
@@ -47,10 +46,9 @@
 | 
			
		||||
 | 
			
		||||
#include "meta-cursor-tracker-private.h"
 | 
			
		||||
#include "screen-private.h"
 | 
			
		||||
#include "meta-wayland-private.h"
 | 
			
		||||
#include "monitor-private.h"
 | 
			
		||||
 | 
			
		||||
#include "wayland/meta-wayland-private.h"
 | 
			
		||||
 | 
			
		||||
#define META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_X 7
 | 
			
		||||
#define META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_Y 4
 | 
			
		||||
 | 
			
		||||
@@ -571,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))
 | 
			
		||||
@@ -1148,12 +1143,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);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -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.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);
 | 
			
		||||
 | 
			
		||||
@@ -809,8 +809,11 @@ meta_screen_free (MetaScreen *screen,
 | 
			
		||||
  
 | 
			
		||||
  meta_display_grab (display);
 | 
			
		||||
 | 
			
		||||
  meta_compositor_unmanage_screen (screen->display->compositor,
 | 
			
		||||
                                   screen);
 | 
			
		||||
  if (screen->display->compositor)
 | 
			
		||||
    {
 | 
			
		||||
      meta_compositor_unmanage_screen (screen->display->compositor,
 | 
			
		||||
				       screen);
 | 
			
		||||
    }
 | 
			
		||||
  
 | 
			
		||||
  meta_display_unmanage_windows_for_screen (display, screen, timestamp);
 | 
			
		||||
  
 | 
			
		||||
@@ -2520,9 +2523,10 @@ on_monitors_changed (MetaMonitorManager *manager,
 | 
			
		||||
                       &changes);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_compositor_sync_screen_size (screen->display->compositor,
 | 
			
		||||
                                    screen,
 | 
			
		||||
                                    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);
 | 
			
		||||
 
 | 
			
		||||
@@ -1245,9 +1245,10 @@ meta_stack_tracker_sync_stack (MetaStackTracker *tracker)
 | 
			
		||||
        meta_windows = g_list_prepend (meta_windows, window->wayland.meta_window);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_compositor_sync_stack (tracker->screen->display->compositor,
 | 
			
		||||
                              tracker->screen,
 | 
			
		||||
                              meta_windows);
 | 
			
		||||
  if (tracker->screen->display->compositor)
 | 
			
		||||
    meta_compositor_sync_stack (tracker->screen->display->compositor,
 | 
			
		||||
                                tracker->screen,
 | 
			
		||||
                                meta_windows);
 | 
			
		||||
  g_list_free (meta_windows);
 | 
			
		||||
 | 
			
		||||
  meta_screen_restacked (tracker->screen);
 | 
			
		||||
 
 | 
			
		||||
@@ -36,8 +36,6 @@
 | 
			
		||||
 | 
			
		||||
#include <X11/Xatom.h>
 | 
			
		||||
 | 
			
		||||
#include "x11/group-private.h"
 | 
			
		||||
 | 
			
		||||
#define WINDOW_HAS_TRANSIENT_TYPE(w)                    \
 | 
			
		||||
          (w->type == META_WINDOW_DIALOG ||             \
 | 
			
		||||
	   w->type == META_WINDOW_MODAL_DIALOG ||       \
 | 
			
		||||
@@ -1707,8 +1705,8 @@ get_default_focus_window (MetaStack     *stack,
 | 
			
		||||
  MetaWindow *topmost_in_group;
 | 
			
		||||
  MetaWindow *topmost_overall;
 | 
			
		||||
  MetaGroup *not_this_one_group;
 | 
			
		||||
  GList *l;
 | 
			
		||||
 | 
			
		||||
  GList *link;
 | 
			
		||||
  
 | 
			
		||||
  transient_parent = NULL;
 | 
			
		||||
  topmost_in_group = NULL;
 | 
			
		||||
  topmost_overall = NULL;
 | 
			
		||||
@@ -1720,49 +1718,49 @@ get_default_focus_window (MetaStack     *stack,
 | 
			
		||||
  stack_ensure_sorted (stack);
 | 
			
		||||
 | 
			
		||||
  /* top of this layer is at the front of the list */
 | 
			
		||||
  for (l = stack->sorted; l != NULL; l = l->next)
 | 
			
		||||
  link = stack->sorted;
 | 
			
		||||
      
 | 
			
		||||
  while (link)
 | 
			
		||||
    {
 | 
			
		||||
      MetaWindow *window = l->data;
 | 
			
		||||
      MetaWindow *window = link->data;
 | 
			
		||||
 | 
			
		||||
      if (!window)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (window == not_this_one)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (window->unmaps_pending > 0)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (window->minimized)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (!(window->input || window->take_focus))
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (workspace != NULL && !meta_window_located_on_workspace (window, workspace))
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (must_be_at_point && !window_contains_point (window, root_x, root_y))
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (not_this_one != NULL)
 | 
			
		||||
      if (window &&
 | 
			
		||||
          window != not_this_one &&
 | 
			
		||||
          (window->unmaps_pending == 0) &&
 | 
			
		||||
          !window->minimized &&
 | 
			
		||||
          (window->input || window->take_focus) &&
 | 
			
		||||
          (workspace == NULL ||
 | 
			
		||||
           meta_window_located_on_workspace (window, workspace)))
 | 
			
		||||
        {
 | 
			
		||||
          if (transient_parent == NULL &&
 | 
			
		||||
              meta_window_get_transient_for (not_this_one) == window)
 | 
			
		||||
            transient_parent = window;
 | 
			
		||||
          if (not_this_one != NULL)
 | 
			
		||||
            {
 | 
			
		||||
              if (transient_parent == NULL &&
 | 
			
		||||
                  not_this_one->xtransient_for != None &&
 | 
			
		||||
                  not_this_one->xtransient_for == window->xwindow &&
 | 
			
		||||
                  (!must_be_at_point ||
 | 
			
		||||
                   window_contains_point (window, root_x, root_y)))
 | 
			
		||||
                transient_parent = window;
 | 
			
		||||
 | 
			
		||||
          if (topmost_in_group == NULL &&
 | 
			
		||||
              not_this_one_group != NULL &&
 | 
			
		||||
              not_this_one_group == meta_window_get_group (window))
 | 
			
		||||
            topmost_in_group = window;
 | 
			
		||||
              if (topmost_in_group == NULL &&
 | 
			
		||||
                  not_this_one_group != NULL &&
 | 
			
		||||
                  not_this_one_group == meta_window_get_group (window) &&
 | 
			
		||||
                  (!must_be_at_point ||
 | 
			
		||||
                   window_contains_point (window, root_x, root_y)))
 | 
			
		||||
                topmost_in_group = window;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          if (topmost_overall == NULL &&
 | 
			
		||||
              window->type != META_WINDOW_DOCK &&
 | 
			
		||||
              (!must_be_at_point ||
 | 
			
		||||
               window_contains_point (window, root_x, root_y)))
 | 
			
		||||
            topmost_overall = window;
 | 
			
		||||
 | 
			
		||||
          /* We could try to bail out early here for efficiency in
 | 
			
		||||
           * some cases, but it's just not worth the code.
 | 
			
		||||
           */
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (topmost_overall == NULL && window->type != META_WINDOW_DOCK)
 | 
			
		||||
        topmost_overall = window;
 | 
			
		||||
 | 
			
		||||
      /* We could try to bail out early here for efficiency in
 | 
			
		||||
       * some cases, but it's just not worth the code.
 | 
			
		||||
       */
 | 
			
		||||
      link = link->next;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (transient_parent)
 | 
			
		||||
 
 | 
			
		||||
@@ -38,15 +38,12 @@
 | 
			
		||||
#include "screen-private.h"
 | 
			
		||||
#include <meta/util.h>
 | 
			
		||||
#include "stack.h"
 | 
			
		||||
#include "iconcache.h"
 | 
			
		||||
#include <X11/Xutil.h>
 | 
			
		||||
#include <cairo.h>
 | 
			
		||||
#include <gdk-pixbuf/gdk-pixbuf.h>
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
 | 
			
		||||
#include "x11/iconcache.h"
 | 
			
		||||
#include "x11/group-private.h"
 | 
			
		||||
 | 
			
		||||
#include "wayland/meta-wayland-types.h"
 | 
			
		||||
#include "meta-wayland-types.h"
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaWindowQueue MetaWindowQueue;
 | 
			
		||||
 | 
			
		||||
@@ -92,13 +89,15 @@ struct _MetaWindow
 | 
			
		||||
  char *desc; /* used in debug spew */
 | 
			
		||||
  char *title;
 | 
			
		||||
 | 
			
		||||
  char *icon_name;
 | 
			
		||||
  GdkPixbuf *icon;
 | 
			
		||||
  GdkPixbuf *mini_icon;
 | 
			
		||||
  MetaIconCache icon_cache;
 | 
			
		||||
  Pixmap wm_hints_pixmap;
 | 
			
		||||
  Pixmap wm_hints_mask;
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
  MetaWindowType type;
 | 
			
		||||
  Atom type_atom;
 | 
			
		||||
 | 
			
		||||
  /* NOTE these five are not in UTF-8, we just treat them as random
 | 
			
		||||
   * binary data
 | 
			
		||||
@@ -160,8 +159,8 @@ struct _MetaWindow
 | 
			
		||||
  /* Whether we're fullscreen */
 | 
			
		||||
  guint fullscreen : 1;
 | 
			
		||||
 | 
			
		||||
  /* Whether the window is marked as urgent */
 | 
			
		||||
  guint urgent : 1;
 | 
			
		||||
  /* Whether the urgent flag of WM_HINTS is set */
 | 
			
		||||
  guint wm_hints_urgent : 1;
 | 
			
		||||
 | 
			
		||||
  /* Whether we have to fullscreen after placement */
 | 
			
		||||
  guint fullscreen_after_placement : 1;
 | 
			
		||||
@@ -263,6 +262,13 @@ struct _MetaWindow
 | 
			
		||||
  guint has_move_func : 1;
 | 
			
		||||
  guint has_resize_func : 1;
 | 
			
		||||
  guint has_fullscreen_func : 1;
 | 
			
		||||
  
 | 
			
		||||
  /* Weird "_NET_WM_STATE_MODAL" flag */
 | 
			
		||||
  guint wm_state_modal : 1;
 | 
			
		||||
 | 
			
		||||
  /* TRUE if the client forced these on */
 | 
			
		||||
  guint wm_state_skip_taskbar : 1;
 | 
			
		||||
  guint wm_state_skip_pager : 1;
 | 
			
		||||
 | 
			
		||||
  /* Computed whether to skip taskbar or not */
 | 
			
		||||
  guint skip_taskbar : 1;
 | 
			
		||||
@@ -316,6 +322,15 @@ struct _MetaWindow
 | 
			
		||||
 | 
			
		||||
  /* Transient parent is a root window */
 | 
			
		||||
  guint transient_parent_is_root_window : 1;
 | 
			
		||||
 | 
			
		||||
  /* Info on which props we got our attributes from */
 | 
			
		||||
  guint using_net_wm_name              : 1; /* vs. plain wm_name */
 | 
			
		||||
  guint using_net_wm_visible_name      : 1; /* tracked so we can clear it */
 | 
			
		||||
  guint using_net_wm_icon_name         : 1; /* vs. plain wm_icon_name */
 | 
			
		||||
  guint using_net_wm_visible_icon_name : 1; /* tracked so we can clear it */
 | 
			
		||||
 | 
			
		||||
  /* icon props have changed */
 | 
			
		||||
  guint need_reread_icon : 1;
 | 
			
		||||
  
 | 
			
		||||
  /* if TRUE, window was maximized at start of current grab op */
 | 
			
		||||
  guint shaken_loose : 1;
 | 
			
		||||
@@ -393,12 +408,6 @@ struct _MetaWindow
 | 
			
		||||
   */
 | 
			
		||||
  MetaRectangle rect;
 | 
			
		||||
 | 
			
		||||
  /* The size and position we want the window to be (i.e. what we last asked
 | 
			
		||||
   * the client to configure).
 | 
			
		||||
   * This is only used for wayland clients.
 | 
			
		||||
   */
 | 
			
		||||
  MetaRectangle expected_rect;
 | 
			
		||||
 | 
			
		||||
  gboolean has_custom_frame_extents;
 | 
			
		||||
  GtkBorder custom_frame_extents;
 | 
			
		||||
 | 
			
		||||
@@ -416,6 +425,8 @@ struct _MetaWindow
 | 
			
		||||
   * gives the position and size of the client window (i.e. ignoring
 | 
			
		||||
   * the frame).
 | 
			
		||||
   *
 | 
			
		||||
   * Position valid if user_has_moved, size valid if user_has_resized
 | 
			
		||||
   *
 | 
			
		||||
   * Position always in root coords, unlike window->rect.
 | 
			
		||||
   */
 | 
			
		||||
  MetaRectangle user_rect;
 | 
			
		||||
@@ -454,9 +465,10 @@ struct _MetaWindowClass
 | 
			
		||||
{
 | 
			
		||||
  GObjectClass parent_class;
 | 
			
		||||
 | 
			
		||||
  void (*get_default_skip_hints) (MetaWindow *window,
 | 
			
		||||
                                  gboolean   *skip_taskbar_out,
 | 
			
		||||
                                  gboolean   *skip_pager_out);
 | 
			
		||||
  void (*workspace_changed) (MetaWindow *window, int  old_workspace);
 | 
			
		||||
  void (*focus)             (MetaWindow *window);
 | 
			
		||||
  void (*raised)            (MetaWindow *window);
 | 
			
		||||
  void (*unmanaged)         (MetaWindow *window);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* These differ from window->has_foo_func in that they consider
 | 
			
		||||
@@ -549,6 +561,9 @@ void        meta_window_change_workspace   (MetaWindow  *window,
 | 
			
		||||
/* Return whether the window should be currently mapped */
 | 
			
		||||
gboolean    meta_window_should_be_showing   (MetaWindow  *window);
 | 
			
		||||
 | 
			
		||||
/* See warning in window.c about this function */
 | 
			
		||||
gboolean    __window_is_terminal (MetaWindow *window);
 | 
			
		||||
 | 
			
		||||
void        meta_window_update_struts      (MetaWindow  *window);
 | 
			
		||||
 | 
			
		||||
/* this gets root coords */
 | 
			
		||||
@@ -613,6 +628,12 @@ void meta_window_show_menu (MetaWindow *window,
 | 
			
		||||
                            int         button,
 | 
			
		||||
                            guint32     timestamp);
 | 
			
		||||
 | 
			
		||||
gboolean meta_window_titlebar_is_onscreen    (MetaWindow *window);
 | 
			
		||||
void     meta_window_shove_titlebar_onscreen (MetaWindow *window);
 | 
			
		||||
 | 
			
		||||
void meta_window_set_gravity (MetaWindow *window,
 | 
			
		||||
                              int         gravity);
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_XSYNC
 | 
			
		||||
void meta_window_update_sync_request_counter (MetaWindow *window,
 | 
			
		||||
                                              gint64      new_counter_value);
 | 
			
		||||
@@ -657,8 +678,9 @@ void meta_window_update_layer (MetaWindow *window);
 | 
			
		||||
 | 
			
		||||
void meta_window_recalc_features    (MetaWindow *window);
 | 
			
		||||
 | 
			
		||||
void meta_window_set_type (MetaWindow     *window,
 | 
			
		||||
                           MetaWindowType  type);
 | 
			
		||||
/* recalc_window_type is x11 only, wayland does its thing and then calls type_changed */
 | 
			
		||||
void meta_window_recalc_window_type (MetaWindow *window);
 | 
			
		||||
void meta_window_type_changed       (MetaWindow *window);
 | 
			
		||||
 | 
			
		||||
void meta_window_frame_size_changed (MetaWindow *window);
 | 
			
		||||
 | 
			
		||||
@@ -723,11 +745,4 @@ void meta_window_activate_full (MetaWindow     *window,
 | 
			
		||||
                                MetaClientType  source_indication,
 | 
			
		||||
                                MetaWorkspace  *workspace);
 | 
			
		||||
 | 
			
		||||
gboolean meta_window_is_client_decorated (MetaWindow *window);
 | 
			
		||||
 | 
			
		||||
void meta_window_update_monitor (MetaWindow *window);
 | 
			
		||||
 | 
			
		||||
void meta_window_set_urgent (MetaWindow *window,
 | 
			
		||||
                             gboolean    urgent);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -40,7 +40,6 @@
 | 
			
		||||
#include <config.h>
 | 
			
		||||
#include "window-props.h"
 | 
			
		||||
#include "window-x11.h"
 | 
			
		||||
#include "window-x11-private.h"
 | 
			
		||||
#include <meta/errors.h>
 | 
			
		||||
#include "xprops.h"
 | 
			
		||||
#include "frame.h"
 | 
			
		||||
@@ -429,8 +428,9 @@ reload_net_wm_user_time_window (MetaWindow    *window,
 | 
			
		||||
/**
 | 
			
		||||
 * set_title_text:
 | 
			
		||||
 *
 | 
			
		||||
 * Called by set_window_title() to set the value of @target to @title.
 | 
			
		||||
 * If required and @atom is set, it will update the appropriate property.
 | 
			
		||||
 * Called by set_window_title() and set_icon_title() to set the value of
 | 
			
		||||
 * @target to @title. It required and @atom is set, it will update the
 | 
			
		||||
 * appropriate property.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: %TRUE if a new title was set.
 | 
			
		||||
 */
 | 
			
		||||
@@ -488,18 +488,15 @@ static void
 | 
			
		||||
set_window_title (MetaWindow *window,
 | 
			
		||||
                  const char *title)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
 | 
			
		||||
  MetaWindowX11Private *priv = window_x11->priv;
 | 
			
		||||
 | 
			
		||||
  char *new_title = NULL;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
  gboolean modified =
 | 
			
		||||
    set_title_text (window,
 | 
			
		||||
                    priv->using_net_wm_visible_name,
 | 
			
		||||
                    window->using_net_wm_visible_name,
 | 
			
		||||
                    title,
 | 
			
		||||
                    window->display->atom__NET_WM_VISIBLE_NAME,
 | 
			
		||||
                    &new_title);
 | 
			
		||||
  priv->using_net_wm_visible_name = modified;
 | 
			
		||||
  window->using_net_wm_visible_name = modified;
 | 
			
		||||
  
 | 
			
		||||
  meta_window_set_title (window, new_title);
 | 
			
		||||
 | 
			
		||||
@@ -511,13 +508,10 @@ reload_net_wm_name (MetaWindow    *window,
 | 
			
		||||
                    MetaPropValue *value,
 | 
			
		||||
                    gboolean       initial)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
 | 
			
		||||
  MetaWindowX11Private *priv = window_x11->priv;
 | 
			
		||||
 | 
			
		||||
  if (value->type != META_PROP_VALUE_INVALID)
 | 
			
		||||
    {
 | 
			
		||||
      set_window_title (window, value->v.str);
 | 
			
		||||
      priv->using_net_wm_name = TRUE;
 | 
			
		||||
      window->using_net_wm_name = TRUE;
 | 
			
		||||
 | 
			
		||||
      meta_verbose ("Using _NET_WM_NAME for new title of %s: \"%s\"\n",
 | 
			
		||||
                    window->desc, window->title);
 | 
			
		||||
@@ -525,7 +519,7 @@ reload_net_wm_name (MetaWindow    *window,
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      set_window_title (window, NULL);
 | 
			
		||||
      priv->using_net_wm_name = FALSE;
 | 
			
		||||
      window->using_net_wm_name = FALSE;
 | 
			
		||||
      if (!initial)
 | 
			
		||||
        meta_window_reload_property (window, XA_WM_NAME, FALSE);
 | 
			
		||||
    }
 | 
			
		||||
@@ -536,10 +530,7 @@ reload_wm_name (MetaWindow    *window,
 | 
			
		||||
                MetaPropValue *value,
 | 
			
		||||
                gboolean       initial)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
 | 
			
		||||
  MetaWindowX11Private *priv = window_x11->priv;
 | 
			
		||||
 | 
			
		||||
  if (priv->using_net_wm_name)
 | 
			
		||||
  if (window->using_net_wm_name)
 | 
			
		||||
    {
 | 
			
		||||
      meta_verbose ("Ignoring WM_NAME \"%s\" as _NET_WM_NAME is set\n",
 | 
			
		||||
                    value->v.str);
 | 
			
		||||
@@ -610,14 +601,71 @@ reload_mutter_hints (MetaWindow    *window,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
set_icon_title (MetaWindow *window,
 | 
			
		||||
                const char *title)
 | 
			
		||||
{
 | 
			
		||||
  gboolean modified =
 | 
			
		||||
    set_title_text (window,
 | 
			
		||||
                    window->using_net_wm_visible_icon_name,
 | 
			
		||||
                    title,
 | 
			
		||||
                    window->display->atom__NET_WM_VISIBLE_ICON_NAME,
 | 
			
		||||
                    &window->icon_name);
 | 
			
		||||
  window->using_net_wm_visible_icon_name = modified;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
reload_net_wm_icon_name (MetaWindow    *window,
 | 
			
		||||
                         MetaPropValue *value,
 | 
			
		||||
                         gboolean       initial)
 | 
			
		||||
{
 | 
			
		||||
  if (value->type != META_PROP_VALUE_INVALID)
 | 
			
		||||
    {
 | 
			
		||||
      set_icon_title (window, value->v.str);
 | 
			
		||||
      window->using_net_wm_icon_name = TRUE;
 | 
			
		||||
 | 
			
		||||
      meta_verbose ("Using _NET_WM_ICON_NAME for new title of %s: \"%s\"\n",
 | 
			
		||||
                    window->desc, window->title);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      set_icon_title (window, NULL);
 | 
			
		||||
      window->using_net_wm_icon_name = FALSE;
 | 
			
		||||
      if (!initial)
 | 
			
		||||
        meta_window_reload_property (window, XA_WM_ICON_NAME, FALSE);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
reload_wm_icon_name (MetaWindow    *window,
 | 
			
		||||
                     MetaPropValue *value,
 | 
			
		||||
                     gboolean       initial)
 | 
			
		||||
{
 | 
			
		||||
  if (window->using_net_wm_icon_name)
 | 
			
		||||
    {
 | 
			
		||||
      meta_verbose ("Ignoring WM_ICON_NAME \"%s\" as _NET_WM_ICON_NAME is set\n",
 | 
			
		||||
                    value->v.str);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
  
 | 
			
		||||
  if (value->type != META_PROP_VALUE_INVALID)
 | 
			
		||||
    {
 | 
			
		||||
      set_icon_title (window, value->v.str);
 | 
			
		||||
      
 | 
			
		||||
      meta_verbose ("Using WM_ICON_NAME for new title of %s: \"%s\"\n",
 | 
			
		||||
                    window->desc, window->title);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      set_icon_title (window, NULL);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
reload_net_wm_state (MetaWindow    *window,
 | 
			
		||||
                     MetaPropValue *value,
 | 
			
		||||
                     gboolean       initial)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
 | 
			
		||||
  MetaWindowX11Private *priv = window_x11->priv;
 | 
			
		||||
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  /* We know this is only an initial window creation,
 | 
			
		||||
@@ -635,9 +683,9 @@ reload_net_wm_state (MetaWindow    *window,
 | 
			
		||||
  window->maximized_horizontally = FALSE;
 | 
			
		||||
  window->maximized_vertically = FALSE;
 | 
			
		||||
  window->fullscreen = FALSE;
 | 
			
		||||
  priv->wm_state_modal = FALSE;
 | 
			
		||||
  priv->wm_state_skip_taskbar = FALSE;
 | 
			
		||||
  priv->wm_state_skip_pager = FALSE;
 | 
			
		||||
  window->wm_state_modal = FALSE;
 | 
			
		||||
  window->wm_state_skip_taskbar = FALSE;
 | 
			
		||||
  window->wm_state_skip_pager = FALSE;
 | 
			
		||||
  window->wm_state_above = FALSE;
 | 
			
		||||
  window->wm_state_below = FALSE;
 | 
			
		||||
  window->wm_state_demands_attention = FALSE;
 | 
			
		||||
@@ -657,11 +705,11 @@ reload_net_wm_state (MetaWindow    *window,
 | 
			
		||||
      else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_HIDDEN)
 | 
			
		||||
        window->minimize_after_placement = TRUE;
 | 
			
		||||
      else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_MODAL)
 | 
			
		||||
        priv->wm_state_modal = TRUE;
 | 
			
		||||
        window->wm_state_modal = TRUE;
 | 
			
		||||
      else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_SKIP_TASKBAR)
 | 
			
		||||
        priv->wm_state_skip_taskbar = TRUE;
 | 
			
		||||
        window->wm_state_skip_taskbar = TRUE;
 | 
			
		||||
      else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_SKIP_PAGER)
 | 
			
		||||
        priv->wm_state_skip_pager = TRUE;
 | 
			
		||||
        window->wm_state_skip_pager = TRUE;
 | 
			
		||||
      else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_FULLSCREEN)
 | 
			
		||||
        window->fullscreen_after_placement = TRUE;
 | 
			
		||||
      else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_ABOVE)
 | 
			
		||||
@@ -679,7 +727,7 @@ reload_net_wm_state (MetaWindow    *window,
 | 
			
		||||
  meta_verbose ("Reloaded _NET_WM_STATE for %s\n",
 | 
			
		||||
                window->desc);
 | 
			
		||||
 | 
			
		||||
  meta_window_x11_recalc_window_type (window);
 | 
			
		||||
  meta_window_recalc_window_type (window);
 | 
			
		||||
  meta_window_recalc_features (window);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1390,9 +1438,10 @@ reload_wm_hints (MetaWindow    *window,
 | 
			
		||||
                 gboolean       initial)
 | 
			
		||||
{
 | 
			
		||||
  Window old_group_leader;
 | 
			
		||||
  gboolean urgent;
 | 
			
		||||
  gboolean old_urgent;
 | 
			
		||||
 | 
			
		||||
  old_group_leader = window->xgroup_leader;
 | 
			
		||||
  old_urgent = window->wm_hints_urgent;
 | 
			
		||||
  
 | 
			
		||||
  /* Fill in defaults */
 | 
			
		||||
  window->input = TRUE;
 | 
			
		||||
@@ -1400,7 +1449,7 @@ reload_wm_hints (MetaWindow    *window,
 | 
			
		||||
  window->xgroup_leader = None;
 | 
			
		||||
  window->wm_hints_pixmap = None;
 | 
			
		||||
  window->wm_hints_mask = None;
 | 
			
		||||
  urgent = FALSE;
 | 
			
		||||
  window->wm_hints_urgent = FALSE;
 | 
			
		||||
 | 
			
		||||
  if (value->type != META_PROP_VALUE_INVALID)
 | 
			
		||||
    {
 | 
			
		||||
@@ -1422,7 +1471,7 @@ reload_wm_hints (MetaWindow    *window,
 | 
			
		||||
        window->wm_hints_mask = hints->icon_mask;
 | 
			
		||||
 | 
			
		||||
      if (hints->flags & XUrgencyHint)
 | 
			
		||||
        urgent = TRUE;
 | 
			
		||||
        window->wm_hints_urgent = TRUE;
 | 
			
		||||
 | 
			
		||||
      meta_verbose ("Read WM_HINTS input: %d iconic: %d group leader: 0x%lx pixmap: 0x%lx mask: 0x%lx\n",
 | 
			
		||||
                    window->input, window->initially_iconic,
 | 
			
		||||
@@ -1439,7 +1488,20 @@ reload_wm_hints (MetaWindow    *window,
 | 
			
		||||
      meta_window_group_leader_changed (window);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_window_set_urgent (window, urgent);
 | 
			
		||||
  /*
 | 
			
		||||
   * Do not emit urgency notification on the inital property load
 | 
			
		||||
   */
 | 
			
		||||
  if (!initial && (window->wm_hints_urgent != old_urgent))
 | 
			
		||||
    g_object_notify (G_OBJECT (window), "urgent");
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * Do not emit signal for the initial property load, let the constructor to
 | 
			
		||||
   * take care of it once the MetaWindow is fully constructed.
 | 
			
		||||
   *
 | 
			
		||||
   * Only emit if the property is both changed and set.
 | 
			
		||||
   */
 | 
			
		||||
  if (!initial && window->wm_hints_urgent && !old_urgent)
 | 
			
		||||
    g_signal_emit_by_name (window->display, "window-marked-urgent", window);
 | 
			
		||||
 | 
			
		||||
  meta_icon_cache_property_changed (&window->icon_cache,
 | 
			
		||||
                                    window->display,
 | 
			
		||||
@@ -1671,6 +1733,8 @@ meta_display_init_window_prop_hooks (MetaDisplay *display)
 | 
			
		||||
    { XA_WM_NAME,                      META_PROP_VALUE_TEXT_PROPERTY, reload_wm_name,      TRUE,  TRUE },
 | 
			
		||||
    { display->atom__MUTTER_HINTS,     META_PROP_VALUE_TEXT_PROPERTY, reload_mutter_hints, TRUE,  TRUE },
 | 
			
		||||
    { display->atom__NET_WM_OPAQUE_REGION, META_PROP_VALUE_CARDINAL_LIST, reload_opaque_region, TRUE, TRUE },
 | 
			
		||||
    { display->atom__NET_WM_ICON_NAME, META_PROP_VALUE_UTF8,     reload_net_wm_icon_name,  TRUE,  FALSE },
 | 
			
		||||
    { XA_WM_ICON_NAME,                 META_PROP_VALUE_TEXT_PROPERTY, reload_wm_icon_name, TRUE,  FALSE },
 | 
			
		||||
    { display->atom__NET_WM_DESKTOP,   META_PROP_VALUE_CARDINAL, reload_net_wm_desktop,    TRUE,  FALSE },
 | 
			
		||||
    { display->atom__NET_STARTUP_ID,   META_PROP_VALUE_UTF8,     reload_net_startup_id,    TRUE,  FALSE },
 | 
			
		||||
    { display->atom__NET_WM_SYNC_REQUEST_COUNTER, META_PROP_VALUE_SYNC_COUNTER_LIST, reload_update_counter, TRUE, TRUE },
 | 
			
		||||
@@ -23,7 +23,6 @@
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include "window-x11.h"
 | 
			
		||||
#include "window-x11-private.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <X11/Xatom.h>
 | 
			
		||||
@@ -45,44 +44,9 @@
 | 
			
		||||
#include "window-props.h"
 | 
			
		||||
#include "xprops.h"
 | 
			
		||||
 | 
			
		||||
struct _MetaWindowX11Class
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowClass parent_class;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaWindowX11, meta_window_x11, META_TYPE_WINDOW)
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_window_x11_init (MetaWindowX11 *window_x11)
 | 
			
		||||
{
 | 
			
		||||
  window_x11->priv = meta_window_x11_get_instance_private (window_x11);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_window_x11_get_default_skip_hints (MetaWindow *window,
 | 
			
		||||
                                        gboolean   *skip_taskbar_out,
 | 
			
		||||
                                        gboolean   *skip_pager_out)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
 | 
			
		||||
  MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
 | 
			
		||||
 | 
			
		||||
  *skip_taskbar_out = priv->wm_state_skip_taskbar;
 | 
			
		||||
  *skip_pager_out = priv->wm_state_skip_pager;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_window_x11_class_init (MetaWindowX11Class *klass)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowClass *window_class = META_WINDOW_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
  window_class->get_default_skip_hints = meta_window_x11_get_default_skip_hints;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_window_x11_set_net_wm_state (MetaWindow *window)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
 | 
			
		||||
  MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
 | 
			
		||||
  int i;
 | 
			
		||||
  unsigned long data[13];
 | 
			
		||||
 | 
			
		||||
@@ -92,7 +56,7 @@ meta_window_x11_set_net_wm_state (MetaWindow *window)
 | 
			
		||||
      data[i] = window->display->atom__NET_WM_STATE_SHADED;
 | 
			
		||||
      ++i;
 | 
			
		||||
    }
 | 
			
		||||
  if (priv->wm_state_modal)
 | 
			
		||||
  if (window->wm_state_modal)
 | 
			
		||||
    {
 | 
			
		||||
      data[i] = window->display->atom__NET_WM_STATE_MODAL;
 | 
			
		||||
      ++i;
 | 
			
		||||
@@ -199,13 +163,11 @@ meta_window_x11_set_net_wm_state (MetaWindow *window)
 | 
			
		||||
void
 | 
			
		||||
meta_window_x11_update_net_wm_type (MetaWindow *window)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
 | 
			
		||||
  MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
 | 
			
		||||
  int n_atoms;
 | 
			
		||||
  Atom *atoms;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  priv->type_atom = None;
 | 
			
		||||
  window->type_atom = None;
 | 
			
		||||
  n_atoms = 0;
 | 
			
		||||
  atoms = NULL;
 | 
			
		||||
 | 
			
		||||
@@ -236,7 +198,7 @@ meta_window_x11_update_net_wm_type (MetaWindow *window)
 | 
			
		||||
          atoms[i] == window->display->atom__NET_WM_WINDOW_TYPE_DND ||
 | 
			
		||||
          atoms[i] == window->display->atom__NET_WM_WINDOW_TYPE_NORMAL)
 | 
			
		||||
        {
 | 
			
		||||
          priv->type_atom = atoms[i];
 | 
			
		||||
          window->type_atom = atoms[i];
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -250,10 +212,10 @@ meta_window_x11_update_net_wm_type (MetaWindow *window)
 | 
			
		||||
      char *str;
 | 
			
		||||
 | 
			
		||||
      str = NULL;
 | 
			
		||||
      if (priv->type_atom != None)
 | 
			
		||||
      if (window->type_atom != None)
 | 
			
		||||
        {
 | 
			
		||||
          meta_error_trap_push (window->display);
 | 
			
		||||
          str = XGetAtomName (window->display->xdisplay, priv->type_atom);
 | 
			
		||||
          str = XGetAtomName (window->display->xdisplay, window->type_atom);
 | 
			
		||||
          meta_error_trap_pop (window->display);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -264,7 +226,7 @@ meta_window_x11_update_net_wm_type (MetaWindow *window)
 | 
			
		||||
        meta_XFree (str);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_window_x11_recalc_window_type (window);
 | 
			
		||||
  meta_window_recalc_window_type (window);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -299,7 +261,8 @@ meta_window_set_opaque_region (MetaWindow     *window,
 | 
			
		||||
  if (region != NULL)
 | 
			
		||||
    window->opaque_region = cairo_region_reference (region);
 | 
			
		||||
 | 
			
		||||
  meta_compositor_window_shape_changed (window->display->compositor, window);
 | 
			
		||||
  if (window->display->compositor)
 | 
			
		||||
    meta_compositor_window_shape_changed (window->display->compositor, window);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -384,7 +347,8 @@ meta_window_set_input_region (MetaWindow     *window,
 | 
			
		||||
  if (region != NULL)
 | 
			
		||||
    window->input_region = cairo_region_reference (region);
 | 
			
		||||
 | 
			
		||||
  meta_compositor_window_shape_changed (window->display->compositor, window);
 | 
			
		||||
  if (window->display->compositor)
 | 
			
		||||
    meta_compositor_window_shape_changed (window->display->compositor, window);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
@@ -490,7 +454,8 @@ meta_window_set_shape_region (MetaWindow     *window,
 | 
			
		||||
  if (region != NULL)
 | 
			
		||||
    window->shape_region = cairo_region_reference (region);
 | 
			
		||||
 | 
			
		||||
  meta_compositor_window_shape_changed (window->display->compositor, window);
 | 
			
		||||
  if (window->display->compositor)
 | 
			
		||||
    meta_compositor_window_shape_changed (window->display->compositor, window);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -729,8 +694,6 @@ gboolean
 | 
			
		||||
meta_window_x11_client_message (MetaWindow *window,
 | 
			
		||||
                                XEvent     *event)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
 | 
			
		||||
  MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
 | 
			
		||||
  MetaDisplay *display;
 | 
			
		||||
 | 
			
		||||
  display = window->display;
 | 
			
		||||
@@ -905,18 +868,18 @@ meta_window_x11_client_message (MetaWindow *window,
 | 
			
		||||
      if (first == display->atom__NET_WM_STATE_MODAL ||
 | 
			
		||||
          second == display->atom__NET_WM_STATE_MODAL)
 | 
			
		||||
        {
 | 
			
		||||
          priv->wm_state_modal =
 | 
			
		||||
          window->wm_state_modal =
 | 
			
		||||
            (action == _NET_WM_STATE_ADD) ||
 | 
			
		||||
            (action == _NET_WM_STATE_TOGGLE && !priv->wm_state_modal);
 | 
			
		||||
            (action == _NET_WM_STATE_TOGGLE && !window->wm_state_modal);
 | 
			
		||||
 | 
			
		||||
          meta_window_x11_recalc_window_type (window);
 | 
			
		||||
          meta_window_recalc_window_type (window);
 | 
			
		||||
          meta_window_queue(window, META_QUEUE_MOVE_RESIZE);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (first == display->atom__NET_WM_STATE_SKIP_PAGER ||
 | 
			
		||||
          second == display->atom__NET_WM_STATE_SKIP_PAGER)
 | 
			
		||||
        {
 | 
			
		||||
          priv->wm_state_skip_pager =
 | 
			
		||||
          window->wm_state_skip_pager =
 | 
			
		||||
            (action == _NET_WM_STATE_ADD) ||
 | 
			
		||||
            (action == _NET_WM_STATE_TOGGLE && !window->skip_pager);
 | 
			
		||||
 | 
			
		||||
@@ -927,7 +890,7 @@ meta_window_x11_client_message (MetaWindow *window,
 | 
			
		||||
      if (first == display->atom__NET_WM_STATE_SKIP_TASKBAR ||
 | 
			
		||||
          second == display->atom__NET_WM_STATE_SKIP_TASKBAR)
 | 
			
		||||
        {
 | 
			
		||||
          priv->wm_state_skip_taskbar =
 | 
			
		||||
          window->wm_state_skip_taskbar =
 | 
			
		||||
            (action == _NET_WM_STATE_ADD) ||
 | 
			
		||||
            (action == _NET_WM_STATE_TOGGLE && !window->skip_taskbar);
 | 
			
		||||
 | 
			
		||||
@@ -1347,7 +1310,7 @@ is_our_xwindow (MetaDisplay       *display,
 | 
			
		||||
  if (xwindow == screen->guard_window)
 | 
			
		||||
    return TRUE;
 | 
			
		||||
 | 
			
		||||
  if (xwindow == XCompositeGetOverlayWindow (display->xdisplay, screen->xroot))
 | 
			
		||||
  if (display->compositor && xwindow == XCompositeGetOverlayWindow (display->xdisplay, screen->xroot))
 | 
			
		||||
    return TRUE;
 | 
			
		||||
 | 
			
		||||
  /* Any windows created via meta_create_offscreen_window */
 | 
			
		||||
@@ -1543,148 +1506,3 @@ error:
 | 
			
		||||
  meta_error_trap_pop (display);
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_window_x11_recalc_window_type (MetaWindow *window)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
 | 
			
		||||
  MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
 | 
			
		||||
  MetaWindowType type;
 | 
			
		||||
 | 
			
		||||
  if (priv->type_atom != None)
 | 
			
		||||
    {
 | 
			
		||||
      if (priv->type_atom  == window->display->atom__NET_WM_WINDOW_TYPE_DESKTOP)
 | 
			
		||||
        type = META_WINDOW_DESKTOP;
 | 
			
		||||
      else if (priv->type_atom  == window->display->atom__NET_WM_WINDOW_TYPE_DOCK)
 | 
			
		||||
        type = META_WINDOW_DOCK;
 | 
			
		||||
      else if (priv->type_atom  == window->display->atom__NET_WM_WINDOW_TYPE_TOOLBAR)
 | 
			
		||||
        type = META_WINDOW_TOOLBAR;
 | 
			
		||||
      else if (priv->type_atom  == window->display->atom__NET_WM_WINDOW_TYPE_MENU)
 | 
			
		||||
        type = META_WINDOW_MENU;
 | 
			
		||||
      else if (priv->type_atom  == window->display->atom__NET_WM_WINDOW_TYPE_UTILITY)
 | 
			
		||||
        type = META_WINDOW_UTILITY;
 | 
			
		||||
      else if (priv->type_atom  == window->display->atom__NET_WM_WINDOW_TYPE_SPLASH)
 | 
			
		||||
        type = META_WINDOW_SPLASHSCREEN;
 | 
			
		||||
      else if (priv->type_atom  == window->display->atom__NET_WM_WINDOW_TYPE_DIALOG)
 | 
			
		||||
        type = META_WINDOW_DIALOG;
 | 
			
		||||
      else if (priv->type_atom  == window->display->atom__NET_WM_WINDOW_TYPE_NORMAL)
 | 
			
		||||
        type = META_WINDOW_NORMAL;
 | 
			
		||||
      /* The below are *typically* override-redirect windows, but the spec does
 | 
			
		||||
       * not disallow using them for managed windows.
 | 
			
		||||
       */
 | 
			
		||||
      else if (priv->type_atom  == window->display->atom__NET_WM_WINDOW_TYPE_DROPDOWN_MENU)
 | 
			
		||||
        type = META_WINDOW_DROPDOWN_MENU;
 | 
			
		||||
      else if (priv->type_atom  == window->display->atom__NET_WM_WINDOW_TYPE_POPUP_MENU)
 | 
			
		||||
        type = META_WINDOW_POPUP_MENU;
 | 
			
		||||
      else if (priv->type_atom  == window->display->atom__NET_WM_WINDOW_TYPE_TOOLTIP)
 | 
			
		||||
        type = META_WINDOW_TOOLTIP;
 | 
			
		||||
      else if (priv->type_atom  == window->display->atom__NET_WM_WINDOW_TYPE_NOTIFICATION)
 | 
			
		||||
        type = META_WINDOW_NOTIFICATION;
 | 
			
		||||
      else if (priv->type_atom  == window->display->atom__NET_WM_WINDOW_TYPE_COMBO)
 | 
			
		||||
        type = META_WINDOW_COMBO;
 | 
			
		||||
      else if (priv->type_atom  == window->display->atom__NET_WM_WINDOW_TYPE_DND)
 | 
			
		||||
        type = META_WINDOW_DND;
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          char *atom_name;
 | 
			
		||||
 | 
			
		||||
          /*
 | 
			
		||||
           * Fallback on a normal type, and print warning. Don't abort.
 | 
			
		||||
           */
 | 
			
		||||
          type = META_WINDOW_NORMAL;
 | 
			
		||||
 | 
			
		||||
          meta_error_trap_push (window->display);
 | 
			
		||||
          atom_name = XGetAtomName (window->display->xdisplay,
 | 
			
		||||
                                    priv->type_atom);
 | 
			
		||||
          meta_error_trap_pop (window->display);
 | 
			
		||||
 | 
			
		||||
          meta_warning ("Unrecognized type atom [%s] set for %s \n",
 | 
			
		||||
                        atom_name ? atom_name : "unknown",
 | 
			
		||||
                        window->desc);
 | 
			
		||||
 | 
			
		||||
          if (atom_name)
 | 
			
		||||
            XFree (atom_name);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  else if (window->transient_for != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      type = META_WINDOW_DIALOG;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      type = META_WINDOW_NORMAL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (type == META_WINDOW_DIALOG && priv->wm_state_modal)
 | 
			
		||||
    type = META_WINDOW_MODAL_DIALOG;
 | 
			
		||||
 | 
			
		||||
  /* We don't want to allow override-redirect windows to have decorated-window
 | 
			
		||||
   * types since that's just confusing.
 | 
			
		||||
   */
 | 
			
		||||
  if (window->override_redirect)
 | 
			
		||||
    {
 | 
			
		||||
      switch (window->type)
 | 
			
		||||
        {
 | 
			
		||||
        /* Decorated types */
 | 
			
		||||
        case META_WINDOW_NORMAL:
 | 
			
		||||
        case META_WINDOW_DIALOG:
 | 
			
		||||
        case META_WINDOW_MODAL_DIALOG:
 | 
			
		||||
        case META_WINDOW_MENU:
 | 
			
		||||
        case META_WINDOW_UTILITY:
 | 
			
		||||
          type = META_WINDOW_OVERRIDE_OTHER;
 | 
			
		||||
          break;
 | 
			
		||||
        /* Undecorated types, normally not override-redirect */
 | 
			
		||||
        case META_WINDOW_DESKTOP:
 | 
			
		||||
        case META_WINDOW_DOCK:
 | 
			
		||||
        case META_WINDOW_TOOLBAR:
 | 
			
		||||
        case META_WINDOW_SPLASHSCREEN:
 | 
			
		||||
        /* Undecorated types, normally override-redirect types */
 | 
			
		||||
        case META_WINDOW_DROPDOWN_MENU:
 | 
			
		||||
        case META_WINDOW_POPUP_MENU:
 | 
			
		||||
        case META_WINDOW_TOOLTIP:
 | 
			
		||||
        case META_WINDOW_NOTIFICATION:
 | 
			
		||||
        case META_WINDOW_COMBO:
 | 
			
		||||
        case META_WINDOW_DND:
 | 
			
		||||
        /* To complete enum */
 | 
			
		||||
        case META_WINDOW_OVERRIDE_OTHER:
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_verbose ("Calculated type %u for %s, old type %u\n",
 | 
			
		||||
                type, window->desc, type);
 | 
			
		||||
  meta_window_set_type (window, type);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_window_x11_configure_notify: (skip)
 | 
			
		||||
 * @window: a #MetaWindow
 | 
			
		||||
 * @event: a #XConfigureEvent
 | 
			
		||||
 *
 | 
			
		||||
 * This is used to notify us of an unrequested configuration
 | 
			
		||||
 * (only applicable to override redirect windows)
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
meta_window_x11_configure_notify (MetaWindow      *window,
 | 
			
		||||
                                  XConfigureEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  g_assert (window->override_redirect);
 | 
			
		||||
  g_assert (window->frame == NULL);
 | 
			
		||||
 | 
			
		||||
  window->rect.x = event->x;
 | 
			
		||||
  window->rect.y = event->y;
 | 
			
		||||
  window->rect.width = event->width;
 | 
			
		||||
  window->rect.height = event->height;
 | 
			
		||||
  meta_window_update_monitor (window);
 | 
			
		||||
 | 
			
		||||
  /* Whether an override-redirect window is considered fullscreen depends
 | 
			
		||||
   * on its geometry.
 | 
			
		||||
   */
 | 
			
		||||
  if (window->override_redirect)
 | 
			
		||||
    meta_screen_queue_check_fullscreen (window->screen);
 | 
			
		||||
 | 
			
		||||
  if (!event->override_redirect && !event->send_event)
 | 
			
		||||
    meta_warning ("Unhandled change of windows override redirect status\n");
 | 
			
		||||
 | 
			
		||||
  meta_compositor_sync_window_geometry (window->display->compositor, window, FALSE);
 | 
			
		||||
}
 | 
			
		||||
@@ -26,20 +26,6 @@
 | 
			
		||||
#include <meta/window.h>
 | 
			
		||||
#include <X11/Xlib.h>
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_WINDOW_X11            (meta_window_x11_get_type())
 | 
			
		||||
#define META_WINDOW_X11(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_WINDOW_X11, MetaWindowX11))
 | 
			
		||||
#define META_WINDOW_X11_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_WINDOW_X11, MetaWindowX11Class))
 | 
			
		||||
#define META_IS_WINDOW_X11(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_WINDOW_X11))
 | 
			
		||||
#define META_IS_WINDOW_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_WINDOW_X11))
 | 
			
		||||
#define META_WINDOW_X11_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_WINDOW_X11, MetaWindowX11Class))
 | 
			
		||||
 | 
			
		||||
GType meta_window_x11_get_type (void);
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaWindowX11      MetaWindowX11;
 | 
			
		||||
typedef struct _MetaWindowX11Class MetaWindowX11Class;
 | 
			
		||||
 | 
			
		||||
void meta_window_x11_set_net_wm_state            (MetaWindow *window);
 | 
			
		||||
void meta_window_x11_set_wm_state                (MetaWindow *window);
 | 
			
		||||
 | 
			
		||||
@@ -49,8 +35,6 @@ void meta_window_x11_update_opaque_region        (MetaWindow *window);
 | 
			
		||||
void meta_window_x11_update_input_region         (MetaWindow *window);
 | 
			
		||||
void meta_window_x11_update_shape_region         (MetaWindow *window);
 | 
			
		||||
 | 
			
		||||
void meta_window_x11_recalc_window_type          (MetaWindow *window);
 | 
			
		||||
 | 
			
		||||
gboolean meta_window_x11_configure_request       (MetaWindow *window,
 | 
			
		||||
                                                  XEvent     *event);
 | 
			
		||||
gboolean meta_window_x11_property_notify         (MetaWindow *window,
 | 
			
		||||
@@ -58,7 +42,4 @@ gboolean meta_window_x11_property_notify         (MetaWindow *window,
 | 
			
		||||
gboolean meta_window_x11_client_message          (MetaWindow *window,
 | 
			
		||||
                                                  XEvent     *event);
 | 
			
		||||
 | 
			
		||||
void     meta_window_x11_configure_notify        (MetaWindow      *window,
 | 
			
		||||
                                                  XConfigureEvent *event);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -91,6 +91,7 @@ item(hotplug_mode_update)
 | 
			
		||||
item(_NET_WM_SYNC_REQUEST)
 | 
			
		||||
item(_NET_WM_SYNC_REQUEST_COUNTER)
 | 
			
		||||
item(_NET_WM_VISIBLE_NAME)
 | 
			
		||||
item(_NET_WM_VISIBLE_ICON_NAME)
 | 
			
		||||
item(_NET_SUPPORTING_WM_CHECK)
 | 
			
		||||
 | 
			
		||||
/* But I suppose it's quite reasonable not to advertise using
 | 
			
		||||
@@ -131,6 +132,7 @@ item(_NET_CLIENT_LIST)
 | 
			
		||||
item(_NET_CLIENT_LIST_STACKING)
 | 
			
		||||
item(_NET_WM_STATE_SKIP_TASKBAR)
 | 
			
		||||
item(_NET_WM_STATE_SKIP_PAGER)
 | 
			
		||||
item(_NET_WM_ICON_NAME)
 | 
			
		||||
item(_NET_WM_ICON)
 | 
			
		||||
item(_NET_WM_ICON_GEOMETRY)
 | 
			
		||||
item(_NET_WM_MOVERESIZE)
 | 
			
		||||
 
 | 
			
		||||
@@ -163,6 +163,13 @@ typedef void (* MetaWindowMenuFunc) (MetaWindowMenu *menu,
 | 
			
		||||
 * @META_GRAB_OP_KEYBOARD_RESIZING_NE: Resizing NE with keyboard
 | 
			
		||||
 * @META_GRAB_OP_KEYBOARD_RESIZING_SW: Resizing SW with keyboard
 | 
			
		||||
 * @META_GRAB_OP_KEYBOARD_RESIZING_NW: Resizing NS with keyboard
 | 
			
		||||
 * @META_GRAB_OP_KEYBOARD_TABBING_NORMAL: Tabbing
 | 
			
		||||
 * @META_GRAB_OP_KEYBOARD_TABBING_DOCK: Tabbing through docks
 | 
			
		||||
 * @META_GRAB_OP_KEYBOARD_ESCAPING_NORMAL: Escaping
 | 
			
		||||
 * @META_GRAB_OP_KEYBOARD_ESCAPING_DOCK: Escaping through docks
 | 
			
		||||
 * @META_GRAB_OP_KEYBOARD_ESCAPING_GROUP: Escaping through groups
 | 
			
		||||
 * @META_GRAB_OP_KEYBOARD_TABBING_GROUP: Tabbing through groups
 | 
			
		||||
 * @META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING: Switch to another workspace
 | 
			
		||||
 * @META_GRAB_OP_CLICKING_MINIMIZE: Clicked minimize button
 | 
			
		||||
 * @META_GRAB_OP_CLICKING_MAXIMIZE: Clicked maximize button
 | 
			
		||||
 * @META_GRAB_OP_CLICKING_UNMAXIMIZE: Clicked unmaximize button
 | 
			
		||||
@@ -221,10 +228,7 @@ typedef enum
 | 
			
		||||
  META_GRAB_OP_CLICKING_UNSTICK,
 | 
			
		||||
 | 
			
		||||
  /* Special grab op when the compositor asked for a grab */
 | 
			
		||||
  META_GRAB_OP_COMPOSITOR,
 | 
			
		||||
 | 
			
		||||
  /* For when a client takes a popup grab */
 | 
			
		||||
  META_GRAB_OP_WAYLAND_CLIENT,
 | 
			
		||||
  META_GRAB_OP_COMPOSITOR
 | 
			
		||||
} MetaGrabOp;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,6 @@ GOptionContext *meta_get_option_context     (void);
 | 
			
		||||
void            meta_init                   (void);
 | 
			
		||||
int             meta_run                    (void);
 | 
			
		||||
void            meta_register_with_session  (void);
 | 
			
		||||
gboolean        meta_activate_session       (void);
 | 
			
		||||
gboolean        meta_get_replace_current_wm (void);  /* Actually defined in util.c */
 | 
			
		||||
 | 
			
		||||
void            meta_set_wm_name              (const char *wm_name);
 | 
			
		||||
 
 | 
			
		||||
@@ -254,6 +254,9 @@ struct _MetaPluginInfo
 | 
			
		||||
 | 
			
		||||
GType meta_plugin_get_type (void);
 | 
			
		||||
 | 
			
		||||
gboolean      meta_plugin_running             (MetaPlugin *plugin);
 | 
			
		||||
gboolean      meta_plugin_debug_mode          (MetaPlugin *plugin);
 | 
			
		||||
 | 
			
		||||
const MetaPluginInfo * meta_plugin_get_info (MetaPlugin *plugin);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -405,7 +408,8 @@ meta_plugin_end_modal (MetaPlugin *plugin,
 | 
			
		||||
 | 
			
		||||
MetaScreen *meta_plugin_get_screen        (MetaPlugin *plugin);
 | 
			
		||||
 | 
			
		||||
void _meta_plugin_set_screen (MetaPlugin *plugin, MetaScreen *screen);
 | 
			
		||||
void
 | 
			
		||||
_meta_plugin_effect_started (MetaPlugin *plugin);
 | 
			
		||||
 | 
			
		||||
/* XXX: Putting this in here so it's in the public header. */
 | 
			
		||||
void     meta_plugin_manager_set_plugin_type (GType gtype);
 | 
			
		||||
 
 | 
			
		||||
@@ -72,13 +72,11 @@ typedef enum
 | 
			
		||||
 * MetaMaximizeFlags:
 | 
			
		||||
 * @META_MAXIMIZE_HORIZONTAL: Horizontal
 | 
			
		||||
 * @META_MAXIMIZE_VERTICAL: Vertical
 | 
			
		||||
 * @META_MAXIMIZE_BOTH: Both
 | 
			
		||||
 */
 | 
			
		||||
typedef enum
 | 
			
		||||
{
 | 
			
		||||
  META_MAXIMIZE_HORIZONTAL = 1 << 0,
 | 
			
		||||
  META_MAXIMIZE_VERTICAL   = 1 << 1,
 | 
			
		||||
  META_MAXIMIZE_BOTH       = (1 << 0 | 1 << 1),
 | 
			
		||||
  META_MAXIMIZE_VERTICAL   = 1 << 1
 | 
			
		||||
} MetaMaximizeFlags;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -125,6 +123,7 @@ MetaScreen *meta_window_get_screen (MetaWindow *window);
 | 
			
		||||
MetaDisplay *meta_window_get_display (MetaWindow *window);
 | 
			
		||||
Window meta_window_get_xwindow (MetaWindow *window);
 | 
			
		||||
MetaWindowType meta_window_get_window_type (MetaWindow *window);
 | 
			
		||||
Atom meta_window_get_window_type_atom (MetaWindow *window);
 | 
			
		||||
MetaWorkspace *meta_window_get_workspace (MetaWindow *window);
 | 
			
		||||
int      meta_window_get_monitor (MetaWindow *window);
 | 
			
		||||
gboolean meta_window_is_on_all_workspaces (MetaWindow *window);
 | 
			
		||||
@@ -164,6 +163,7 @@ void meta_window_change_workspace          (MetaWindow  *window,
 | 
			
		||||
                                            MetaWorkspace *workspace);
 | 
			
		||||
GObject *meta_window_get_compositor_private (MetaWindow *window);
 | 
			
		||||
void meta_window_set_compositor_private (MetaWindow *window, GObject *priv);
 | 
			
		||||
void meta_window_configure_notify (MetaWindow *window, XConfigureEvent *event);
 | 
			
		||||
const char *meta_window_get_role (MetaWindow *window);
 | 
			
		||||
MetaStackLayer meta_window_get_layer (MetaWindow *window);
 | 
			
		||||
MetaWindow* meta_window_find_root_ancestor    (MetaWindow *window);
 | 
			
		||||
@@ -203,6 +203,7 @@ void        meta_window_raise              (MetaWindow  *window);
 | 
			
		||||
void        meta_window_lower              (MetaWindow  *window);
 | 
			
		||||
const char *meta_window_get_title (MetaWindow *window);
 | 
			
		||||
MetaWindow *meta_window_get_transient_for (MetaWindow *window);
 | 
			
		||||
Window      meta_window_get_transient_for_as_xid (MetaWindow *window);
 | 
			
		||||
void        meta_window_delete             (MetaWindow  *window,
 | 
			
		||||
                                            guint32      timestamp);
 | 
			
		||||
guint       meta_window_get_stable_sequence (MetaWindow *window);
 | 
			
		||||
@@ -210,6 +211,7 @@ guint32     meta_window_get_user_time (MetaWindow *window);
 | 
			
		||||
int         meta_window_get_pid (MetaWindow *window);
 | 
			
		||||
const char *meta_window_get_client_machine (MetaWindow *window);
 | 
			
		||||
gboolean    meta_window_is_remote (MetaWindow *window);
 | 
			
		||||
gboolean    meta_window_is_modal (MetaWindow *window);
 | 
			
		||||
gboolean    meta_window_is_attached_dialog (MetaWindow *window);
 | 
			
		||||
const char *meta_window_get_mutter_hints (MetaWindow *window);
 | 
			
		||||
 | 
			
		||||
@@ -250,16 +252,6 @@ void meta_window_begin_grab_op (MetaWindow *window,
 | 
			
		||||
                                gboolean    frame_action,
 | 
			
		||||
                                guint32     timestamp);
 | 
			
		||||
 | 
			
		||||
gboolean meta_window_can_maximize (MetaWindow *window);
 | 
			
		||||
gboolean meta_window_can_minimize (MetaWindow *window);
 | 
			
		||||
gboolean meta_window_can_shade (MetaWindow *window);
 | 
			
		||||
gboolean meta_window_can_close (MetaWindow *window);
 | 
			
		||||
gboolean meta_window_is_always_on_all_workspaces (MetaWindow *window);
 | 
			
		||||
gboolean meta_window_is_above (MetaWindow *window);
 | 
			
		||||
gboolean meta_window_allows_move (MetaWindow *window);
 | 
			
		||||
gboolean meta_window_allows_resize (MetaWindow *window);
 | 
			
		||||
 | 
			
		||||
gboolean meta_window_titlebar_is_onscreen    (MetaWindow *window);
 | 
			
		||||
void     meta_window_shove_titlebar_onscreen (MetaWindow *window);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
[Desktop Entry]
 | 
			
		||||
Type=Application
 | 
			
		||||
_Name=Mutter (wayland compositor)
 | 
			
		||||
Exec=mutter-launch -- mutter --wayland --display-server
 | 
			
		||||
Exec=mutter-launch -- mutter --wayland
 | 
			
		||||
NoDisplay=true
 | 
			
		||||
# name of loadable control center module
 | 
			
		||||
X-GNOME-WMSettingsModule=metacity
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										109
									
								
								src/run-mutter.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										109
									
								
								src/run-mutter.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,109 @@
 | 
			
		||||
#! /bin/bash
 | 
			
		||||
 | 
			
		||||
if test -z "$XNEST_DISPLAY"; then
 | 
			
		||||
  XNEST_DISPLAY=:8
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test -z "$CLIENT_DISPLAY"; then
 | 
			
		||||
  CLIENT_DISPLAY=:8
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test -z "$MUTTER_DISPLAY"; then
 | 
			
		||||
  export MUTTER_DISPLAY=$CLIENT_DISPLAY
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test -z "$SCREENS"; then
 | 
			
		||||
  SCREENS=1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
MAX_SCREEN=`echo $SCREENS-1 | bc`
 | 
			
		||||
 | 
			
		||||
if test "$DEBUG" = none; then
 | 
			
		||||
  DEBUG=
 | 
			
		||||
elif test -z "$DEBUG"; then
 | 
			
		||||
  DEBUG=
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test -z "$CLIENTS"; then
 | 
			
		||||
  CLIENTS=0
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test -z "$SM_CLIENTS"; then
 | 
			
		||||
  SM_CLIENTS=0
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test -n "$EVIL_TEST"; then
 | 
			
		||||
  TEST_CLIENT='./wm-tester/wm-tester --evil'
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test -n "$ICON_TEST"; then
 | 
			
		||||
  TEST_CLIENT='./wm-tester/wm-tester --icon-windows'
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test -n "$DEMO_TEST"; then
 | 
			
		||||
  TEST_CLIENT='./tools/mutter-window-demo'
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test -n "$XINERAMA"; then
 | 
			
		||||
  XINERAMA_FLAGS='+xinerama'
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
export EF_ALLOW_MALLOC_0=1
 | 
			
		||||
 | 
			
		||||
if test -z "$ONLY_WM"; then
 | 
			
		||||
  echo "Launching Xnest"
 | 
			
		||||
  Xnest -ac $XNEST_DISPLAY -scrns $SCREENS -geometry 640x480 -bw 15 $XINERAMA_FLAGS &
 | 
			
		||||
  ## usleep 800000
 | 
			
		||||
  sleep 1
 | 
			
		||||
 | 
			
		||||
  if test -n "$XMON_DIR"; then
 | 
			
		||||
    echo "Launching xmond"
 | 
			
		||||
    $XMON_DIR/xmonui | $XMON_DIR/xmond -server localhost:$XNEST_DISPLAY &
 | 
			
		||||
    sleep 1
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if test -n "$XSCOPE_DIR"; then
 | 
			
		||||
    ## xscope doesn't like to die when it should, it backgrounds itself
 | 
			
		||||
    killall -9 xscope
 | 
			
		||||
    killall -9 xscope
 | 
			
		||||
    echo "Launching xscope"
 | 
			
		||||
    DISPLAY= $XSCOPE_DIR/xscope -o1 -i28  > xscoped-replies.txt &
 | 
			
		||||
    export MUTTER_DISPLAY=localhost:28
 | 
			
		||||
    sleep 1
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  echo "Launching clients"
 | 
			
		||||
  if test -n "$TEST_CLIENT"; then
 | 
			
		||||
      for I in `seq 0 $MAX_SCREEN`; do
 | 
			
		||||
          DISPLAY=$CLIENT_DISPLAY.$I $TEST_CLIENT &
 | 
			
		||||
      done
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if test $CLIENTS != 0; then
 | 
			
		||||
    for I in `seq 1 $CLIENTS`; do
 | 
			
		||||
      echo "Launching xterm $I"
 | 
			
		||||
      DISPLAY=$CLIENT_DISPLAY xterm -geometry 25x15 &
 | 
			
		||||
    done
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if test $SM_CLIENTS != 0; then
 | 
			
		||||
    for I in `seq 1 $SM_CLIENTS`; do
 | 
			
		||||
      echo "Launching gnome-terminal $I"
 | 
			
		||||
      DISPLAY=$CLIENT_DISPLAY gnome-terminal --geometry 25x15 &
 | 
			
		||||
    done
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if test -e ~/.Xmodmap; then
 | 
			
		||||
      DISPLAY=$CLIENT_DISPLAY xmodmap ~/.Xmodmap
 | 
			
		||||
  fi
 | 
			
		||||
 
 | 
			
		||||
  usleep 50000
 | 
			
		||||
 | 
			
		||||
  for I in `seq 0 $MAX_SCREEN`; do
 | 
			
		||||
      DISPLAY=$CLIENT_DISPLAY.$I xsetroot -solid royalblue3
 | 
			
		||||
  done
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test -z "$ONLY_SETUP"; then
 | 
			
		||||
  MUTTER_VERBOSE=1 MUTTER_USE_LOGFILE=1 MUTTER_DEBUG_BUTTON_GRABS=1 exec $DEBUG ./mutter $OPTIONS
 | 
			
		||||
fi
 | 
			
		||||
@@ -48,7 +48,7 @@ data_offer_accept (struct wl_client *client,
 | 
			
		||||
   * this be a wl_data_device request? */
 | 
			
		||||
 | 
			
		||||
  if (offer->source)
 | 
			
		||||
    wl_data_source_send_target (offer->source->resource, mime_type);
 | 
			
		||||
    offer->source->accept (offer->source, serial, mime_type);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -58,9 +58,9 @@ data_offer_receive (struct wl_client *client, struct wl_resource *resource,
 | 
			
		||||
  MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource);
 | 
			
		||||
 | 
			
		||||
  if (offer->source)
 | 
			
		||||
    wl_data_source_send_send (offer->source->resource, mime_type, fd);
 | 
			
		||||
 | 
			
		||||
  close (fd);
 | 
			
		||||
    offer->source->send (offer->source, mime_type, fd);
 | 
			
		||||
  else
 | 
			
		||||
    close (fd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -82,8 +82,7 @@ destroy_data_offer (struct wl_resource *resource)
 | 
			
		||||
 | 
			
		||||
  if (offer->source)
 | 
			
		||||
    wl_list_remove (&offer->source_destroy_listener.link);
 | 
			
		||||
 | 
			
		||||
  g_slice_free (MetaWaylandDataOffer, offer);
 | 
			
		||||
  free (offer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -100,9 +99,13 @@ static struct wl_resource *
 | 
			
		||||
meta_wayland_data_source_send_offer (MetaWaylandDataSource *source,
 | 
			
		||||
                                     struct wl_resource *target)
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandDataOffer *offer = g_slice_new0 (MetaWaylandDataOffer);
 | 
			
		||||
  MetaWaylandDataOffer *offer;
 | 
			
		||||
  char **p;
 | 
			
		||||
 | 
			
		||||
  offer = malloc (sizeof *offer);
 | 
			
		||||
  if (offer == NULL)
 | 
			
		||||
    return NULL;
 | 
			
		||||
 | 
			
		||||
  offer->source = source;
 | 
			
		||||
  offer->source_destroy_listener.notify = destroy_offer_data_source;
 | 
			
		||||
 | 
			
		||||
@@ -175,7 +178,8 @@ destroy_drag_focus (struct wl_listener *listener, void *data)
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
drag_grab_focus (MetaWaylandPointerGrab *grab,
 | 
			
		||||
                 MetaWaylandSurface     *surface)
 | 
			
		||||
                 MetaWaylandSurface     *surface,
 | 
			
		||||
		 const ClutterEvent     *event)
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab;
 | 
			
		||||
  MetaWaylandSeat *seat = drag_grab->seat;
 | 
			
		||||
@@ -256,7 +260,7 @@ data_device_end_drag_grab (MetaWaylandDragGrab *drag_grab)
 | 
			
		||||
  if (drag_grab->drag_data_source)
 | 
			
		||||
    wl_list_remove (&drag_grab->drag_data_source_listener.link);
 | 
			
		||||
 | 
			
		||||
  drag_grab_focus (&drag_grab->generic, NULL);
 | 
			
		||||
  drag_grab_focus (&drag_grab->generic, NULL, NULL);
 | 
			
		||||
 | 
			
		||||
  meta_wayland_pointer_end_grab (drag_grab->generic.pointer);
 | 
			
		||||
  g_slice_free (MetaWaylandDragGrab, drag_grab);
 | 
			
		||||
@@ -314,12 +318,8 @@ data_device_start_drag (struct wl_client *client,
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandSeat *seat = wl_resource_get_user_data (resource);
 | 
			
		||||
  MetaWaylandDragGrab *drag_grab;
 | 
			
		||||
 | 
			
		||||
  if ((seat->pointer.button_count == 0 ||
 | 
			
		||||
       seat->pointer.grab_serial != serial ||
 | 
			
		||||
       !seat->pointer.focus_surface ||
 | 
			
		||||
       seat->pointer.focus_surface != wl_resource_get_user_data (origin_resource)))
 | 
			
		||||
    return;
 | 
			
		||||
  /* FIXME: Check that client has implicit grab on the origin
 | 
			
		||||
   * surface that matches the given time. */
 | 
			
		||||
 | 
			
		||||
  /* FIXME: Check that the data source type array isn't empty. */
 | 
			
		||||
 | 
			
		||||
@@ -332,7 +332,6 @@ data_device_start_drag (struct wl_client *client,
 | 
			
		||||
  drag_grab->generic.pointer = &seat->pointer;
 | 
			
		||||
 | 
			
		||||
  drag_grab->drag_client = client;
 | 
			
		||||
  drag_grab->seat = seat;
 | 
			
		||||
 | 
			
		||||
  if (source_resource)
 | 
			
		||||
    {
 | 
			
		||||
@@ -376,7 +375,7 @@ destroy_selection_data_source (struct wl_listener *listener, void *data)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_seat_set_selection (MetaWaylandSeat *seat,
 | 
			
		||||
                                 MetaWaylandDataSource *source,
 | 
			
		||||
                                 guint32 serial)
 | 
			
		||||
@@ -390,7 +389,7 @@ meta_wayland_seat_set_selection (MetaWaylandSeat *seat,
 | 
			
		||||
 | 
			
		||||
  if (seat->selection_data_source)
 | 
			
		||||
    {
 | 
			
		||||
      wl_data_source_send_cancelled (seat->selection_data_source->resource);
 | 
			
		||||
      seat->selection_data_source->cancel (seat->selection_data_source);
 | 
			
		||||
      wl_list_remove (&seat->selection_data_source_listener.link);
 | 
			
		||||
      seat->selection_data_source = NULL;
 | 
			
		||||
    }
 | 
			
		||||
@@ -450,21 +449,47 @@ static const struct wl_data_device_interface data_device_interface = {
 | 
			
		||||
static void
 | 
			
		||||
destroy_data_source (struct wl_resource *resource)
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
 | 
			
		||||
  MetaWaylandDataSource *source = wl_container_of (resource, source, resource);
 | 
			
		||||
  char **p;
 | 
			
		||||
 | 
			
		||||
  wl_array_for_each (p, &source->mime_types) free (*p);
 | 
			
		||||
 | 
			
		||||
  wl_array_release (&source->mime_types);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
  g_slice_free (MetaWaylandDataSource, source);
 | 
			
		||||
static void
 | 
			
		||||
client_source_accept (MetaWaylandDataSource *source,
 | 
			
		||||
                      guint32 time, const char *mime_type)
 | 
			
		||||
{
 | 
			
		||||
  wl_data_source_send_target (source->resource, mime_type);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
client_source_send (MetaWaylandDataSource *source,
 | 
			
		||||
                    const char *mime_type, int32_t fd)
 | 
			
		||||
{
 | 
			
		||||
  wl_data_source_send_send (source->resource, mime_type, fd);
 | 
			
		||||
  close (fd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
client_source_cancel (MetaWaylandDataSource *source)
 | 
			
		||||
{
 | 
			
		||||
  wl_data_source_send_cancelled (source->resource);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
create_data_source (struct wl_client *client,
 | 
			
		||||
                    struct wl_resource *resource, guint32 id)
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandDataSource *source = g_slice_new0 (MetaWaylandDataSource);
 | 
			
		||||
  MetaWaylandDataSource *source;
 | 
			
		||||
 | 
			
		||||
  source = malloc (sizeof *source);
 | 
			
		||||
  if (source == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      wl_resource_post_no_memory (resource);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  source->resource = wl_resource_create (client, &wl_data_source_interface,
 | 
			
		||||
					 MIN (META_WL_DATA_SOURCE_VERSION,
 | 
			
		||||
@@ -472,6 +497,10 @@ create_data_source (struct wl_client *client,
 | 
			
		||||
  wl_resource_set_implementation (source->resource, &data_source_interface,
 | 
			
		||||
				  source, destroy_data_source);
 | 
			
		||||
 | 
			
		||||
  source->accept = client_source_accept;
 | 
			
		||||
  source->send = client_source_send;
 | 
			
		||||
  source->cancel = client_source_cancel;
 | 
			
		||||
 | 
			
		||||
  wl_array_init (&source->mime_types);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -33,4 +33,10 @@ meta_wayland_data_device_set_keyboard_focus (MetaWaylandSeat *seat);
 | 
			
		||||
int
 | 
			
		||||
meta_wayland_data_device_manager_init (struct wl_display *display);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_seat_set_selection (MetaWaylandSeat *seat,
 | 
			
		||||
                                 MetaWaylandDataSource *source,
 | 
			
		||||
                                 uint32_t serial);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif /* __META_WAYLAND_DATA_DEVICE_H__ */
 | 
			
		||||
 
 | 
			
		||||
@@ -138,11 +138,23 @@ meta_wayland_keyboard_take_keymap (MetaWaylandKeyboard *keyboard,
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  xkb_keymap_unref (xkb_info->keymap);
 | 
			
		||||
  if (xkb_info->keymap)
 | 
			
		||||
    xkb_keymap_unref (xkb_info->keymap);
 | 
			
		||||
  xkb_info->keymap = keymap;
 | 
			
		||||
 | 
			
		||||
  xkb_state_unref (xkb_info->state);
 | 
			
		||||
  xkb_info->state = xkb_state_new (keymap);
 | 
			
		||||
  xkb_info->shift_mod =
 | 
			
		||||
    xkb_map_mod_get_index (xkb_info->keymap, XKB_MOD_NAME_SHIFT);
 | 
			
		||||
  xkb_info->caps_mod =
 | 
			
		||||
    xkb_map_mod_get_index (xkb_info->keymap, XKB_MOD_NAME_CAPS);
 | 
			
		||||
  xkb_info->ctrl_mod =
 | 
			
		||||
    xkb_map_mod_get_index (xkb_info->keymap, XKB_MOD_NAME_CTRL);
 | 
			
		||||
  xkb_info->alt_mod =
 | 
			
		||||
    xkb_map_mod_get_index (xkb_info->keymap, XKB_MOD_NAME_ALT);
 | 
			
		||||
  xkb_info->mod2_mod = xkb_map_mod_get_index (xkb_info->keymap, "Mod2");
 | 
			
		||||
  xkb_info->mod3_mod = xkb_map_mod_get_index (xkb_info->keymap, "Mod3");
 | 
			
		||||
  xkb_info->super_mod =
 | 
			
		||||
    xkb_map_mod_get_index (xkb_info->keymap, XKB_MOD_NAME_LOGO);
 | 
			
		||||
  xkb_info->mod5_mod = xkb_map_mod_get_index (xkb_info->keymap, "Mod5");
 | 
			
		||||
 | 
			
		||||
  keymap_str = xkb_map_get_as_string (xkb_info->keymap);
 | 
			
		||||
  if (keymap_str == NULL)
 | 
			
		||||
@@ -283,6 +295,31 @@ static const MetaWaylandKeyboardGrabInterface
 | 
			
		||||
  default_grab_modifiers,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
modal_key (MetaWaylandKeyboardGrab *grab,
 | 
			
		||||
	   uint32_t                 time,
 | 
			
		||||
	   uint32_t                 key,
 | 
			
		||||
	   uint32_t                 state)
 | 
			
		||||
{
 | 
			
		||||
  /* FALSE means: let the event through to clutter */
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
modal_modifiers (MetaWaylandKeyboardGrab *grab,
 | 
			
		||||
		 uint32_t                 serial,
 | 
			
		||||
		 uint32_t                 mods_depressed,
 | 
			
		||||
		 uint32_t                 mods_latched,
 | 
			
		||||
		 uint32_t                 mods_locked,
 | 
			
		||||
		 uint32_t                 group)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaWaylandKeyboardGrabInterface modal_grab = {
 | 
			
		||||
  modal_key,
 | 
			
		||||
  modal_modifiers,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
 | 
			
		||||
                            struct wl_display   *display)
 | 
			
		||||
@@ -318,8 +355,8 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
 | 
			
		||||
static void
 | 
			
		||||
meta_wayland_xkb_info_destroy (MetaWaylandXkbInfo *xkb_info)
 | 
			
		||||
{
 | 
			
		||||
  xkb_keymap_unref (xkb_info->keymap);
 | 
			
		||||
  xkb_state_unref (xkb_info->state);
 | 
			
		||||
  if (xkb_info->keymap)
 | 
			
		||||
    xkb_map_unref (xkb_info->keymap);
 | 
			
		||||
 | 
			
		||||
  if (xkb_info->keymap_area)
 | 
			
		||||
    munmap (xkb_info->keymap_area, xkb_info->keymap_size);
 | 
			
		||||
@@ -327,7 +364,47 @@ meta_wayland_xkb_info_destroy (MetaWaylandXkbInfo *xkb_info)
 | 
			
		||||
    close (xkb_info->keymap_fd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
state_equal (MetaWaylandXkbState *one,
 | 
			
		||||
	     MetaWaylandXkbState *two)
 | 
			
		||||
{
 | 
			
		||||
  return one->mods_depressed == two->mods_depressed &&
 | 
			
		||||
    one->mods_latched == two->mods_latched &&
 | 
			
		||||
    one->mods_locked == two->mods_locked &&
 | 
			
		||||
    one->group == two->group;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
set_modifiers (MetaWaylandKeyboard *keyboard,
 | 
			
		||||
               guint32              serial,
 | 
			
		||||
               ClutterEvent        *event)
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandKeyboardGrab *grab = keyboard->grab;
 | 
			
		||||
  MetaWaylandXkbState new_state;
 | 
			
		||||
  guint effective_state;
 | 
			
		||||
 | 
			
		||||
  clutter_event_get_state_full (event,
 | 
			
		||||
				NULL,
 | 
			
		||||
				&new_state.mods_depressed,
 | 
			
		||||
				&new_state.mods_latched,
 | 
			
		||||
				&new_state.mods_locked,
 | 
			
		||||
				&effective_state);
 | 
			
		||||
  new_state.group = (effective_state >> 13) & 0x3;
 | 
			
		||||
 | 
			
		||||
  if (state_equal (&keyboard->modifier_state, &new_state))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  keyboard->modifier_state = new_state;
 | 
			
		||||
 | 
			
		||||
  grab->interface->modifiers (grab,
 | 
			
		||||
                              serial,
 | 
			
		||||
                              new_state.mods_depressed,
 | 
			
		||||
			      new_state.mods_latched,
 | 
			
		||||
			      new_state.mods_locked,
 | 
			
		||||
                              new_state.group);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
update_pressed_keys (MetaWaylandKeyboard   *keyboard,
 | 
			
		||||
		     uint32_t               evdev_code,
 | 
			
		||||
		     gboolean               is_press)
 | 
			
		||||
@@ -338,10 +415,13 @@ update_pressed_keys (MetaWaylandKeyboard   *keyboard,
 | 
			
		||||
                                keyboard->keys.size);
 | 
			
		||||
      uint32_t *k;
 | 
			
		||||
 | 
			
		||||
      /* Make sure we don't already have this key. */
 | 
			
		||||
      /* We want to ignore events that are sent because of auto-repeat. In
 | 
			
		||||
	 the Clutter event stream these appear as a single key press
 | 
			
		||||
	 event. We can detect that because the key will already have been
 | 
			
		||||
	 pressed */
 | 
			
		||||
      for (k = keyboard->keys.data; k < end; k++)
 | 
			
		||||
        if (*k == evdev_code)
 | 
			
		||||
          return;
 | 
			
		||||
          return TRUE;
 | 
			
		||||
 | 
			
		||||
      /* Otherwise add the key to the list of pressed keys */
 | 
			
		||||
      k = wl_array_add (&keyboard->keys, sizeof (*k));
 | 
			
		||||
@@ -359,44 +439,18 @@ update_pressed_keys (MetaWaylandKeyboard   *keyboard,
 | 
			
		||||
          {
 | 
			
		||||
            *k = *(end - 1);
 | 
			
		||||
            keyboard->keys.size -= sizeof (*k);
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
            goto found;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
      g_warning ("unexpected key release event for key 0x%x", evdev_code);
 | 
			
		||||
      return FALSE;
 | 
			
		||||
 | 
			
		||||
    found:
 | 
			
		||||
      (void) 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static guint
 | 
			
		||||
evdev_code (const ClutterKeyEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  /* clutter-xkb-utils.c adds a fixed offset of 8 to go into XKB's
 | 
			
		||||
   * range, so we do the reverse here. */
 | 
			
		||||
  return event->hardware_keycode - 8;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_keyboard_update (MetaWaylandKeyboard *keyboard,
 | 
			
		||||
                              const ClutterKeyEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandKeyboardGrab *grab = keyboard->grab;
 | 
			
		||||
  gboolean is_press = event->type == CLUTTER_KEY_PRESS;
 | 
			
		||||
  struct xkb_state *state = keyboard->xkb_info.state;
 | 
			
		||||
  enum xkb_state_component changed_state;
 | 
			
		||||
 | 
			
		||||
  update_pressed_keys (keyboard, evdev_code (event), is_press);
 | 
			
		||||
 | 
			
		||||
  changed_state = xkb_state_update_key (state,
 | 
			
		||||
                                        event->hardware_keycode,
 | 
			
		||||
                                        is_press ? XKB_KEY_DOWN : XKB_KEY_UP);
 | 
			
		||||
  if (changed_state == 0)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  grab->interface->modifiers (grab,
 | 
			
		||||
                              wl_display_next_serial (keyboard->display),
 | 
			
		||||
                              xkb_state_serialize_mods (state, XKB_STATE_MODS_DEPRESSED),
 | 
			
		||||
                              xkb_state_serialize_mods (state, XKB_STATE_MODS_LATCHED),
 | 
			
		||||
                              xkb_state_serialize_mods (state, XKB_STATE_MODS_LOCKED),
 | 
			
		||||
                              xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_EFFECTIVE));
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
@@ -404,20 +458,34 @@ meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard,
 | 
			
		||||
                                    const ClutterKeyEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  gboolean is_press = event->type == CLUTTER_KEY_PRESS;
 | 
			
		||||
  guint xkb_keycode, evdev_code;
 | 
			
		||||
  uint32_t serial;
 | 
			
		||||
  gboolean autorepeat;
 | 
			
		||||
  gboolean handled;
 | 
			
		||||
 | 
			
		||||
  /* Synthetic key events are for autorepeat. Ignore those, as
 | 
			
		||||
   * autorepeat in Wayland is done on the client side. */
 | 
			
		||||
  if (event->flags & CLUTTER_EVENT_FLAG_SYNTHETIC)
 | 
			
		||||
  xkb_keycode = event->hardware_keycode;
 | 
			
		||||
  if (event->device == NULL ||
 | 
			
		||||
      !clutter_input_device_keycode_to_evdev (event->device,
 | 
			
		||||
					      xkb_keycode, &evdev_code))
 | 
			
		||||
    evdev_code = xkb_keycode - 8; /* What everyone is doing in practice... */
 | 
			
		||||
 | 
			
		||||
  autorepeat = update_pressed_keys (keyboard, evdev_code, is_press);
 | 
			
		||||
 | 
			
		||||
  meta_verbose ("Handling key %s%s event code %d\n",
 | 
			
		||||
		is_press ? "press" : "release",
 | 
			
		||||
		autorepeat ? " (autorepeat)" : "",
 | 
			
		||||
		xkb_keycode);
 | 
			
		||||
 | 
			
		||||
  if (autorepeat)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  meta_verbose ("Handling key %s event code %d\n",
 | 
			
		||||
		is_press ? "press" : "release",
 | 
			
		||||
		event->hardware_keycode);
 | 
			
		||||
  serial = wl_display_next_serial (keyboard->display);
 | 
			
		||||
 | 
			
		||||
  set_modifiers (keyboard, serial, (ClutterEvent*)event);
 | 
			
		||||
 | 
			
		||||
  handled = keyboard->grab->interface->key (keyboard->grab,
 | 
			
		||||
					    event->time,
 | 
			
		||||
					    evdev_code (event),
 | 
			
		||||
					    evdev_code,
 | 
			
		||||
					    is_press);
 | 
			
		||||
 | 
			
		||||
  if (handled)
 | 
			
		||||
@@ -465,16 +533,28 @@ meta_wayland_keyboard_set_focus (MetaWaylandKeyboard *keyboard,
 | 
			
		||||
        {
 | 
			
		||||
          struct wl_client *client = wl_resource_get_client (keyboard->focus_resource);
 | 
			
		||||
          struct wl_display *display = wl_client_get_display (client);
 | 
			
		||||
          struct xkb_state *state = keyboard->xkb_info.state;
 | 
			
		||||
          uint32_t serial = wl_display_next_serial (display);
 | 
			
		||||
 | 
			
		||||
          wl_keyboard_send_modifiers (keyboard->focus_resource, serial,
 | 
			
		||||
                                      xkb_state_serialize_mods (state, XKB_STATE_MODS_DEPRESSED),
 | 
			
		||||
                                      xkb_state_serialize_mods (state, XKB_STATE_MODS_LATCHED),
 | 
			
		||||
                                      xkb_state_serialize_mods (state, XKB_STATE_MODS_LOCKED),
 | 
			
		||||
                                      xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_EFFECTIVE));
 | 
			
		||||
          wl_keyboard_send_enter (keyboard->focus_resource, serial, keyboard->focus_surface->resource,
 | 
			
		||||
                                  &keyboard->keys);
 | 
			
		||||
          /* If we're in a modal grab, the client is focused but doesn't see
 | 
			
		||||
             modifiers or pressed keys (and fix that up when we exit the modal) */
 | 
			
		||||
          if (keyboard->grab->interface == &modal_grab)
 | 
			
		||||
            {
 | 
			
		||||
              struct wl_array empty;
 | 
			
		||||
              wl_array_init (&empty);
 | 
			
		||||
 | 
			
		||||
              wl_keyboard_send_modifiers (keyboard->focus_resource, serial, 0, 0, 0, 0);
 | 
			
		||||
              wl_keyboard_send_enter (keyboard->focus_resource, serial, keyboard->focus_surface->resource, &empty);
 | 
			
		||||
            }
 | 
			
		||||
          else
 | 
			
		||||
            {
 | 
			
		||||
              wl_keyboard_send_modifiers (keyboard->focus_resource, serial,
 | 
			
		||||
                                          keyboard->modifier_state.mods_depressed,
 | 
			
		||||
                                          keyboard->modifier_state.mods_latched,
 | 
			
		||||
                                          keyboard->modifier_state.mods_locked,
 | 
			
		||||
                                          keyboard->modifier_state.group);
 | 
			
		||||
              wl_keyboard_send_enter (keyboard->focus_resource, serial, keyboard->focus_surface->resource,
 | 
			
		||||
                                      &keyboard->keys);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          wl_resource_add_destroy_listener (keyboard->focus_resource, &keyboard->focus_resource_listener);
 | 
			
		||||
          keyboard->focus_serial = serial;
 | 
			
		||||
@@ -508,6 +588,85 @@ meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard)
 | 
			
		||||
  wl_array_release (&keyboard->keys);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_wayland_keyboard_begin_modal (MetaWaylandKeyboard *keyboard,
 | 
			
		||||
				   guint32              timestamp)
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandKeyboardGrab *grab;
 | 
			
		||||
  uint32_t *end = (void *) ((char *) keyboard->keys.data +
 | 
			
		||||
			    keyboard->keys.size);
 | 
			
		||||
  uint32_t *k;
 | 
			
		||||
  uint32_t serial;
 | 
			
		||||
 | 
			
		||||
  meta_verbose ("Asked to acquire modal keyboard grab, timestamp %d\n", timestamp);
 | 
			
		||||
 | 
			
		||||
  if (keyboard->grab != &keyboard->default_grab)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  if (keyboard->focus_surface)
 | 
			
		||||
    {
 | 
			
		||||
      /* Fake key release events for the focused app */
 | 
			
		||||
      serial = wl_display_next_serial (keyboard->display);
 | 
			
		||||
      keyboard->grab->interface->modifiers (keyboard->grab,
 | 
			
		||||
					    serial,
 | 
			
		||||
					    0, 0, 0, 0);
 | 
			
		||||
 | 
			
		||||
      for (k = keyboard->keys.data; k < end; k++)
 | 
			
		||||
	{
 | 
			
		||||
	  keyboard->grab->interface->key (keyboard->grab,
 | 
			
		||||
					  timestamp,
 | 
			
		||||
					  *k, 0);
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  grab = g_slice_new0 (MetaWaylandKeyboardGrab);
 | 
			
		||||
  grab->interface = &modal_grab;
 | 
			
		||||
  meta_wayland_keyboard_start_grab (keyboard, grab);
 | 
			
		||||
 | 
			
		||||
  meta_verbose ("Acquired modal keyboard grab, timestamp %d\n", timestamp);
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_keyboard_end_modal (MetaWaylandKeyboard *keyboard,
 | 
			
		||||
				 guint32              timestamp)
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandKeyboardGrab *grab;
 | 
			
		||||
  uint32_t *end = (void *) ((char *) keyboard->keys.data +
 | 
			
		||||
			    keyboard->keys.size);
 | 
			
		||||
  uint32_t *k;
 | 
			
		||||
  uint32_t serial;
 | 
			
		||||
 | 
			
		||||
  grab = keyboard->grab;
 | 
			
		||||
 | 
			
		||||
  g_assert (grab->interface == &modal_grab);
 | 
			
		||||
 | 
			
		||||
  meta_wayland_keyboard_end_grab (keyboard);
 | 
			
		||||
  g_slice_free (MetaWaylandKeyboardGrab, grab);
 | 
			
		||||
 | 
			
		||||
  if (keyboard->focus_surface)
 | 
			
		||||
    {
 | 
			
		||||
      /* Fake key press events for the focused app */
 | 
			
		||||
      serial = wl_display_next_serial (keyboard->display);
 | 
			
		||||
      keyboard->grab->interface->modifiers (keyboard->grab,
 | 
			
		||||
					    serial,
 | 
			
		||||
					    keyboard->modifier_state.mods_depressed,
 | 
			
		||||
					    keyboard->modifier_state.mods_latched, 
 | 
			
		||||
					    keyboard->modifier_state.mods_locked,
 | 
			
		||||
					    keyboard->modifier_state.group);
 | 
			
		||||
 | 
			
		||||
      for (k = keyboard->keys.data; k < end; k++)
 | 
			
		||||
	{
 | 
			
		||||
	  keyboard->grab->interface->key (keyboard->grab,
 | 
			
		||||
					  timestamp,
 | 
			
		||||
					  *k, 1);
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_verbose ("Released modal keyboard grab, timestamp %d\n", timestamp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_keyboard_set_keymap_names (MetaWaylandKeyboard *keyboard,
 | 
			
		||||
					const char          *rules,
 | 
			
		||||
 
 | 
			
		||||
@@ -69,12 +69,27 @@ struct _MetaWaylandKeyboardGrab
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
  struct xkb_keymap *keymap;
 | 
			
		||||
  struct xkb_state *state;
 | 
			
		||||
  int keymap_fd;
 | 
			
		||||
  size_t keymap_size;
 | 
			
		||||
  char *keymap_area;
 | 
			
		||||
  xkb_mod_index_t shift_mod;
 | 
			
		||||
  xkb_mod_index_t caps_mod;
 | 
			
		||||
  xkb_mod_index_t ctrl_mod;
 | 
			
		||||
  xkb_mod_index_t alt_mod;
 | 
			
		||||
  xkb_mod_index_t mod2_mod;
 | 
			
		||||
  xkb_mod_index_t mod3_mod;
 | 
			
		||||
  xkb_mod_index_t super_mod;
 | 
			
		||||
  xkb_mod_index_t mod5_mod;
 | 
			
		||||
} MetaWaylandXkbInfo;
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
  uint32_t mods_depressed;
 | 
			
		||||
  uint32_t mods_latched;
 | 
			
		||||
  uint32_t mods_locked;
 | 
			
		||||
  uint32_t group;
 | 
			
		||||
} MetaWaylandXkbState;
 | 
			
		||||
 | 
			
		||||
struct _MetaWaylandKeyboard
 | 
			
		||||
{
 | 
			
		||||
  struct wl_list resource_list;
 | 
			
		||||
@@ -93,6 +108,8 @@ struct _MetaWaylandKeyboard
 | 
			
		||||
 | 
			
		||||
  struct wl_array keys;
 | 
			
		||||
 | 
			
		||||
  MetaWaylandXkbState modifier_state;
 | 
			
		||||
 | 
			
		||||
  struct wl_display *display;
 | 
			
		||||
 | 
			
		||||
  struct xkb_context *xkb_context;
 | 
			
		||||
@@ -133,11 +150,14 @@ meta_wayland_keyboard_start_grab (MetaWaylandKeyboard *device,
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_keyboard_end_grab (MetaWaylandKeyboard *keyboard);
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_wayland_keyboard_begin_modal (MetaWaylandKeyboard *keyboard,
 | 
			
		||||
				   guint32              timestamp);
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_keyboard_end_modal   (MetaWaylandKeyboard *keyboard,
 | 
			
		||||
				   guint32              timestamp);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_keyboard_update (MetaWaylandKeyboard *keyboard,
 | 
			
		||||
                              const ClutterKeyEvent *event);
 | 
			
		||||
 | 
			
		||||
#endif /* __META_WAYLAND_KEYBOARD_H__ */
 | 
			
		||||
 
 | 
			
		||||
@@ -78,7 +78,8 @@ pointer_handle_focus_resource_destroy (struct wl_listener *listener, void *data)
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
default_grab_focus (MetaWaylandPointerGrab *grab,
 | 
			
		||||
                    MetaWaylandSurface     *surface)
 | 
			
		||||
                    MetaWaylandSurface     *surface,
 | 
			
		||||
		    const ClutterEvent     *event)
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandPointer *pointer = grab->pointer;
 | 
			
		||||
 | 
			
		||||
@@ -384,7 +385,7 @@ meta_wayland_pointer_start_grab (MetaWaylandPointer *pointer,
 | 
			
		||||
  grab->pointer = pointer;
 | 
			
		||||
 | 
			
		||||
  if (pointer->current)
 | 
			
		||||
    interface->focus (pointer->grab, pointer->current);
 | 
			
		||||
    interface->focus (pointer->grab, pointer->current, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -394,7 +395,62 @@ meta_wayland_pointer_end_grab (MetaWaylandPointer *pointer)
 | 
			
		||||
 | 
			
		||||
  pointer->grab = &pointer->default_grab;
 | 
			
		||||
  interface = pointer->grab->interface;
 | 
			
		||||
  interface->focus (pointer->grab, pointer->current);
 | 
			
		||||
  interface->focus (pointer->grab, pointer->current, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
modal_focus (MetaWaylandPointerGrab *grab,
 | 
			
		||||
	     MetaWaylandSurface     *surface,
 | 
			
		||||
	     const ClutterEvent     *event)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
modal_motion (MetaWaylandPointerGrab *grab,
 | 
			
		||||
	      const ClutterEvent     *event)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
modal_button (MetaWaylandPointerGrab *grab,
 | 
			
		||||
	      const ClutterEvent     *event)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaWaylandPointerGrabInterface modal_grab = {
 | 
			
		||||
  modal_focus,
 | 
			
		||||
  modal_motion,
 | 
			
		||||
  modal_button
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_wayland_pointer_begin_modal (MetaWaylandPointer *pointer)
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandPointerGrab *grab;
 | 
			
		||||
 | 
			
		||||
  if (pointer->grab != &pointer->default_grab)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  meta_wayland_pointer_set_focus (pointer, NULL);
 | 
			
		||||
 | 
			
		||||
  grab = g_slice_new0 (MetaWaylandPointerGrab);
 | 
			
		||||
  grab->interface = &modal_grab;
 | 
			
		||||
  meta_wayland_pointer_start_grab (pointer, grab);
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_pointer_end_modal (MetaWaylandPointer *pointer)
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandPointerGrab *grab;
 | 
			
		||||
 | 
			
		||||
  grab = pointer->grab;
 | 
			
		||||
 | 
			
		||||
  g_assert (grab->interface == &modal_grab);
 | 
			
		||||
 | 
			
		||||
  meta_wayland_pointer_end_grab (pointer);
 | 
			
		||||
  g_slice_free (MetaWaylandPointerGrab, grab);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
@@ -414,14 +470,15 @@ typedef struct {
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
popup_grab_focus (MetaWaylandPointerGrab *grab,
 | 
			
		||||
		  MetaWaylandSurface     *surface)
 | 
			
		||||
		  MetaWaylandSurface     *surface,
 | 
			
		||||
		  const ClutterEvent     *event)
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandPopupGrab *popup_grab = (MetaWaylandPopupGrab*)grab;
 | 
			
		||||
 | 
			
		||||
  /* Popup grabs are in owner-events mode (ie, events for the same client
 | 
			
		||||
     are reported as normal) */
 | 
			
		||||
  if (surface && wl_resource_get_client (surface->resource) == popup_grab->grab_client)
 | 
			
		||||
    default_grab_focus (grab, surface);
 | 
			
		||||
    default_grab_focus (grab, surface, event);
 | 
			
		||||
  else
 | 
			
		||||
    meta_wayland_pointer_set_focus (grab->pointer, NULL);
 | 
			
		||||
}
 | 
			
		||||
@@ -476,12 +533,6 @@ meta_wayland_pointer_end_popup_grab (MetaWaylandPointer *pointer)
 | 
			
		||||
      g_slice_free (MetaWaylandPopup, popup);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  {
 | 
			
		||||
    MetaDisplay *display = meta_get_display ();
 | 
			
		||||
    meta_display_end_grab_op (display,
 | 
			
		||||
                              meta_display_get_current_time_roundtrip (display));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  meta_wayland_pointer_end_grab (pointer);
 | 
			
		||||
  g_slice_free (MetaWaylandPopupGrab, popup_grab);
 | 
			
		||||
}
 | 
			
		||||
@@ -521,8 +572,6 @@ meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
 | 
			
		||||
 | 
			
		||||
  if (pointer->grab == &pointer->default_grab)
 | 
			
		||||
    {
 | 
			
		||||
      MetaWindow *window = surface->window;
 | 
			
		||||
 | 
			
		||||
      grab = g_slice_new0 (MetaWaylandPopupGrab);
 | 
			
		||||
      grab->generic.interface = &popup_grab_interface;
 | 
			
		||||
      grab->generic.pointer = pointer;
 | 
			
		||||
@@ -530,19 +579,6 @@ meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
 | 
			
		||||
      wl_list_init (&grab->all_popups);
 | 
			
		||||
 | 
			
		||||
      meta_wayland_pointer_start_grab (pointer, (MetaWaylandPointerGrab*)grab);
 | 
			
		||||
 | 
			
		||||
      meta_display_begin_grab_op (window->display,
 | 
			
		||||
                                  window->screen,
 | 
			
		||||
                                  window,
 | 
			
		||||
                                  META_GRAB_OP_WAYLAND_CLIENT,
 | 
			
		||||
                                  FALSE, /* pointer_already_grabbed */
 | 
			
		||||
                                  FALSE, /* frame_action */
 | 
			
		||||
                                  1, /* button. XXX? */
 | 
			
		||||
                                  0, /* modmask */
 | 
			
		||||
                                  meta_display_get_current_time_roundtrip (window->display),
 | 
			
		||||
                                  wl_fixed_to_int (pointer->grab_x),
 | 
			
		||||
                                  wl_fixed_to_int (pointer->grab_y));
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    grab = (MetaWaylandPopupGrab*)pointer->grab;
 | 
			
		||||
@@ -557,6 +593,7 @@ meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
 | 
			
		||||
    wl_resource_add_destroy_listener (surface->wl_shell_surface.resource, &popup->surface_destroy_listener);
 | 
			
		||||
 | 
			
		||||
  wl_list_insert (&grab->all_popups, &popup->link);
 | 
			
		||||
      
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,8 @@
 | 
			
		||||
struct _MetaWaylandPointerGrabInterface
 | 
			
		||||
{
 | 
			
		||||
  void (*focus) (MetaWaylandPointerGrab *grab,
 | 
			
		||||
                 MetaWaylandSurface     *surface);
 | 
			
		||||
                 MetaWaylandSurface     *surface,
 | 
			
		||||
		 const ClutterEvent     *event);
 | 
			
		||||
  void (*motion) (MetaWaylandPointerGrab *grab,
 | 
			
		||||
		  const ClutterEvent     *event);
 | 
			
		||||
  void (*button) (MetaWaylandPointerGrab *grab,
 | 
			
		||||
@@ -84,6 +85,11 @@ meta_wayland_pointer_start_grab (MetaWaylandPointer *pointer,
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_pointer_end_grab (MetaWaylandPointer *pointer);
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_wayland_pointer_begin_modal (MetaWaylandPointer *pointer);
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_pointer_end_modal   (MetaWaylandPointer *pointer);
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
 | 
			
		||||
				       MetaWaylandSurface *popup);
 | 
			
		||||
 
 | 
			
		||||
@@ -276,53 +276,42 @@ static void
 | 
			
		||||
handle_scroll_event (MetaWaylandSeat    *seat,
 | 
			
		||||
                     const ClutterEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  wl_fixed_t x_value = 0, y_value = 0;
 | 
			
		||||
  enum wl_pointer_axis axis;
 | 
			
		||||
  wl_fixed_t value;
 | 
			
		||||
 | 
			
		||||
  notify_motion (seat, event);
 | 
			
		||||
 | 
			
		||||
  if (!seat->pointer.focus_resource)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  if (clutter_event_is_pointer_emulated (event))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  switch (clutter_event_get_scroll_direction (event))
 | 
			
		||||
    {
 | 
			
		||||
    case CLUTTER_SCROLL_UP:
 | 
			
		||||
      y_value = -DEFAULT_AXIS_STEP_DISTANCE;
 | 
			
		||||
      axis = WL_POINTER_AXIS_VERTICAL_SCROLL;
 | 
			
		||||
      value = -DEFAULT_AXIS_STEP_DISTANCE;
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case CLUTTER_SCROLL_DOWN:
 | 
			
		||||
      y_value = DEFAULT_AXIS_STEP_DISTANCE;
 | 
			
		||||
      axis = WL_POINTER_AXIS_VERTICAL_SCROLL;
 | 
			
		||||
      value = DEFAULT_AXIS_STEP_DISTANCE;
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case CLUTTER_SCROLL_LEFT:
 | 
			
		||||
      x_value = -DEFAULT_AXIS_STEP_DISTANCE;
 | 
			
		||||
      axis = WL_POINTER_AXIS_HORIZONTAL_SCROLL;
 | 
			
		||||
      value = -DEFAULT_AXIS_STEP_DISTANCE;
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case CLUTTER_SCROLL_RIGHT:
 | 
			
		||||
      x_value = DEFAULT_AXIS_STEP_DISTANCE;
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case CLUTTER_SCROLL_SMOOTH:
 | 
			
		||||
      {
 | 
			
		||||
        double dx, dy;
 | 
			
		||||
        clutter_event_get_scroll_delta (event, &dx, &dy);
 | 
			
		||||
        x_value = wl_fixed_from_double (dx);
 | 
			
		||||
        y_value = wl_fixed_from_double (dy);
 | 
			
		||||
      }
 | 
			
		||||
      axis = WL_POINTER_AXIS_HORIZONTAL_SCROLL;
 | 
			
		||||
      value = DEFAULT_AXIS_STEP_DISTANCE;
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (x_value)
 | 
			
		||||
    wl_pointer_send_axis (seat->pointer.focus_resource, clutter_event_get_time (event),
 | 
			
		||||
                          WL_POINTER_AXIS_HORIZONTAL_SCROLL, x_value);
 | 
			
		||||
  if (y_value)
 | 
			
		||||
    wl_pointer_send_axis (seat->pointer.focus_resource, clutter_event_get_time (event),
 | 
			
		||||
                          WL_POINTER_AXIS_VERTICAL_SCROLL, y_value);
 | 
			
		||||
  if (seat->pointer.focus_resource)
 | 
			
		||||
    wl_pointer_send_axis (seat->pointer.focus_resource,
 | 
			
		||||
                          clutter_event_get_time (event),
 | 
			
		||||
                          axis,
 | 
			
		||||
                          value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
@@ -347,7 +336,7 @@ count_buttons (const ClutterEvent *event)
 | 
			
		||||
  return count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_seat_update_pointer (MetaWaylandSeat    *seat,
 | 
			
		||||
                                  const ClutterEvent *event)
 | 
			
		||||
{
 | 
			
		||||
@@ -370,27 +359,6 @@ meta_wayland_seat_update_pointer (MetaWaylandSeat    *seat,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_seat_update (MetaWaylandSeat    *seat,
 | 
			
		||||
                          const ClutterEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  switch (event->type)
 | 
			
		||||
    {
 | 
			
		||||
    case CLUTTER_MOTION:
 | 
			
		||||
    case CLUTTER_BUTTON_PRESS:
 | 
			
		||||
    case CLUTTER_BUTTON_RELEASE:
 | 
			
		||||
    case CLUTTER_SCROLL:
 | 
			
		||||
      meta_wayland_seat_update_pointer (seat, event);
 | 
			
		||||
      break;
 | 
			
		||||
    case CLUTTER_KEY_PRESS:
 | 
			
		||||
    case CLUTTER_KEY_RELEASE:
 | 
			
		||||
      meta_wayland_keyboard_update (&seat->keyboard, (const ClutterKeyEvent *) event);
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
 | 
			
		||||
                                const ClutterEvent *event)
 | 
			
		||||
@@ -461,7 +429,8 @@ meta_wayland_seat_repick (MetaWaylandSeat    *seat,
 | 
			
		||||
    {
 | 
			
		||||
      const MetaWaylandPointerGrabInterface *interface =
 | 
			
		||||
        pointer->grab->interface;
 | 
			
		||||
      interface->focus (pointer->grab, surface);
 | 
			
		||||
      interface->focus (pointer->grab,
 | 
			
		||||
                        surface, for_event);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -43,6 +43,12 @@ struct _MetaWaylandDataSource
 | 
			
		||||
{
 | 
			
		||||
  struct wl_resource *resource;
 | 
			
		||||
  struct wl_array mime_types;
 | 
			
		||||
 | 
			
		||||
  void (*accept) (MetaWaylandDataSource * source,
 | 
			
		||||
                  uint32_t serial, const char *mime_type);
 | 
			
		||||
  void (*send) (MetaWaylandDataSource * source,
 | 
			
		||||
                const char *mime_type, int32_t fd);
 | 
			
		||||
  void (*cancel) (MetaWaylandDataSource * source);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaWaylandSeat
 | 
			
		||||
@@ -71,8 +77,8 @@ MetaWaylandSeat *
 | 
			
		||||
meta_wayland_seat_new (struct wl_display *display);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_seat_update (MetaWaylandSeat    *seat,
 | 
			
		||||
                          const ClutterEvent *event);
 | 
			
		||||
meta_wayland_seat_update_pointer (MetaWaylandSeat *seat,
 | 
			
		||||
                                  const ClutterEvent *event);
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
 | 
			
		||||
 
 | 
			
		||||
@@ -336,6 +336,22 @@ toplevel_surface_commit (MetaWaylandSurface             *surface,
 | 
			
		||||
 | 
			
		||||
  if (pending->frame_extents_changed)
 | 
			
		||||
    meta_window_set_custom_frame_extents (surface->window, &pending->frame_extents);
 | 
			
		||||
 | 
			
		||||
  if (pending->maximized.changed)
 | 
			
		||||
    {
 | 
			
		||||
      if (pending->maximized.value)
 | 
			
		||||
        meta_window_maximize (surface->window, META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
 | 
			
		||||
      else
 | 
			
		||||
        meta_window_unmaximize (surface->window, META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (pending->fullscreen.changed)
 | 
			
		||||
    {
 | 
			
		||||
      if (pending->fullscreen.value)
 | 
			
		||||
        meta_window_make_fullscreen (surface->window);
 | 
			
		||||
      else
 | 
			
		||||
        meta_window_unmake_fullscreen (surface->window);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -361,6 +377,8 @@ double_buffered_state_init (MetaWaylandDoubleBufferedState *state)
 | 
			
		||||
  wl_list_init (&state->frame_callback_list);
 | 
			
		||||
 | 
			
		||||
  state->frame_extents_changed = FALSE;
 | 
			
		||||
  state->maximized.changed = FALSE;
 | 
			
		||||
  state->fullscreen.changed = FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -843,44 +861,44 @@ xdg_surface_set_output (struct wl_client *client,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
xdg_surface_request_change_state (struct wl_client *client,
 | 
			
		||||
                                  struct wl_resource *resource,
 | 
			
		||||
                                  uint32_t state_type,
 | 
			
		||||
                                  uint32_t value,
 | 
			
		||||
                                  uint32_t serial)
 | 
			
		||||
xdg_surface_set_fullscreen (struct wl_client *client,
 | 
			
		||||
                            struct wl_resource *resource)
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
 | 
			
		||||
 | 
			
		||||
  surface->state_changed_serial = serial;
 | 
			
		||||
 | 
			
		||||
  switch (state_type)
 | 
			
		||||
    {
 | 
			
		||||
    case XDG_SURFACE_STATE_MAXIMIZED:
 | 
			
		||||
      if (value)
 | 
			
		||||
        meta_window_maximize (surface->window, META_MAXIMIZE_BOTH);
 | 
			
		||||
      else
 | 
			
		||||
        meta_window_unmaximize (surface->window, META_MAXIMIZE_BOTH);
 | 
			
		||||
      break;
 | 
			
		||||
    case XDG_SURFACE_STATE_FULLSCREEN:
 | 
			
		||||
      if (value)
 | 
			
		||||
        meta_window_make_fullscreen (surface->window);
 | 
			
		||||
      else
 | 
			
		||||
        meta_window_unmake_fullscreen (surface->window);
 | 
			
		||||
    }
 | 
			
		||||
  surface->pending.fullscreen.changed = TRUE;
 | 
			
		||||
  surface->pending.fullscreen.value = TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
xdg_surface_ack_change_state (struct wl_client *client,
 | 
			
		||||
                              struct wl_resource *resource,
 | 
			
		||||
                              uint32_t state_type,
 | 
			
		||||
                              uint32_t value,
 | 
			
		||||
                              uint32_t serial)
 | 
			
		||||
xdg_surface_unset_fullscreen (struct wl_client *client,
 | 
			
		||||
                              struct wl_resource *resource)
 | 
			
		||||
{
 | 
			
		||||
  /* Do nothing for now. In the future, we'd imagine that
 | 
			
		||||
   * we'd ignore attaches when we have a state pending that
 | 
			
		||||
   * we haven't had the client ACK'd, to prevent a race
 | 
			
		||||
   * condition when we have an in-flight attach when the
 | 
			
		||||
   * client gets the new state. */
 | 
			
		||||
  MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
 | 
			
		||||
  MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
 | 
			
		||||
 | 
			
		||||
  surface->pending.fullscreen.changed = TRUE;
 | 
			
		||||
  surface->pending.fullscreen.value = FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
xdg_surface_set_maximized (struct wl_client *client,
 | 
			
		||||
                           struct wl_resource *resource)
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
 | 
			
		||||
 | 
			
		||||
  surface->pending.maximized.changed = TRUE;
 | 
			
		||||
  surface->pending.maximized.value = TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
xdg_surface_unset_maximized (struct wl_client *client,
 | 
			
		||||
                             struct wl_resource *resource)
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
 | 
			
		||||
 | 
			
		||||
  surface->pending.maximized.changed = TRUE;
 | 
			
		||||
  surface->pending.maximized.value = FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -901,8 +919,10 @@ static const struct xdg_surface_interface meta_wayland_xdg_surface_interface = {
 | 
			
		||||
  xdg_surface_move,
 | 
			
		||||
  xdg_surface_resize,
 | 
			
		||||
  xdg_surface_set_output,
 | 
			
		||||
  xdg_surface_request_change_state,
 | 
			
		||||
  xdg_surface_ack_change_state,
 | 
			
		||||
  xdg_surface_set_fullscreen,
 | 
			
		||||
  xdg_surface_unset_fullscreen,
 | 
			
		||||
  xdg_surface_set_maximized,
 | 
			
		||||
  xdg_surface_unset_maximized,
 | 
			
		||||
  xdg_surface_set_minimized,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -991,7 +1011,8 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
 | 
			
		||||
  surface->window->placed = TRUE;
 | 
			
		||||
  meta_window_set_transient_for (surface->window, parent_surf->window);
 | 
			
		||||
 | 
			
		||||
  meta_window_set_type (surface->window, META_WINDOW_DROPDOWN_MENU);
 | 
			
		||||
  surface->window->type = META_WINDOW_DROPDOWN_MENU;
 | 
			
		||||
  meta_window_type_changed (surface->window);
 | 
			
		||||
 | 
			
		||||
  meta_wayland_pointer_start_popup_grab (&seat->pointer, surface);
 | 
			
		||||
}
 | 
			
		||||
@@ -1153,9 +1174,9 @@ wl_shell_surface_set_state (MetaWaylandSurface *surface,
 | 
			
		||||
    meta_window_unmake_fullscreen (surface->window);
 | 
			
		||||
 | 
			
		||||
  if (state == SURFACE_STATE_MAXIMIZED)
 | 
			
		||||
    meta_window_maximize (surface->window, META_MAXIMIZE_BOTH);
 | 
			
		||||
    meta_window_maximize (surface->window, META_MAXIMIZE_VERTICAL | META_MAXIMIZE_HORIZONTAL);
 | 
			
		||||
  else
 | 
			
		||||
    meta_window_unmaximize (surface->window, META_MAXIMIZE_BOTH);
 | 
			
		||||
    meta_window_unmaximize (surface->window, META_MAXIMIZE_VERTICAL | META_MAXIMIZE_HORIZONTAL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -1444,6 +1465,8 @@ subsurface_parent_surface_committed (MetaWaylandSurface *surface)
 | 
			
		||||
 | 
			
		||||
  if (surface->sub.synchronous)
 | 
			
		||||
    commit_double_buffered_state (surface, pending_surface_state);
 | 
			
		||||
 | 
			
		||||
  double_buffered_state_reset (pending_surface_state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -1715,55 +1738,6 @@ meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
 | 
			
		||||
                                     0, new_width, new_height);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
send_change_state (MetaWaylandSurface *surface,
 | 
			
		||||
                   uint32_t state_type,
 | 
			
		||||
                   uint32_t value)
 | 
			
		||||
{
 | 
			
		||||
  if (surface->xdg_surface.resource)
 | 
			
		||||
    {
 | 
			
		||||
      uint32_t serial;
 | 
			
		||||
 | 
			
		||||
      if (surface->state_changed_serial != 0)
 | 
			
		||||
        {
 | 
			
		||||
          serial = surface->state_changed_serial;
 | 
			
		||||
          surface->state_changed_serial = 0;
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          struct wl_client *client = wl_resource_get_client (surface->xdg_surface.resource);
 | 
			
		||||
          struct wl_display *display = wl_client_get_display (client);
 | 
			
		||||
          serial = wl_display_next_serial (display);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      xdg_surface_send_change_state (surface->xdg_surface.resource, state_type, value, serial);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_surface_send_maximized (MetaWaylandSurface *surface)
 | 
			
		||||
{
 | 
			
		||||
  send_change_state (surface, XDG_SURFACE_STATE_MAXIMIZED, TRUE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_surface_send_unmaximized (MetaWaylandSurface *surface)
 | 
			
		||||
{
 | 
			
		||||
  send_change_state (surface, XDG_SURFACE_STATE_MAXIMIZED, FALSE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_surface_send_fullscreened (MetaWaylandSurface *surface)
 | 
			
		||||
{
 | 
			
		||||
  send_change_state (surface, XDG_SURFACE_STATE_FULLSCREEN, TRUE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_surface_send_unfullscreened (MetaWaylandSurface *surface)
 | 
			
		||||
{
 | 
			
		||||
  send_change_state (surface, XDG_SURFACE_STATE_FULLSCREEN, FALSE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_surface_activated (MetaWaylandSurface *surface)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -41,6 +41,12 @@ struct _MetaWaylandBuffer
 | 
			
		||||
  uint32_t ref_count;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
  guint changed : 1;
 | 
			
		||||
  guint value : 1;
 | 
			
		||||
} MetaWaylandStateFlag;
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
  /* wl_surface.attach */
 | 
			
		||||
@@ -61,6 +67,9 @@ typedef struct
 | 
			
		||||
 | 
			
		||||
  gboolean frame_extents_changed;
 | 
			
		||||
  GtkBorder frame_extents;
 | 
			
		||||
 | 
			
		||||
  MetaWaylandStateFlag fullscreen;
 | 
			
		||||
  MetaWaylandStateFlag maximized;
 | 
			
		||||
} MetaWaylandDoubleBufferedState;
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
@@ -98,8 +107,6 @@ struct _MetaWaylandSurface
 | 
			
		||||
    GSList *pending_placement_ops;
 | 
			
		||||
  } sub;
 | 
			
		||||
 | 
			
		||||
  uint32_t state_changed_serial;
 | 
			
		||||
 | 
			
		||||
  /* All the pending state, that wl_surface.commit will apply. */
 | 
			
		||||
  MetaWaylandDoubleBufferedState pending;
 | 
			
		||||
};
 | 
			
		||||
@@ -117,10 +124,6 @@ void                meta_wayland_surface_window_unmanaged (MetaWaylandSurface *s
 | 
			
		||||
void                meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
 | 
			
		||||
							   int                 width,
 | 
			
		||||
							   int                 height);
 | 
			
		||||
void                meta_wayland_surface_send_maximized (MetaWaylandSurface *surface);
 | 
			
		||||
void                meta_wayland_surface_send_unmaximized (MetaWaylandSurface *surface);
 | 
			
		||||
void                meta_wayland_surface_send_fullscreened (MetaWaylandSurface *surface);
 | 
			
		||||
void                meta_wayland_surface_send_unfullscreened (MetaWaylandSurface *surface);
 | 
			
		||||
 | 
			
		||||
void                meta_wayland_surface_activated (MetaWaylandSurface *surface);
 | 
			
		||||
void                meta_wayland_surface_deactivated (MetaWaylandSurface *surface);
 | 
			
		||||
 
 | 
			
		||||
@@ -508,15 +508,6 @@ stage_destroy_cb (void)
 | 
			
		||||
  meta_quit (META_EXIT_SUCCESS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_wayland_compositor_update:
 | 
			
		||||
 * @compositor: the #MetaWaylandCompositor instance
 | 
			
		||||
 * @event: the #ClutterEvent used to update @seat's state
 | 
			
		||||
 *
 | 
			
		||||
 * This is used to update display server state like updating cursor
 | 
			
		||||
 * position and keeping track of buttons and keys pressed. It must be
 | 
			
		||||
 * called for all input events coming from the underlying devices.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_compositor_update (MetaWaylandCompositor *compositor,
 | 
			
		||||
                                const ClutterEvent    *event)
 | 
			
		||||
@@ -545,18 +536,18 @@ meta_wayland_compositor_update (MetaWaylandCompositor *compositor,
 | 
			
		||||
      meta_idle_monitor_reset_idletime (device_monitor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_wayland_seat_update (compositor->seat, event);
 | 
			
		||||
  switch (event->type)
 | 
			
		||||
    {
 | 
			
		||||
    case CLUTTER_MOTION:
 | 
			
		||||
    case CLUTTER_BUTTON_PRESS:
 | 
			
		||||
    case CLUTTER_BUTTON_RELEASE:
 | 
			
		||||
    case CLUTTER_SCROLL:
 | 
			
		||||
      meta_wayland_seat_update_pointer (compositor->seat, event);
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_wayland_compositor_handle_event:
 | 
			
		||||
 * @compositor: the #MetaWaylandCompositor instance
 | 
			
		||||
 * @event: the #ClutterEvent to be sent
 | 
			
		||||
 *
 | 
			
		||||
 * This method sends events to the focused wayland client, if any.
 | 
			
		||||
 *
 | 
			
		||||
 * Return value: whether @event was sent to a wayland client.
 | 
			
		||||
 */
 | 
			
		||||
gboolean
 | 
			
		||||
meta_wayland_compositor_handle_event (MetaWaylandCompositor *compositor,
 | 
			
		||||
                                      const ClutterEvent    *event)
 | 
			
		||||
@@ -652,8 +643,6 @@ meta_wayland_init (void)
 | 
			
		||||
 | 
			
		||||
  clutter_wayland_set_compositor_display (compositor->wayland_display);
 | 
			
		||||
 | 
			
		||||
  /* If we're running on bare metal, we're a display server,
 | 
			
		||||
   * so start talking to weston-launch. */
 | 
			
		||||
#if defined(CLUTTER_WINDOWING_EGL)
 | 
			
		||||
  if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
 | 
			
		||||
    compositor->launcher = meta_launcher_new ();
 | 
			
		||||
@@ -662,6 +651,17 @@ meta_wayland_init (void)
 | 
			
		||||
  if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
 | 
			
		||||
    g_error ("Failed to initialize Clutter");
 | 
			
		||||
 | 
			
		||||
#if defined(CLUTTER_WINDOWING_EGL)
 | 
			
		||||
  if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
 | 
			
		||||
    {
 | 
			
		||||
      ClutterBackend *backend = clutter_get_default_backend ();
 | 
			
		||||
      CoglContext *cogl_context = clutter_backend_get_cogl_context (backend);
 | 
			
		||||
      CoglRenderer *cogl_renderer = cogl_display_get_renderer (cogl_context_get_display (cogl_context));
 | 
			
		||||
      int drm_fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
 | 
			
		||||
      meta_launcher_set_drm_fd (compositor->launcher, drm_fd, NULL);
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  meta_monitor_manager_initialize ();
 | 
			
		||||
  monitors = meta_monitor_manager_get ();
 | 
			
		||||
  g_signal_connect (monitors, "monitors-changed",
 | 
			
		||||
@@ -728,22 +728,7 @@ meta_wayland_compositor_activate_vt (MetaWaylandCompositor  *compositor,
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      g_debug ("Ignoring VT switch keybinding, not running as display server");
 | 
			
		||||
      return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_wayland_compositor_activate_session (MetaWaylandCompositor  *compositor,
 | 
			
		||||
                                          GError                **error)
 | 
			
		||||
{
 | 
			
		||||
  if (compositor->launcher)
 | 
			
		||||
    {
 | 
			
		||||
      return meta_launcher_activate_vt (compositor->launcher, -1, error);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      g_debug ("Ignoring activate_session, not running as display server");
 | 
			
		||||
      g_debug ("Ignoring VT switch keybinding, not running as VT manager");
 | 
			
		||||
      return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -46,8 +46,6 @@ void                    meta_wayland_compositor_paint_finished  (MetaWaylandComp
 | 
			
		||||
gboolean                meta_wayland_compositor_activate_vt     (MetaWaylandCompositor  *compositor,
 | 
			
		||||
                                                                 int                     vt,
 | 
			
		||||
                                                                 GError                **error);
 | 
			
		||||
gboolean                meta_wayland_compositor_activate_session (MetaWaylandCompositor  *compositor,
 | 
			
		||||
                                                                  GError                **error);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,6 @@
 | 
			
		||||
#include <gio/gunixfdmessage.h>
 | 
			
		||||
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
#include <clutter/egl/clutter-egl.h>
 | 
			
		||||
#include <clutter/evdev/clutter-evdev.h>
 | 
			
		||||
 | 
			
		||||
#include <glib.h>
 | 
			
		||||
@@ -42,8 +41,6 @@
 | 
			
		||||
#include <xf86drm.h>
 | 
			
		||||
#include <xf86drmMode.h>
 | 
			
		||||
 | 
			
		||||
#include "meta-wayland-private.h"
 | 
			
		||||
#include "meta-cursor-tracker-private.h"
 | 
			
		||||
#include "meta-weston-launch.h"
 | 
			
		||||
 | 
			
		||||
struct _MetaLauncher
 | 
			
		||||
@@ -157,11 +154,36 @@ send_message_to_wl (MetaLauncher           *self,
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
meta_launcher_open_device (MetaLauncher  *self,
 | 
			
		||||
                           const char    *name,
 | 
			
		||||
                           int            flags,
 | 
			
		||||
                           GError       **error)
 | 
			
		||||
gboolean
 | 
			
		||||
meta_launcher_set_drm_fd (MetaLauncher  *self,
 | 
			
		||||
			  int            drm_fd,
 | 
			
		||||
			  GError       **error)
 | 
			
		||||
{
 | 
			
		||||
  struct weston_launcher_message message;
 | 
			
		||||
  GSocketControlMessage *cmsg;
 | 
			
		||||
  gboolean ok;
 | 
			
		||||
 | 
			
		||||
  message.opcode = WESTON_LAUNCHER_DRM_SET_FD;
 | 
			
		||||
 | 
			
		||||
  cmsg = g_unix_fd_message_new ();
 | 
			
		||||
  if (g_unix_fd_message_append_fd (G_UNIX_FD_MESSAGE (cmsg),
 | 
			
		||||
				   drm_fd, error) == FALSE)
 | 
			
		||||
    {
 | 
			
		||||
      g_object_unref (cmsg);
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  ok = send_message_to_wl (self, &message, sizeof message, cmsg, NULL, error);
 | 
			
		||||
 | 
			
		||||
  g_object_unref (cmsg);
 | 
			
		||||
  return ok;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
meta_launcher_open_input_device (MetaLauncher  *self,
 | 
			
		||||
				 const char    *name,
 | 
			
		||||
				 int            flags,
 | 
			
		||||
				 GError       **error)
 | 
			
		||||
{
 | 
			
		||||
  struct weston_launcher_open *message;
 | 
			
		||||
  GSocketControlMessage *cmsg;
 | 
			
		||||
@@ -210,17 +232,6 @@ meta_launcher_enter (MetaLauncher *launcher)
 | 
			
		||||
  cogl_kms_display_queue_modes_reset (cogl_display);
 | 
			
		||||
 | 
			
		||||
  clutter_evdev_reclaim_devices ();
 | 
			
		||||
 | 
			
		||||
  {
 | 
			
		||||
    MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
 | 
			
		||||
 | 
			
		||||
    /* When we mode-switch back, we need to immediately queue a redraw
 | 
			
		||||
     * in case nothing else queued one for us, and force the cursor to
 | 
			
		||||
     * update. */
 | 
			
		||||
 | 
			
		||||
    clutter_actor_queue_redraw (compositor->stage);
 | 
			
		||||
    meta_cursor_tracker_force_update (compositor->seat->cursor_tracker);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -237,14 +248,7 @@ on_evdev_device_open (const char  *path,
 | 
			
		||||
{
 | 
			
		||||
  MetaLauncher *launcher = user_data;
 | 
			
		||||
 | 
			
		||||
  return meta_launcher_open_device (launcher, path, flags, error);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_evdev_device_close (int          fd,
 | 
			
		||||
                       gpointer     user_data)
 | 
			
		||||
{
 | 
			
		||||
  close (fd);
 | 
			
		||||
  return meta_launcher_open_input_device (launcher, path, flags, error);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -350,6 +354,8 @@ meta_launcher_new (void)
 | 
			
		||||
 | 
			
		||||
  self->weston_launch = g_socket_new_from_fd (launch_fd, NULL);
 | 
			
		||||
 | 
			
		||||
  clutter_evdev_set_open_callback (on_evdev_device_open, self);
 | 
			
		||||
 | 
			
		||||
  self->nested_context = g_main_context_new ();
 | 
			
		||||
  self->nested_loop = g_main_loop_new (self->nested_context, FALSE);
 | 
			
		||||
 | 
			
		||||
@@ -363,22 +369,6 @@ meta_launcher_new (void)
 | 
			
		||||
  g_source_attach (self->inner_source, self->nested_context);
 | 
			
		||||
  g_source_unref (self->inner_source);
 | 
			
		||||
 | 
			
		||||
  clutter_evdev_set_device_callbacks (on_evdev_device_open,
 | 
			
		||||
                                      on_evdev_device_close,
 | 
			
		||||
                                      self);
 | 
			
		||||
 | 
			
		||||
#if defined(CLUTTER_WINDOWING_EGL)
 | 
			
		||||
  if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
 | 
			
		||||
    {
 | 
			
		||||
      GError *error = NULL;
 | 
			
		||||
      int fd = meta_launcher_open_device (self, "/dev/dri/card0", O_RDWR, &error);
 | 
			
		||||
      if (error)
 | 
			
		||||
        g_error ("Failed to open /dev/dri/card0: %s", error->message);
 | 
			
		||||
 | 
			
		||||
      clutter_egl_set_kms_fd (fd);
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -398,7 +388,7 @@ meta_launcher_free (MetaLauncher *launcher)
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_launcher_activate_vt (MetaLauncher  *launcher,
 | 
			
		||||
			   signed char    vt,
 | 
			
		||||
			   int            vt,
 | 
			
		||||
			   GError       **error)
 | 
			
		||||
{
 | 
			
		||||
  struct weston_launcher_activate_vt message;
 | 
			
		||||
 
 | 
			
		||||
@@ -29,6 +29,18 @@ MetaLauncher     *meta_launcher_new                     (void);
 | 
			
		||||
void              meta_launcher_free                    (MetaLauncher  *self);
 | 
			
		||||
 | 
			
		||||
gboolean          meta_launcher_activate_vt             (MetaLauncher  *self,
 | 
			
		||||
							 signed char    vt,
 | 
			
		||||
							 int            number,
 | 
			
		||||
							 GError       **error);
 | 
			
		||||
 | 
			
		||||
gboolean          meta_launcher_set_drm_fd              (MetaLauncher  *self,
 | 
			
		||||
							 int            drm_fd,
 | 
			
		||||
							 GError       **error);
 | 
			
		||||
gboolean          meta_launcher_set_master              (MetaLauncher  *self,
 | 
			
		||||
							 gboolean       master,
 | 
			
		||||
							 GError       **error);
 | 
			
		||||
int               meta_launcher_open_input_device       (MetaLauncher  *self,
 | 
			
		||||
							 const char    *name,
 | 
			
		||||
							 int            flags,
 | 
			
		||||
							 GError       **error);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -47,13 +47,6 @@ xserver_set_window_id (struct wl_client *client,
 | 
			
		||||
  if (!window)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  /* If the window has an existing surface, like if we're
 | 
			
		||||
   * undecorating or decorating the window, then we need
 | 
			
		||||
   * to detach the window from its old surface.
 | 
			
		||||
   */
 | 
			
		||||
  if (window->surface)
 | 
			
		||||
    window->surface->window = NULL;
 | 
			
		||||
 | 
			
		||||
  meta_wayland_surface_make_toplevel (surface);
 | 
			
		||||
 | 
			
		||||
  surface->window = window;
 | 
			
		||||
 
 | 
			
		||||
@@ -80,7 +80,6 @@ struct weston_launch {
 | 
			
		||||
	struct termios terminal_attributes;
 | 
			
		||||
	int kb_mode;
 | 
			
		||||
	enum vt_state vt_state;
 | 
			
		||||
	unsigned vt;
 | 
			
		||||
 | 
			
		||||
        int drm_fd;
 | 
			
		||||
};
 | 
			
		||||
@@ -165,6 +164,69 @@ setenv_fd(const char *env, int fd)
 | 
			
		||||
	setenv(env, buf, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
handle_setdrmfd(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
 | 
			
		||||
{
 | 
			
		||||
        struct weston_launcher_reply reply;
 | 
			
		||||
	struct cmsghdr *cmsg;
 | 
			
		||||
	union cmsg_data *data;
 | 
			
		||||
	struct stat s;
 | 
			
		||||
 | 
			
		||||
	reply.header.opcode = WESTON_LAUNCHER_DRM_SET_FD;
 | 
			
		||||
	reply.ret = -1;
 | 
			
		||||
 | 
			
		||||
	if (wl->drm_fd != -1) {
 | 
			
		||||
		error(0, 0, "DRM FD already set");
 | 
			
		||||
		reply.ret = -EINVAL;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cmsg = CMSG_FIRSTHDR(msg);
 | 
			
		||||
	if (!cmsg ||
 | 
			
		||||
	    cmsg->cmsg_level != SOL_SOCKET ||
 | 
			
		||||
	    cmsg->cmsg_type != SCM_RIGHTS) {
 | 
			
		||||
		error(0, 0, "invalid control message");
 | 
			
		||||
		reply.ret = -EINVAL;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	data = (union cmsg_data *) CMSG_DATA(cmsg);
 | 
			
		||||
	if (data->fd < 0) {
 | 
			
		||||
		error(0, 0, "missing drm fd in socket request");
 | 
			
		||||
		reply.ret = -EINVAL;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (fstat(data->fd, &s) < 0) {
 | 
			
		||||
		reply.ret = -errno;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (major(s.st_rdev) != DRM_MAJOR) {
 | 
			
		||||
		fprintf(stderr, "FD is not for DRM\n");
 | 
			
		||||
		reply.ret = -EPERM;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	wl->drm_fd = data->fd;
 | 
			
		||||
	reply.ret = drmSetMaster(data->fd);
 | 
			
		||||
	if (reply.ret < 0)
 | 
			
		||||
		reply.ret = -errno;
 | 
			
		||||
 | 
			
		||||
	if (wl->verbose)
 | 
			
		||||
		fprintf(stderr, "mutter-launch: set drm FD, ret: %d, fd: %d\n",
 | 
			
		||||
			reply.ret, data->fd);
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	do {
 | 
			
		||||
		len = send(wl->sock[0], &reply, sizeof reply, 0);
 | 
			
		||||
	} while (len < 0 && errno == EINTR);
 | 
			
		||||
	if (len < 0)
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
handle_confirm_vt_switch(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
 | 
			
		||||
{
 | 
			
		||||
@@ -212,7 +274,6 @@ handle_activate_vt(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
 | 
			
		||||
{
 | 
			
		||||
        struct weston_launcher_reply reply;
 | 
			
		||||
	struct weston_launcher_activate_vt *message;
 | 
			
		||||
	unsigned vt;
 | 
			
		||||
 | 
			
		||||
	reply.header.opcode = WESTON_LAUNCHER_ACTIVATE_VT;
 | 
			
		||||
	reply.ret = -1;
 | 
			
		||||
@@ -224,13 +285,7 @@ handle_activate_vt(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
 | 
			
		||||
 | 
			
		||||
	message = msg->msg_iov->iov_base;
 | 
			
		||||
 | 
			
		||||
	/* Negative values mean that we're activating our own VT */
 | 
			
		||||
	if (message->vt > 0)
 | 
			
		||||
		vt = message->vt;
 | 
			
		||||
	else
 | 
			
		||||
		vt = wl->vt;
 | 
			
		||||
 | 
			
		||||
	reply.ret = ioctl(wl->tty, VT_ACTIVATE, vt);
 | 
			
		||||
	reply.ret = ioctl(wl->tty, VT_ACTIVATE, message->vt);
 | 
			
		||||
	if (reply.ret < 0)
 | 
			
		||||
		reply.ret = -errno;
 | 
			
		||||
 | 
			
		||||
@@ -260,7 +315,6 @@ handle_open(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
 | 
			
		||||
	struct iovec iov;
 | 
			
		||||
	struct weston_launcher_open *message;
 | 
			
		||||
	union cmsg_data *data;
 | 
			
		||||
	int dev_major;
 | 
			
		||||
 | 
			
		||||
	reply.header.opcode = WESTON_LAUNCHER_OPEN;
 | 
			
		||||
	reply.ret = -1;
 | 
			
		||||
@@ -277,22 +331,6 @@ handle_open(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
 | 
			
		||||
		goto err0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dev_major = major(s.st_rdev);
 | 
			
		||||
 | 
			
		||||
	if (dev_major != INPUT_MAJOR &&
 | 
			
		||||
	    dev_major != DRM_MAJOR) {
 | 
			
		||||
		fprintf(stderr, "Device %s is not an input or DRM device\n",
 | 
			
		||||
			message->path);
 | 
			
		||||
		reply.ret = -EPERM;
 | 
			
		||||
		goto err0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (dev_major == DRM_MAJOR && wl->drm_fd != -1) {
 | 
			
		||||
		fprintf(stderr, "Already have a DRM device open\n");
 | 
			
		||||
		reply.ret = -EPERM;
 | 
			
		||||
		goto err0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fd = open(message->path, message->flags);
 | 
			
		||||
	if (fd < 0) {
 | 
			
		||||
		fprintf(stderr, "Error opening device %s: %m\n",
 | 
			
		||||
@@ -301,8 +339,13 @@ handle_open(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
 | 
			
		||||
		goto err0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (dev_major == DRM_MAJOR) {
 | 
			
		||||
		wl->drm_fd = fd;
 | 
			
		||||
	if (major(s.st_rdev) != INPUT_MAJOR) {
 | 
			
		||||
		close(fd);
 | 
			
		||||
		fd = -1;
 | 
			
		||||
		fprintf(stderr, "Device %s is not an input device\n",
 | 
			
		||||
			message->path);
 | 
			
		||||
		reply.ret = -EPERM;
 | 
			
		||||
		goto err0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
err0:
 | 
			
		||||
@@ -370,6 +413,9 @@ handle_socket_msg(struct weston_launch *wl)
 | 
			
		||||
	case WESTON_LAUNCHER_OPEN:
 | 
			
		||||
		ret = handle_open(wl, &msg, len);
 | 
			
		||||
		break;
 | 
			
		||||
	case WESTON_LAUNCHER_DRM_SET_FD:
 | 
			
		||||
		ret = handle_setdrmfd(wl, &msg, len);
 | 
			
		||||
		break;
 | 
			
		||||
	case WESTON_LAUNCHER_CONFIRM_VT_SWITCH:
 | 
			
		||||
		ret = handle_confirm_vt_switch(wl, &msg, len);
 | 
			
		||||
		break;
 | 
			
		||||
@@ -508,7 +554,7 @@ setup_tty(struct weston_launch *wl)
 | 
			
		||||
	struct stat buf;
 | 
			
		||||
	struct termios raw_attributes;
 | 
			
		||||
	struct vt_mode mode = { 0 };
 | 
			
		||||
	char *session;
 | 
			
		||||
	char *session, *tty;
 | 
			
		||||
	char path[PATH_MAX];
 | 
			
		||||
	int ok;
 | 
			
		||||
 | 
			
		||||
@@ -516,12 +562,43 @@ setup_tty(struct weston_launch *wl)
 | 
			
		||||
	if (ok < 0)
 | 
			
		||||
	  error(1, -ok, "could not determine current session");
 | 
			
		||||
 | 
			
		||||
	ok = sd_session_get_vt(session, &wl->vt);
 | 
			
		||||
	if (ok < 0)
 | 
			
		||||
		error(1, -ok, "could not determine current TTY");
 | 
			
		||||
	ok = sd_session_get_tty(session, &tty);
 | 
			
		||||
	if (ok == 0) {
 | 
			
		||||
		/* Old systemd only has the tty name in the TTY
 | 
			
		||||
		   field, new one has the full char device path.
 | 
			
		||||
 | 
			
		||||
	snprintf(path, PATH_MAX, "/dev/tty%u", wl->vt);
 | 
			
		||||
	wl->tty = open(path, O_RDWR | O_NOCTTY | O_CLOEXEC);
 | 
			
		||||
		   Check what we have and fix it properly.
 | 
			
		||||
		*/
 | 
			
		||||
		if (strncmp(tty, "/dev", strlen("/dev")) == 0) {
 | 
			
		||||
			strncpy(path, tty, PATH_MAX);
 | 
			
		||||
			path[PATH_MAX-1] = 0;
 | 
			
		||||
		} else {
 | 
			
		||||
			snprintf(path, PATH_MAX, "/dev/%s", tty);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		wl->tty = open(path, O_RDWR | O_NOCTTY | O_CLOEXEC);
 | 
			
		||||
		free(tty);
 | 
			
		||||
#ifdef HAVE_SD_SESSION_GET_VT
 | 
			
		||||
	} else if (ok == -ENOENT) {
 | 
			
		||||
		unsigned vt;
 | 
			
		||||
 | 
			
		||||
		/* Negative errnos are cool, right?
 | 
			
		||||
		   So cool that we can't distinguish "session not found"
 | 
			
		||||
		   from "key does not exist in the session file"!
 | 
			
		||||
		   Let's assume the latter, as we got the value
 | 
			
		||||
		   from sd_pid_get_session()...
 | 
			
		||||
		*/
 | 
			
		||||
 | 
			
		||||
		ok = sd_session_get_vt(session, &vt);
 | 
			
		||||
		if (ok < 0)
 | 
			
		||||
			error(1, -ok, "could not determine current TTY");
 | 
			
		||||
 | 
			
		||||
		snprintf(path, PATH_MAX, "/dev/tty%u", vt);
 | 
			
		||||
		wl->tty = open(path, O_RDWR | O_NOCTTY | O_CLOEXEC);
 | 
			
		||||
		free(tty);
 | 
			
		||||
#endif
 | 
			
		||||
	} else
 | 
			
		||||
		error(1, -ok, "could not determine current TTY");
 | 
			
		||||
 | 
			
		||||
	if (wl->tty < 0)
 | 
			
		||||
		error(1, errno, "failed to open tty");
 | 
			
		||||
 
 | 
			
		||||
@@ -31,8 +31,9 @@ enum weston_launcher_message_type {
 | 
			
		||||
 | 
			
		||||
enum weston_launcher_opcode {
 | 
			
		||||
	WESTON_LAUNCHER_OPEN              = (1 << 1 | WESTON_LAUNCHER_REQUEST),
 | 
			
		||||
	WESTON_LAUNCHER_ACTIVATE_VT       = (2 << 1 | WESTON_LAUNCHER_REQUEST),
 | 
			
		||||
	WESTON_LAUNCHER_CONFIRM_VT_SWITCH = (3 << 1 | WESTON_LAUNCHER_REQUEST),
 | 
			
		||||
	WESTON_LAUNCHER_DRM_SET_FD        = (2 << 1 | WESTON_LAUNCHER_REQUEST),
 | 
			
		||||
	WESTON_LAUNCHER_ACTIVATE_VT       = (3 << 1 | WESTON_LAUNCHER_REQUEST),
 | 
			
		||||
	WESTON_LAUNCHER_CONFIRM_VT_SWITCH = (4 << 1 | WESTON_LAUNCHER_REQUEST),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum weston_launcher_server_opcode {
 | 
			
		||||
@@ -52,7 +53,7 @@ struct weston_launcher_open {
 | 
			
		||||
 | 
			
		||||
struct weston_launcher_activate_vt {
 | 
			
		||||
	struct weston_launcher_message header;
 | 
			
		||||
	signed char vt;
 | 
			
		||||
	int vt;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct weston_launcher_reply {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,57 +0,0 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2001 Havoc Pennington, Anders Carlsson
 | 
			
		||||
 * Copyright (C) 2002, 2003 Red Hat, Inc.
 | 
			
		||||
 * Copyright (C) 2003 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 "window-private.h"
 | 
			
		||||
 | 
			
		||||
#ifndef META_WINDOW_X11_PRIVATE_H
 | 
			
		||||
#define META_WINDOW_X11_PRIVATE_H
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaWindowX11Private MetaWindowX11Private;
 | 
			
		||||
 | 
			
		||||
struct _MetaWindowX11
 | 
			
		||||
{
 | 
			
		||||
  MetaWindow parent;
 | 
			
		||||
 | 
			
		||||
  MetaWindowX11Private *priv;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaWindowX11Private
 | 
			
		||||
{
 | 
			
		||||
  /* TRUE if the client forced these on */
 | 
			
		||||
  guint wm_state_skip_taskbar : 1;
 | 
			
		||||
  guint wm_state_skip_pager : 1;
 | 
			
		||||
 | 
			
		||||
  /* Weird "_NET_WM_STATE_MODAL" flag */
 | 
			
		||||
  guint wm_state_modal : 1;
 | 
			
		||||
 | 
			
		||||
  /* Info on which props we got our attributes from */
 | 
			
		||||
  guint using_net_wm_name              : 1; /* vs. plain wm_name */
 | 
			
		||||
  guint using_net_wm_visible_name      : 1; /* tracked so we can clear it */
 | 
			
		||||
 | 
			
		||||
  Atom type_atom;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										0
									
								
								stamp.h.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								stamp.h.in
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										7
									
								
								test/tokentest/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								test/tokentest/Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
# completely hacked-up makefile, proceed at your own risk, etc
 | 
			
		||||
 | 
			
		||||
default:
 | 
			
		||||
	@echo "Try 'make tp' or 'make glib'"
 | 
			
		||||
 | 
			
		||||
tp: tokentest.c
 | 
			
		||||
	gcc `pkg-config --cflags --libs glib-2.0 gdk-2.0 atk` -DMUTTER_DATADIR=\"/usr/share/mutter\" -I../.. -I../../src -I../../src/include tokentest.c ../../src/ui/theme.c ../../src/ui/gradient.c -o tp
 | 
			
		||||
							
								
								
									
										19
									
								
								test/tokentest/README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								test/tokentest/README
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
Tokeniser test
 | 
			
		||||
==============
 | 
			
		||||
This directory contains a set of tools for checking the behaviour
 | 
			
		||||
of the tokeniser for Metacity theme files.
 | 
			
		||||
 | 
			
		||||
tokentest.ini contains a list of all expressions retrieved from
 | 
			
		||||
all theme files on art.gnome.org, and mappings to what the tokenising
 | 
			
		||||
should be, in a separate representation.  get-tokens.py produces the
 | 
			
		||||
template version of this; it will produce a file with no expected
 | 
			
		||||
values.
 | 
			
		||||
 | 
			
		||||
tokentest.c will either check that a tokeniser behaves according to
 | 
			
		||||
tokentest.ini, or, if it finds a file, is empty it will print the
 | 
			
		||||
values that the tokeniser it's using is producing.
 | 
			
		||||
 | 
			
		||||
The makefile is a hacky attempt at letting you compile either against
 | 
			
		||||
Metacity's existing tokeniser or one which uses GLib's "scanner".
 | 
			
		||||
 | 
			
		||||
This code may or may not eventually end up in the automated test suite.
 | 
			
		||||
							
								
								
									
										89
									
								
								test/tokentest/get-tokens.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								test/tokentest/get-tokens.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,89 @@
 | 
			
		||||
#!/usr/bin/python
 | 
			
		||||
# Copyright (C) 2008 Thomas Thurman
 | 
			
		||||
# 
 | 
			
		||||
# 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/>.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import os
 | 
			
		||||
import xml.sax
 | 
			
		||||
 | 
			
		||||
standard = ['x', 'y', 'width', 'height']
 | 
			
		||||
 | 
			
		||||
expressions = {
 | 
			
		||||
  'line': ['x1', 'x2', 'y1', 'y2'],
 | 
			
		||||
  'rectangle': standard,
 | 
			
		||||
  'arc': standard,
 | 
			
		||||
  'clip': standard,
 | 
			
		||||
  'gradient': standard,
 | 
			
		||||
  'image': standard,
 | 
			
		||||
  'gtk_arrow': standard,
 | 
			
		||||
  'gtk_box': standard,
 | 
			
		||||
  'gtk_vline': standard,
 | 
			
		||||
  'icon': standard,
 | 
			
		||||
  'title': standard,
 | 
			
		||||
  'include': standard,
 | 
			
		||||
  'tile': ['x', 'y', 'width', 'height',
 | 
			
		||||
           'tile_xoffset', 'tile_yoffset',
 | 
			
		||||
           'tile_width', 'tile_height'],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
all_themes = '../../../all-themes/'
 | 
			
		||||
 | 
			
		||||
result = {}
 | 
			
		||||
 | 
			
		||||
class themeparser:
 | 
			
		||||
  def __init__(self, name):
 | 
			
		||||
    self.filename = name
 | 
			
		||||
 | 
			
		||||
  def processingInstruction(self):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
  def characters(self, what):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
  def setDocumentLocator(self, where):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
  def startDocument(self):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
  def startElement(self, name, attrs):
 | 
			
		||||
    if expressions.has_key(name):
 | 
			
		||||
      for attr in expressions[name]:
 | 
			
		||||
        if attrs.has_key(attr):
 | 
			
		||||
          expression = attrs[attr]
 | 
			
		||||
          if not result.has_key(expression): result[expression] = {}
 | 
			
		||||
          result[expression][self.filename] = 1
 | 
			
		||||
 | 
			
		||||
  def endElement(self, name):
 | 
			
		||||
    pass # print "end element"
 | 
			
		||||
 | 
			
		||||
  def endDocument(self):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
def maybe_parse(themename, filename):
 | 
			
		||||
  if os.access(all_themes+filename, os.F_OK):
 | 
			
		||||
    parser = themeparser(themename)
 | 
			
		||||
    xml.sax.parse(all_themes+filename, parser)
 | 
			
		||||
  
 | 
			
		||||
for theme in os.listdir(all_themes):
 | 
			
		||||
  maybe_parse(theme, theme+'/metacity-1/metacity-theme-1.xml')
 | 
			
		||||
  maybe_parse(theme, theme+'/metacity-theme-1.xml')
 | 
			
		||||
 | 
			
		||||
print '[tokentest0]'
 | 
			
		||||
 | 
			
		||||
for expr in sorted(result.keys()):
 | 
			
		||||
  print "# %s" % (', '.join(sorted(result[expr])))
 | 
			
		||||
  print "%s=REQ" % (expr)
 | 
			
		||||
  print
 | 
			
		||||
							
								
								
									
										304
									
								
								test/tokentest/tokentest.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										304
									
								
								test/tokentest/tokentest.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,304 @@
 | 
			
		||||
/* 
 | 
			
		||||
 * tokentest.c - test for Metacity's tokeniser
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2008 Thomas Thurman
 | 
			
		||||
 * 
 | 
			
		||||
 * 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/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Still under heavy development. */
 | 
			
		||||
/* Especially: FIXME: GErrors need checking! */
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <glib/gerror.h>
 | 
			
		||||
#include <gtk/gtkobject.h>
 | 
			
		||||
#include <gtk/gtkicontheme.h>
 | 
			
		||||
#include <ui/theme.h>
 | 
			
		||||
#include <util.h>
 | 
			
		||||
 | 
			
		||||
#define TOKENTEST_GROUP "tokentest0"
 | 
			
		||||
 | 
			
		||||
/************************/
 | 
			
		||||
/* Dummy functions which are just here to keep the linker happy */
 | 
			
		||||
 | 
			
		||||
MetaTheme* meta_theme_load (const char *theme_name,
 | 
			
		||||
                            GError    **err) {
 | 
			
		||||
  /* dummy */
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_bug(const char *format, ...)
 | 
			
		||||
{
 | 
			
		||||
  /* dummy */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_warning(const char *format, ...)
 | 
			
		||||
{
 | 
			
		||||
  /* dummy */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GType
 | 
			
		||||
gtk_widget_get_type (void)
 | 
			
		||||
{
 | 
			
		||||
  /* dummy */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GType
 | 
			
		||||
gtk_object_get_type (void)
 | 
			
		||||
{
 | 
			
		||||
  /* dummy */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void gtk_paint_arrow      (GtkStyle        *style,
 | 
			
		||||
                           GdkWindow       *window,
 | 
			
		||||
                           GtkStateType     state_type,
 | 
			
		||||
                           GtkShadowType    shadow_type,
 | 
			
		||||
                           GdkRectangle    *area,
 | 
			
		||||
                           GtkWidget       *widget,
 | 
			
		||||
                           const gchar     *detail,
 | 
			
		||||
                           GtkArrowType     arrow_type,
 | 
			
		||||
                           gboolean         fill,
 | 
			
		||||
                           gint             x,
 | 
			
		||||
                           gint             y,
 | 
			
		||||
                           gint             width,
 | 
			
		||||
                           gint             height)
 | 
			
		||||
{
 | 
			
		||||
  /* dummy */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void gtk_paint_vline      (GtkStyle        *style,
 | 
			
		||||
                           GdkWindow       *window,
 | 
			
		||||
                           GtkStateType     state_type,
 | 
			
		||||
                           GdkRectangle    *area,
 | 
			
		||||
                           GtkWidget       *widget,
 | 
			
		||||
                           const gchar     *detail,
 | 
			
		||||
                           gint             y1_,
 | 
			
		||||
                           gint             y2_,
 | 
			
		||||
                           gint             x)
 | 
			
		||||
{
 | 
			
		||||
  /* dummy */
 | 
			
		||||
}
 | 
			
		||||
void gtk_paint_box        (GtkStyle        *style,
 | 
			
		||||
                           GdkWindow       *window,
 | 
			
		||||
                           GtkStateType     state_type,
 | 
			
		||||
                           GtkShadowType    shadow_type,
 | 
			
		||||
                           GdkRectangle    *area,
 | 
			
		||||
                           GtkWidget       *widget,
 | 
			
		||||
                           const gchar     *detail,
 | 
			
		||||
                           gint             x,
 | 
			
		||||
                           gint             y,
 | 
			
		||||
                           gint             width,
 | 
			
		||||
                           gint             height)
 | 
			
		||||
{
 | 
			
		||||
  /* dummy */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GtkIconTheme *gtk_icon_theme_get_default           (void)
 | 
			
		||||
{
 | 
			
		||||
  /* dummy */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GdkPixbuf *   gtk_icon_theme_load_icon             (GtkIconTheme                *icon_theme,
 | 
			
		||||
                                                    const gchar                 *icon_name,
 | 
			
		||||
                                                    gint                         size,
 | 
			
		||||
                                                    GtkIconLookupFlags           flags,
 | 
			
		||||
                                                    GError                     **error)
 | 
			
		||||
{
 | 
			
		||||
  /* dummy */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetaRectangle                 meta_rect (int x, int y, int width, int height)
 | 
			
		||||
{
 | 
			
		||||
  /* dummy */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_topic_real (MetaDebugTopic topic,
 | 
			
		||||
                 const char *format,
 | 
			
		||||
                 ...)
 | 
			
		||||
{
 | 
			
		||||
  /* dummy */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*********************************/
 | 
			
		||||
 | 
			
		||||
GString *draw_spec_to_string(MetaDrawSpec *spec)
 | 
			
		||||
{
 | 
			
		||||
  GString *result;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  if (spec == NULL)
 | 
			
		||||
    return g_string_new ("NONE");
 | 
			
		||||
 | 
			
		||||
  result = g_string_new ("");
 | 
			
		||||
 | 
			
		||||
  if (spec->constant)
 | 
			
		||||
    {
 | 
			
		||||
      g_string_append_printf (result, "{%d==}", spec->value);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  for (i=0; i<spec->n_tokens; i++)
 | 
			
		||||
    {
 | 
			
		||||
      PosToken t = spec->tokens[i];
 | 
			
		||||
 | 
			
		||||
      switch (t.type)
 | 
			
		||||
        {
 | 
			
		||||
        case POS_TOKEN_INT:
 | 
			
		||||
          g_string_append_printf (result, "(int %d)", t.d.i.val);
 | 
			
		||||
          break;
 | 
			
		||||
 | 
			
		||||
        case POS_TOKEN_DOUBLE:
 | 
			
		||||
          g_string_append_printf (result, "(double %g)", t.d.d.val);
 | 
			
		||||
          break;
 | 
			
		||||
 | 
			
		||||
        case POS_TOKEN_OPERATOR:
 | 
			
		||||
 | 
			
		||||
          switch (t.d.o.op) {
 | 
			
		||||
            case POS_OP_NONE:
 | 
			
		||||
              g_string_append (result, "(no-op)");
 | 
			
		||||
              break;
 | 
			
		||||
 | 
			
		||||
            case POS_OP_ADD:
 | 
			
		||||
              g_string_append (result, "(add)");
 | 
			
		||||
              break;
 | 
			
		||||
 | 
			
		||||
            case POS_OP_SUBTRACT:
 | 
			
		||||
              g_string_append (result, "(subtract)");
 | 
			
		||||
              break;
 | 
			
		||||
 | 
			
		||||
            case POS_OP_MULTIPLY:
 | 
			
		||||
              g_string_append (result, "(multiply)");
 | 
			
		||||
              break;
 | 
			
		||||
 | 
			
		||||
            case POS_OP_DIVIDE:
 | 
			
		||||
              g_string_append (result, "(divide)");
 | 
			
		||||
              break;
 | 
			
		||||
 | 
			
		||||
            case POS_OP_MOD:
 | 
			
		||||
              g_string_append (result, "(mod)");
 | 
			
		||||
              break;
 | 
			
		||||
 | 
			
		||||
            case POS_OP_MAX:
 | 
			
		||||
              g_string_append (result, "(max)");
 | 
			
		||||
              break;
 | 
			
		||||
 | 
			
		||||
            case POS_OP_MIN:
 | 
			
		||||
              g_string_append (result, "(min)");
 | 
			
		||||
              break;
 | 
			
		||||
 | 
			
		||||
            default:
 | 
			
		||||
              g_string_append_printf (result, "(op %d)", t.d.o.op);
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          break;
 | 
			
		||||
 | 
			
		||||
        case POS_TOKEN_VARIABLE:
 | 
			
		||||
          g_string_append_printf (result, "(str %s)", t.d.v.name);
 | 
			
		||||
          break;
 | 
			
		||||
 | 
			
		||||
        case POS_TOKEN_OPEN_PAREN:
 | 
			
		||||
          g_string_append (result, "( ");
 | 
			
		||||
          break;
 | 
			
		||||
 | 
			
		||||
       case POS_TOKEN_CLOSE_PAREN:
 | 
			
		||||
          g_string_append (result, " )");
 | 
			
		||||
          break;
 | 
			
		||||
 | 
			
		||||
        default:
 | 
			
		||||
          g_string_append_printf (result, "(strange %d)", t.type);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GKeyFile *keys;
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
load_keys ()
 | 
			
		||||
{
 | 
			
		||||
  GError* err = NULL;
 | 
			
		||||
  gchar** keys_of_file;
 | 
			
		||||
  gchar** cursor;
 | 
			
		||||
  gboolean ever_printed_header = FALSE;
 | 
			
		||||
  gint passes = 0, fails = 0;
 | 
			
		||||
 | 
			
		||||
  keys = g_key_file_new ();
 | 
			
		||||
 | 
			
		||||
  g_key_file_load_from_file (keys,
 | 
			
		||||
        "tokentest.ini",
 | 
			
		||||
        G_KEY_FILE_KEEP_COMMENTS,
 | 
			
		||||
        &err);
 | 
			
		||||
 | 
			
		||||
  keys_of_file = g_key_file_get_keys (keys,
 | 
			
		||||
				      TOKENTEST_GROUP,
 | 
			
		||||
				      NULL,
 | 
			
		||||
				      &err);
 | 
			
		||||
 | 
			
		||||
  cursor = keys_of_file;
 | 
			
		||||
 | 
			
		||||
  while (*cursor)
 | 
			
		||||
    {
 | 
			
		||||
      gchar *desideratum = g_key_file_get_value (keys,
 | 
			
		||||
						 TOKENTEST_GROUP,
 | 
			
		||||
						 *cursor,
 | 
			
		||||
						 &err);
 | 
			
		||||
      MetaTheme *dummy = meta_theme_new ();
 | 
			
		||||
      MetaDrawSpec *spec;
 | 
			
		||||
      GString *str;
 | 
			
		||||
 | 
			
		||||
      spec = meta_draw_spec_new (dummy, *cursor, &err);
 | 
			
		||||
 | 
			
		||||
      str = draw_spec_to_string (spec);
 | 
			
		||||
 | 
			
		||||
      if (strcmp ("REQ", desideratum)==0) {
 | 
			
		||||
	gchar *comment = g_key_file_get_comment (keys, TOKENTEST_GROUP, *cursor, &err);
 | 
			
		||||
 | 
			
		||||
	if (!ever_printed_header) {
 | 
			
		||||
	  g_print ("[%s]\n", TOKENTEST_GROUP);
 | 
			
		||||
	  ever_printed_header = TRUE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	g_print ("\n#%s%s=%s\n", comment? comment: "", *cursor, str->str);
 | 
			
		||||
	g_free (comment);
 | 
			
		||||
      } else if (strcmp (str->str, desideratum)==0) {
 | 
			
		||||
        g_print("PASS: %s\n", *cursor);
 | 
			
		||||
	passes++;
 | 
			
		||||
      } else {
 | 
			
		||||
        g_warning ("FAIL: %s, wanted %s, got %s\n",
 | 
			
		||||
            *cursor, desideratum, str->str);
 | 
			
		||||
	fails++;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      meta_theme_free (dummy);
 | 
			
		||||
      g_string_free (str, TRUE);
 | 
			
		||||
      g_free (desideratum);
 | 
			
		||||
 | 
			
		||||
      cursor++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_strfreev (keys_of_file);
 | 
			
		||||
 | 
			
		||||
  g_print("\n# Passes: %d.  Fails: %d.\n", passes, fails);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main ()
 | 
			
		||||
{
 | 
			
		||||
  load_keys ();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1873
									
								
								test/tokentest/tokentest.ini
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1873
									
								
								test/tokentest/tokentest.ini
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										43
									
								
								tools/xlib.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								tools/xlib.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
			
		||||
# Very simple Xlib-based client in Python.
 | 
			
		||||
# Copyright (c) 2008 Thomas Thurman <tthurman@gnome.org>; GPL 2.0 or later.
 | 
			
		||||
# Originally based around example code in python-xlib
 | 
			
		||||
# by Peter Liljenberg <petli@ctrl-c.liu.se>.
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
from Xlib import X
 | 
			
		||||
from Xlib.protocol import display
 | 
			
		||||
from Xlib.protocol.request import *
 | 
			
		||||
 | 
			
		||||
display = display.Display()
 | 
			
		||||
screen = display.info.roots[display.default_screen]
 | 
			
		||||
window = display.allocate_resource_id()
 | 
			
		||||
gc = display.allocate_resource_id()
 | 
			
		||||
 | 
			
		||||
CreateWindow(display, None,
 | 
			
		||||
             depth = screen.root_depth,
 | 
			
		||||
             wid = window,
 | 
			
		||||
             parent = screen.root,
 | 
			
		||||
             x = 100, y = 100, width = 250, height = 250, border_width = 2,
 | 
			
		||||
             window_class = X.InputOutput, visual = X.CopyFromParent,
 | 
			
		||||
             background_pixel = screen.white_pixel,
 | 
			
		||||
             event_mask = (X.ExposureMask |
 | 
			
		||||
                           X.StructureNotifyMask |
 | 
			
		||||
                           X.ButtonPressMask |
 | 
			
		||||
                           X.ButtonReleaseMask |
 | 
			
		||||
                           X.Button1MotionMask),
 | 
			
		||||
             colormap = X.CopyFromParent)
 | 
			
		||||
 | 
			
		||||
CreateGC(display, None, gc, window)
 | 
			
		||||
 | 
			
		||||
MapWindow(display, None, window)
 | 
			
		||||
 | 
			
		||||
while 1:
 | 
			
		||||
    event = display.next_event()
 | 
			
		||||
 | 
			
		||||
    if event.type == X.DestroyNotify:
 | 
			
		||||
        sys.exit(0)
 | 
			
		||||
 | 
			
		||||
    print event
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user