Compare commits

..

1 Commits

Author SHA1 Message Date
7e28a69c51 window: Assume CSD frame extents are 0 in maximized and tiling modes
When the user maximized a CSD window, this is the order of operations
that happens:

  1. The CSD application sends us a _NET_WM_STATE client message telling
     us to add the _NET_WM_MAXIMIZED_VERT/HORZ state.

  2. We respond by setting _NET_WM_STATE on the window and resizing the
     window. Windows are positioned according to the visible borders of
     the window, so since _GTK_FRAME_EXTENTS has not been updated yet to
     reflect the border/padding of the window state, the borders are wrong.

  3. GTK+ gets the _NET_WM_STATE event, updates its state, and then sets
     new theme properties, including _GTK_FRAME_EXTENTS.

  4. mutter sees that _GTK_FRAME_EXTENTS has been updated, and repositions
     the window to where it should be.

This means that the user sees the borders "flicker" for a half-second while
the maximization state is in limbo. Trying to make this resize operation
atomic is a foregone conclusion under X11, so to solve this, we're going to
make two changes to our _GTK_FRAME_EXTENTS protocol:

  1. _GTK_FRAME_EXTENTS now reflects the "normal" borders, always. This
     means that _GTK_FRAME_EXTENTS should not change at runtime unless the
     theme changes.

  2. mutter will only respect _GTK_FRAME_EXTENTS in places where the user
     expects to see a shadow. This means that mutter will hardcode the
     extents to 0 when the window is maximized. If the window is tiled-left,
     then all extents will be 0, except for the shadow on the right hand
     side, and vice versa for the tiled-right state.
2014-01-10 14:07:45 -05:00
291 changed files with 55624 additions and 41827 deletions

24
.gitignore vendored
View File

@ -22,8 +22,8 @@ missing
src/50-mutter-navigation.xml
src/50-mutter-system.xml
src/50-mutter-windows.xml
src/mutter-wm.desktop
src/mutter.desktop
src/mutter-wayland.desktop
*.o
*.a
*.lo
@ -48,10 +48,10 @@ po/*.pot
50-metacity-key.xml
libmutter.pc
mutter
mutter-theme-viewer
mutter.desktop
org.gnome.mutter.gschema.valid
org.gnome.mutter.gschema.xml
org.gnome.mutter.wayland.gschema.valid
org.gnome.mutter.wayland.gschema.xml
testasyncgetprop
testboxes
testgradient
@ -75,15 +75,9 @@ src/mutter-enum-types.[ch]
src/stamp-mutter-enum-types.h
src/mutter-marshal.[ch]
src/stamp-mutter-marshal.h
src/meta-dbus-display-config.[ch]
src/meta-dbus-xrandr.[ch]
src/meta-dbus-idle-monitor.[ch]
src/meta-dbus-login1.[ch]
src/gtk-shell-protocol.c
src/gtk-shell-server-protocol.h
src/xdg-shell-protocol.c
src/xdg-shell-server-protocol.h
src/xserver-protocol.c
src/xserver-server-protocol.h
src/mutter-plugins.pc
doc/reference/*.args
doc/reference/*.bak
doc/reference/*.hierarchy
@ -101,11 +95,3 @@ doc/reference/meta-undocumented.txt
doc/reference/meta-unused.txt
doc/reference/meta-docs.sgml
doc/reference/meta.types
gtk-doc.m4
intltool.m4
libtool.m4
ltoptions.m4
ltsugar.m4
ltversion.m4
lt~obsolete.m4
.dirstamp

1
AUTHORS Normal file
View File

@ -0,0 +1 @@
Havoc Pennington <hp@redhat.com>

159
COMPLIANCE Normal file
View 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

41
COPYING
View File

@ -1,12 +1,12 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
@ -55,8 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
@ -225,7 +225,7 @@ impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
@ -303,16 +303,17 @@ the "copyright" line and a pointer to where the full notice is found.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
@ -335,5 +336,5 @@ necessary. Here is a sample; alter the names:
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

15414
ChangeLog Normal file

File diff suppressed because it is too large Load Diff

1297
Doxyfile Normal file

File diff suppressed because it is too large Load Diff

298
HACKING Normal file
View 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
View 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
View 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

View File

@ -3,6 +3,8 @@ SUBDIRS=src po doc
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
EXTRA_DIST = HACKING MAINTAINERS rationales.txt
DISTCLEANFILES = intltool-extract intltool-merge intltool-update po/stamp-it po/.intltool-merge-cache
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc

227
NEWS
View File

@ -1,175 +1,63 @@
3.13.2
======
* Add basic HiDPI support on wayland [Adel; #728902]
* Fix crash when monitors change during suspend [Giovanni; #725637]
* Replace mutter-launch with logind integration [Jasper; #724604]
* Move window menu into the compositor [Jasper; #726352]
* Fix delayed focus-follows-mouse support [Florian; #730541]
* Support fallback app menu in window decorations [Florian; #730752]
* Misc. bug fixes and cleanups [Giovanni, Jonas, Jasper; #729732, #729602,
#726714]
Contributors:
Jonas Ådahl, Giovanni Campagna, Adel Gadllah, Florian Müllner,
Jasper St. Pierre, Rico Tzschichholz
Translations:
Pau Iranzo [ca], Daniel Mustieles [es]
3.13.1
======
* Fix opacity values from _NET_WM_WINDOW_OPACITY [Nirbheek; #727874]
* Merge wayland branch [Jasper, Giovanni, Robert B., Neil, Adel, Rui, Jonas,
Lionel, Tim, Owen, Florian, Colin W., Cosimo, Ray, Kalev, Pavel, Robert A.,
Magdalen, Marek, Matthias, Alban, Seán, Daniel, Stefano, Carlos, Colin G.,
Andreas, Alexander, Ryan, Marc-André, Asad, Alberto, Bastien, Hans,
Debarshi, Sindhu, Andika, Rico, Olav]
* Don't prevent workspace switches for present_with_time() [Florian; #728018]
* Add shortcuts for switching to the last workspace [Elad; #659288]
* Make move/resize menu items behave like the keybindings [Jasper; #728617]
* Misc. bug fixes and cleanups [Jasper, Bastien, Florian, Adel; #720631,
#727979, #728423, #728395, #729044]
Contributors:
Jonas Ådahl, Elad Alfassa, Robert Ancell, Magdalen Berns, Robert Bragg,
Giovanni Campagna, Cosimo Cecchi, Marek Chalupa, Nirbheek Chauhan,
Matthias Clasen, Alban Crequy, Seán de Búrca, Daniel Drake, Jason Ekstrand,
Stefano Facchini, Adel Gadllah, Carlos Garnacho, Colin Guthrie,
Andreas Heider, Lionel Landwerlin, Alexander Larsson, Kalev Lember,
Ryan Lortie, Tim Lunn, Marc-André Lureau, Rui Matos, Asad Mehmood,
Alberto Milone, Florian Müllner, Bastien Nocera, Hans Petter Jansson,
Debarshi Ray, Neil Roberts, Sindhu S, Jasper St. Pierre, Ray Strode,
Andika Triwidada, Rico Tzschichholz, Pavel Vasin, Olav Vitters,
Colin Walters, A. Walton, Owen W. Taylor
Translations:
Inaki Larranaga Murgoitio [eu], marablack3 [el], Daniel Mustieles [es],
Fran Diéguez [gl], Yosef Or Boczko [he], Dirgita [id]
3.12.0
======
* Fix grab issue with SSD xwayland windows [Rui; #726123]
* Misc. bug fixes [Jasper, Ray, Rui, Florian; #727011]
Contributors:
Rui Matos, Florian Müllner, Jasper St. Pierre, Ray Strode
3.11.92
=======
* Fix identification of CSD windows [Owen; #723029]
* Update keyboard state unconditionally [Rui; #722847]
* Misc bug fixes and cleanups [Owen, Rui, Giovanni, Matthias, Adel, Ryan,
Jasper, Marek, Florian; #723580, #726123, #726683]
Contributors:
Giovanni Campagna, Marek Chalupa, Matthias Clasen, Adel Gadllah, Ryan Lortie,
Rui Matos, Florian Müllner, Jasper St. Pierre, Owen W. Taylor
3.11.91
=======
* Don't use keysym to match keybindings [Rui; #678001]
* Fix message tray icons showing up blank (again) [Adel; #725180]
* Improve keybinding lookups [Rui; #725588]
* Fix dynamic updates of titlebar style properties [Owen; #725751]
* Fix positioning of manually positioned windows [Owen; #724049]
* Misc bug fixes and cleanups [Jasper, Carlos, Adel, Giovanni, Florian; #720631,
#724969, #725216, #724402, #722266, #725338, #725525]
Contributors:
Giovanni Campagna, Adel Gadllah, Carlos Garnacho, Rui Matos, Florian Müllner,
Jasper St. Pierre, Owen W. Taylor
3.11.90
=======
* Fix double-scaling on high DPI resolutions [Adel; #723931]
* Make tile previews a compositor effect [Stefano, Florian; #665758]
* Misc. bug fixes and cleanups [Ryan, Giovanni, Jasper, Adel; #722530, #724257,
#724258, #720631, #724364, #724472]
Contributors:
Giovanni Campagna, Marek Chalupa, Stefano Facchini, Adel Gadllah,
Ryan Lortie, Florian Müllner, Jasper St. Pierre, Rico Tzschichholz
3.11.5
======
* Fix CSD titlebars being placed off-screen [Jasper; #719772]
* Add support for subsurfaces [Jonas; #705502]
* Expose MetaWindow:skip-taskbar property [Florian; #723307]
* Fix legacy tray icons showing up blank [Adel; #721596]
* Fix configuration of cloned monitors [Adel; #710610]
* Misc bug fixes and cleanups [Jasper, Adel, Marek, Jonas; #720631, #723468,
#720818, #723563, #723564]
Contributors:
Jonas Ådahl, Marek Ch, Adel Gadllah, Florian Müllner, Jasper St. Pierre
3.11.4
======
* Don't leave focus on windows that are being unmanaged [Owen; #711618]
* Reduce server grabs [Daniel Drake; #721345, #721709]
* Improve heuristic to determine display output name [Cosimo Cecchi; #721674]
* Atomically unmaximize both directions [Jasper; #722108]
* Misc bug fixes [Debarshi, Andika, Florian; #721517, #721674, #722347]
Contributors:
Cosimo Cecchi, Daniel Drake, Florian Müllner, Debarshi Ray, Jasper St. Pierre,
Andika Triwidada, Owen W. Taylor
3.11.3
======
* Fix focus issues with external OSKs[Jasper; #715030]
* xrandr: Use "hotplug_mode_update" property [Marc-André; #711216]
* Fix position of attached dialogs for CSD windows [Giovanni, Owen; #707194]
* Fix focus issues with external OSKs [Jasper; #715030]
* Add a MetaCullable interface [Jasper; #714706]
* Fix window keybindings [Rui; #719724]
* Fix settings keyboard/pointer focus for new clients [Rui; #719725]
* Fix window group paint volume [Owen; #719669]
* Fix frame extents problems [Owen; #714707]
* Add shortcut to move windows between monitors [Florian; #671054]
* Fix problems with focus tracking [Owen; #720558]
* Misc. bug fixes and cleanups: [Rui, Colin, Lionel, Jasper, Owen; #712833,
#719557, #719695, #719833, #678989, #720417, #720630]
* Misc. bug fixes and cleanups [Rui, Jasper, Owen; #712833, #678989, #720106,
#720417, #720630]
Contributors:
Lionel Landwerlin, Rui Matos, Alberto Milone, Florian Müllner,
Jasper St. Pierre, Rico Tzschichholz, Owen W. Taylor, Colin Walters
Robert Bragg, Giovanni Campagna, Marc-André Lureau, Rui Matos, Alberto Milone,
Florian Müllner, Sindhu S, Jasper St. Pierre, Rico Tzschichholz,
Owen W. Taylor
Translations:
甘露(Gan Lu) [zh_CN], Khaled Hosny [ar]
3.11.2
======
* Support setting a NULL opaque region [Andreas; #711518]
* Sync keymap from X to wayland [Giovanni; #707446]
* Implement support for subsurfaces [Jonas; #705502]
* Don't focus the no-focus-window for globally active windows [Jasper; #710296]
* Support "hotplug_mode_update" property [Marc-André; #711216]
* Fix resize operations using mouse-button-modifier [Lionel; #710251]
* Fix position of attached modals for CSD windows [Giovanni, Owen; #707194]
* Misc. bug fixes [Rui, Jasper, Neil, Florian; #712247, #711731]
* Misc. fixes and cleanups [Jasper, Rico, Florian; #711731]
Contributors:
Giovanni Campagna, Andreas Heider, Lionel Landwerlin, Marc-André Lureau,
Rui Matos, Florian Müllner, Neil Roberts, Sindhu S, Jasper St. Pierre,
Rico Tzschichholz, Owen W. Taylor, Jonas Ådahl
Lionel Landwerlin, Florian Müllner, Jasper St. Pierre, Rico Tzschichholz
3.11.1
======
* Fix tile previews getting stuck on right click during drags [Lionel; #704759]
* Don't require at least one output device to be connected [Giovanni; #709009]
* Name the guard window [Andrew; #710346]
* Use new UPower API [Bastien]
* Set hot spot when cursor set from wl_buffer [Jonas; #709593]
* Expose min-backlight-step [Asad; #710380]
* Misc. bug fixes and cleanups [Jasper, Olav, Magdalen; #709776]
* Don't focus the no-focus-window for globally active windows [Jasper; #710296]
* Misc. fixes and cleanups [Jasper, Rico, Olav, Magdalen; #709776]
Contributors:
Magdalen Berns, Lionel Landwerlin, Asad Mehmood, Bastien Nocera,
Jasper St. Pierre, Olav Vitters, Jonas Ådahl
Magdalen Berns, Giovanni Campagna, Asad Mehmood, Bastien Nocera,
Jasper St. Pierre, Rico Tzschichholz, Olav Vitters, Andrew Walton
Translations:
Reinout van Schouwen [nl]
3.10.1
======
* Don't apply fullscreen workarounds to CSD windows [Giovanni; #708718]
* Fix hangs during DND operations [Adel; #709340]
* Misc bug fixes [Dan, Giovanni, Jasper; #708813, #708420]
* Use nearest-pixel interpolation when possible [Hans; #708389]
* Fix tile previews getting stuck on right click during drags [Lionel; #704759]
* Misc bug fixes [Giovanni, Jasper; #708420]
Contributors:
Giovanni Campagna, Adel Gadllah, Dan Horák, Hans Petter Jansson,
Giovanni Campagna, Adel Gadllah, Lionel Landwerlin, Hans Petter Jansson,
Jasper St. Pierre
Translations:
Khaled Hosny [ar], Reinout van Schouwen [nl], Carles Ferrando [ca@valencia]
3.10.0.1
========
* Fix bug when a window changed size twice in a single frame - this
@ -180,32 +68,24 @@ Contributors:
3.10.0
======
* Update dependencies [Giovanni; #708210]
Translations:
Ask H. Larsen [da], Gabor Kelemen [hu], Duarte Loreto [pt],
Yosef Or Boczko [he]
3.9.92
======
* Constrain the pointer position onto visible monitors [Giovanni; #706655]
* Fix keyboard state handling in face of event compression [Giovanni; #706963]
* Extend the MetaCursorTracker API with query pointer and cursor visibility [Giovanni; #707474]
* Be stricter in checking and exposing the wayland protocol version [#707851]
* Don't require plugins to pass event to Clutter [Giovanni; #707482]
* Move the --wayland option from the binary to the library [Giovanni; #707897]
* Implement running from gnome-session (environment variable setting, process group
handling, Clutter backend variables) [Giovanni; #706421]
* Add support for more cursor types [Giovanni; #707919]
* Drop man pages for removed utilities [Kalev; #706579]
* Implement monitor configuration on KMS [Giovanni; #706308]
* Implement HW cursors [Giovanni; #707573]
* Implement minimal support for resizing and maximizing wayland clients [Giovanni; #707401]
* Implement transient hints for wayland clients [Giovanni; #707401]
* Implement popup menu surfaces and grabs [Giovanni; #707863]
* Immediately fire idle watches that are already expired [Giovanni; #707302]
* Don't create a dummy texture for the texture pipeline template [Neil; #707458]
* Remove holes generated by disabling the laptop lid [Giovanni; #707473]
* Misc bug fixes [Giovanni, Pavel, Adel; #707649, #706124, #707584, #707851, #707929,
#708070]
* https://bugzilla.gnome.org/show_bug.cgi?id=707474 [Giovanni; #707474]
* Don't require plugins to pass event to Clutter [Giovanni; #707482]
* Add support for more cursor types [Giovanni; #707919]
* Immediately fire idle watches that are already expired [Giovanni; #707302]
* Misc bug fixes [Giovanni, Colin, Pavel; #707649, #707563, #708070]
Contributors:
Adel Gadllah, Giovanni Campagna, Kalev Lember, Pavel Vasin
Giovanni Campagna, Adel Gadllah, Colin Guthrie, Neil Roberts,
Jasper St. Pierre, Ray Strode, Pavel Vasin
Translations:
Мирослав Николић po/sr, sr@latin.po, Мирослав Николић [sr, sr@latin],
@ -218,30 +98,19 @@ Translations:
3.9.91
======
* Drop man pages for removed utilities [Kalev; #706579]
* Add support for idle tracking [Giovanni, Cosimo; #706005, #707250]
* Add support for idle tracking [Giovanni; #706005]
* Skip CRTC reconfigurations that have no effect [Giovanni; #706672]
* Ignore skip-taskbar hints on parentless dialogs [Giovanni; #673399]
* Don't save pixbuf data in user data [Tim; #706777]
* Don't queue redraws for obscured regions [Adel; #703332]
* Suppor the opaque region hints for wayland clients [Jasper; #707019]
* Turn blending off when drawing entirely opaque regions [Jasper; #707019]
* Turn blending off when drawing entirely opaque regions [Jasper; #706930]
* Check event timestamps before reconfiguring [Giovanni; #706735]
* Merge the DBus API for display configuration in the wayland branch [Giovanni]
* Install an X IO error handler for XWayland [Giovanni; #706962]
* Use the clutter xkbcommon integration for the wayland keyboard [Giovanni; #705862]
* Add a setuid helper for running on KMS+evdev [Giovanni, Colin; #705861]
* Add keybindings for switching VT [Giovanni; #705861]
* Implement plugin modality when running as a wayland compositor [Giovanni; #705917]
* Add support for the application menu for wayland clients [Giovanni; #707128]
* Several Coverity spotted fixes [Jasper]
* Don't create a dummy texture for the texture template [Neil; #707458]
* Use a more conservative paint volume for obscured windows [Adel]
* Misc bug fixes [Giovanni, Colin, Seán, Jasper, Cosimo; #706582, #706598,
#706787, #706729, #706825, #707081, #707090, #707267, #706982, #706289]
#706787, #706729, #706825, #707081, #707090, #707250, #707267]
Contributors:
Giovanni Campagna, Cosimo Cecchi, Adel Gadllah, Colin Guthrie, Kalev Lember,
Tim Lunn, Jasper St. Pierre, Neil Roberts, Rico Tzschichholz, Seán de Búrca
Tim Lunn, Jasper St. Pierre, Rico Tzschichholz, Seán de Búrca
Translations:
Piotr Drąg [pl], Alexandre Franke [fr], Kjartan Maraas [nb],
@ -250,8 +119,6 @@ Translations:
3.9.90
======
* First release from the wayland branch, includes basic support for running
as a wayland compositor [Robert, Neil, Giovanni]
* Add support for _GTK_FRAME_EXTENTS [Jasper; #705766]
* Fix quick consecutive <super> presses breaking keyboard input [Alban; #666101]
* Work towards running as wayland compositor [Giovanni]
@ -266,8 +133,8 @@ Translations:
Contributors:
Robert Bragg, Giovanni Campagna, Alban Crequy, Adel Gadllah,
Alexander Larsson, Florian Müllner, Jasper St. Pierre, Neil Roberts,
Rico Tzschichholz, Colin Walters
Alexander Larsson, Florian Müllner, Jasper St. Pierre, Rico Tzschichholz,
Colin Walters
Translations:
Jiro Matsuzawa [ja], Kjartan Maraas [nb], Matej Urbančič [sl],

416
README Normal file
View 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.

View File

@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
# Run this to generate all the initial makefiles, etc.
srcdir=`dirname $0`

View File

@ -2,8 +2,8 @@ AC_PREREQ(2.50)
AC_CONFIG_MACRO_DIR([m4])
m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [13])
m4_define([mutter_micro_version], [2])
m4_define([mutter_minor_version], [11])
m4_define([mutter_micro_version], [3])
m4_define([mutter_version],
[mutter_major_version.mutter_minor_version.mutter_micro_version])
@ -17,7 +17,7 @@ AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_SRCDIR(src/core/display.c)
AC_CONFIG_HEADERS(config.h)
AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz tar-ustar subdir-objects])
AM_INIT_AUTOMAKE([1.11 no-dist-gzip dist-xz tar-ustar])
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],)
AM_MAINTAINER_MODE([enable])
@ -74,9 +74,9 @@ MUTTER_PC_MODULES="
pango >= 1.2.0
cairo >= 1.10.0
gsettings-desktop-schemas >= 3.7.3
xcomposite >= 0.2 xfixes xext xdamage xi >= 1.6.0
$CLUTTER_PACKAGE >= 1.17.5
cogl-1.0 >= 1.17.1
xcomposite >= 0.2 xfixes xrender xdamage xi >= 1.6.0
$CLUTTER_PACKAGE >= 1.15.90
cogl-1.0 >= 1.15.6
upower-glib >= 0.99.0
gnome-desktop-3.0
"
@ -117,11 +117,6 @@ AC_ARG_ENABLE(shape,
[disable mutter's use of the shaped window extension]),,
enable_shape=auto)
AC_ARG_WITH([xwayland-path],
[AS_HELP_STRING([--with-xwayland-path], [Absolute path for an X Wayland server])],
[XWAYLAND_PATH="$withval"],
[XWAYLAND_PATH="$bindir/Xwayland"])
AM_GLIB_GNU_GETTEXT
## here we get the flags we'll actually use
@ -191,22 +186,21 @@ if test x$found_introspection != xno; then
AC_SUBST(META_GIR)
fi
MUTTER_PC_MODULES="$MUTTER_PC_MODULES xcursor"
AC_MSG_CHECKING([Xcursor])
if $PKG_CONFIG xcursor; then
have_xcursor=yes
else
have_xcursor=no
fi
AC_MSG_RESULT($have_xcursor)
AC_PATH_PROG([WAYLAND_SCANNER],[wayland-scanner],[no])
AS_IF([test "x$WAYLAND_SCANNER" = "xno"],
AC_MSG_ERROR([Could not find wayland-scanner in your PATH, required for parsing wayland extension protocols]))
AC_SUBST([WAYLAND_SCANNER])
AC_SUBST(XWAYLAND_PATH)
MUTTER_PC_MODULES="$MUTTER_PC_MODULES clutter-wayland-1.0 clutter-wayland-compositor-1.0 clutter-egl-1.0 wayland-server >= 1.4.93"
PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES)
PKG_CHECK_MODULES(MUTTER_NATIVE_BACKEND, [libdrm libsystemd], [have_native_backend=yes], [have_native_backend=no])
if test $have_native_backend = yes; then
AC_DEFINE([HAVE_NATIVE_BACKEND],[1],[Define if you want to enable the native (KMS) backend based on systemd])
if test x$have_xcursor = xyes; then
echo "Building with Xcursor"
MUTTER_PC_MODULES="$MUTTER_PC_MODULES xcursor"
AC_DEFINE(HAVE_XCURSOR, , [Building with Xcursor support])
fi
AM_CONDITIONAL([HAVE_NATIVE_BACKEND],[test $have_native_backend = yes])
PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES)
PKG_CHECK_EXISTS([xi >= 1.6.99.1],
AC_DEFINE([HAVE_XI23],[1],[Define if you have support for XInput 2.3 or greater]))
@ -244,6 +238,28 @@ if test x$have_xinerama = xno; then
AC_MSG_ERROR([Xinerama extension was not found])
fi
SHAPE_LIBS=
found_shape=no
AC_CHECK_LIB(Xext, XShapeQueryExtension,
[AC_CHECK_HEADER(X11/extensions/shape.h,
SHAPE_LIBS=-lXext found_shape=yes)],
, $ALL_X_LIBS)
if test x$enable_shape = xno; then
found_shape=no
fi
if test x$enable_shape = xyes; then
if test "$found_shape" = "no"; then
AC_MSG_ERROR([--enable-shape forced and Shape not found])
exit 1
fi
fi
if test "x$found_shape" = "xyes"; then
AC_DEFINE(HAVE_SHAPE, , [Have the shape extension library])
fi
found_xkb=no
AC_CHECK_LIB(X11, XkbQueryExtension,
[AC_CHECK_HEADER(X11/XKBlib.h,
@ -261,13 +277,37 @@ AC_CHECK_LIB(Xrandr, XRRUpdateConfiguration,
[AC_CHECK_HEADER(X11/extensions/Xrandr.h,
RANDR_LIBS=-lXrandr found_randr=yes,,
[#include <X11/Xlib.h>])],
, -lXext $ALL_X_LIBS)
, -lXrender -lXext $ALL_X_LIBS)
if test "x$found_randr" = "xyes"; then
AC_DEFINE(HAVE_RANDR, , [Have the Xrandr extension library])
fi
MUTTER_LIBS="$MUTTER_LIBS $RANDR_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm"
XSYNC_LIBS=
found_xsync=no
AC_CHECK_LIB(Xext, XSyncQueryExtension,
[AC_CHECK_HEADER(X11/extensions/sync.h,
found_xsync=yes,,
[#include <X11/Xlib.h>])],
, $ALL_X_LIBS)
if test x$enable_xsync = xno; then
found_xsync=no
fi
if test x$enable_xsync = xyes; then
if test "$found_xsync" = "no"; then
AC_MSG_ERROR([--enable-xsync forced and XSync not found])
exit 1
fi
fi
if test "x$found_xsync" = "xyes"; then
XSYNC_LIBS=-lXext
AC_DEFINE(HAVE_XSYNC, , [Have the Xsync extension library])
fi
MUTTER_LIBS="$MUTTER_LIBS $XSYNC_LIBS $RANDR_LIBS $SHAPE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm"
found_sm=no
case "$MUTTER_LIBS" in
@ -324,11 +364,6 @@ fi
GTK_DOC_CHECK([1.15], [--flavour no-tmpl])
AC_CHECK_DECL([GL_EXT_x11_sync_object],
[],
[AC_MSG_ERROR([GL_EXT_x11_sync_object definition not found, please update your GL headers])],
[#include <GL/glx.h>])
#### Warnings (last since -Werror can disturb other tests)
# Stay command-line compatible with the gnome-common configure option. Here
@ -403,6 +438,7 @@ doc/reference/Makefile
doc/reference/meta-docs.sgml
src/Makefile
src/libmutter.pc
src/mutter-plugins.pc
src/compositor/plugins/Makefile
po/Makefile.in
])
@ -429,6 +465,9 @@ mutter-$VERSION
libcanberra: ${have_libcanberra}
Introspection: ${found_introspection}
Session management: ${found_sm}
Shape extension: ${found_shape}
Xsync: ${found_xsync}
Xcursor: ${have_xcursor}
"

View File

@ -1,3 +0,0 @@
defaultcursordir = $(datadir)/mutter/cursors
dist_defaultcursor_DATA = left_ptr.png

View File

@ -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

View File

@ -79,6 +79,8 @@ IGNORE_HFILES= \
iconcache.h \
inlinepixbufs.h \
keybindings-private.h \
menu.h \
metaaccellabel.h \
meta-background-actor-private.h \
meta-background-group-private.h \
meta-module.h \

View File

@ -96,6 +96,8 @@ meta_compositor_hide_window
meta_compositor_switch_workspace
meta_compositor_maximize_window
meta_compositor_unmaximize_window
meta_compositor_window_mapped
meta_compositor_window_unmapped
meta_compositor_sync_window_geometry
meta_compositor_set_updates_frozen
meta_compositor_queue_frame_drawn

View File

@ -21,6 +21,7 @@ environment.</description>
-->
<mailing-list rdf:resource="http://mail.gnome.org/mailman/listinfo/gnome-shell-list" />
<download-page rdf:resource="http://download.gnome.org/sources/mutter/" />
<download-page rdf:resource="http://download.gnome.org/sources/mutter-wayland/" />
<bug-database rdf:resource="http://bugzilla.gnome.org/browse.cgi?product=mutter" />
<category rdf:resource="http://api.gnome.org/doap-extensions#desktop" />

View File

@ -3,7 +3,6 @@
src/50-mutter-navigation.xml.in
src/50-mutter-system.xml.in
src/50-mutter-windows.xml.in
src/backends/meta-monitor-manager.c
src/compositor/compositor.c
src/compositor/meta-background.c
src/core/bell.c
@ -13,18 +12,21 @@ src/core/display.c
src/core/errors.c
src/core/keybindings.c
src/core/main.c
src/core/monitor.c
src/core/mutter.c
src/core/prefs.c
src/core/screen.c
src/core/session.c
src/core/util.c
src/core/window.c
src/core/window-props.c
src/core/xprops.c
src/mutter.desktop.in
src/mutter-wm.desktop.in
src/org.gnome.mutter.gschema.xml.in
src/org.gnome.mutter.wayland.gschema.xml.in
src/ui/frames.c
src/ui/menu.c
src/ui/metaaccellabel.c
src/ui/resizepopup.c
src/ui/theme.c
src/ui/theme-parser.c
src/x11/session.c
src/x11/window-props.c
src/x11/xprops.c

View File

@ -1,2 +1,2 @@
src/metacity.schemas.in
src/mutter-wayland.desktop.in

471
po/ar.po

File diff suppressed because it is too large Load Diff

527
po/ca.po

File diff suppressed because it is too large Load Diff

534
po/cs.po

File diff suppressed because it is too large Load Diff

517
po/da.po

File diff suppressed because it is too large Load Diff

3551
po/el.po

File diff suppressed because it is too large Load Diff

952
po/es.po

File diff suppressed because it is too large Load Diff

787
po/eu.po

File diff suppressed because it is too large Load Diff

683
po/fr.po

File diff suppressed because it is too large Load Diff

898
po/gl.po

File diff suppressed because it is too large Load Diff

914
po/he.po

File diff suppressed because it is too large Load Diff

524
po/hu.po

File diff suppressed because it is too large Load Diff

951
po/id.po

File diff suppressed because it is too large Load Diff

515
po/it.po

File diff suppressed because it is too large Load Diff

2012
po/kn.po

File diff suppressed because it is too large Load Diff

531
po/ko.po

File diff suppressed because it is too large Load Diff

523
po/lt.po

File diff suppressed because it is too large Load Diff

528
po/lv.po

File diff suppressed because it is too large Load Diff

519
po/nb.po

File diff suppressed because it is too large Load Diff

524
po/pa.po

File diff suppressed because it is too large Load Diff

519
po/pl.po

File diff suppressed because it is too large Load Diff

531
po/pt.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

992
po/ru.po

File diff suppressed because it is too large Load Diff

522
po/sl.po

File diff suppressed because it is too large Load Diff

549
po/sr.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1132
po/uk.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -17,9 +17,6 @@
<KeyListEntry name="move-to-workspace-4"
_description="Move window to workspace 4" />
<KeyListEntry name="move-to-workspace-last"
_description="Move window to last workspace" />
<KeyListEntry name="move-to-workspace-left"
_description="Move window one workspace to the left" />
@ -32,18 +29,6 @@
<KeyListEntry name="move-to-workspace-down"
_description="Move window one workspace down" />
<KeyListEntry name="move-to-monitor-left"
_description="Move window one monitor to the left" />
<KeyListEntry name="move-to-monitor-right"
_description="Move window one monitor to the right" />
<KeyListEntry name="move-to-monitor-up"
_description="Move window one monitor up" />
<KeyListEntry name="move-to-monitor-down"
_description="Move window one monitor down" />
<KeyListEntry name="switch-applications"
_description="Switch applications"/>
@ -80,9 +65,6 @@
<KeyListEntry name="switch-to-workspace-4"
_description="Switch to workspace 4" />
<KeyListEntry name="switch-to-workspace-last"
_description="Switch to last workspace" />
<KeyListEntry name="switch-to-workspace-left"
_description="Move to workspace left" />

View File

@ -6,14 +6,11 @@ lib_LTLIBRARIES = libmutter.la
SUBDIRS=compositor/plugins
INCLUDES= \
-DCLUTTER_ENABLE_COMPOSITOR_API \
-DCLUTTER_ENABLE_EXPERIMENTAL_API \
-DCOGL_ENABLE_EXPERIMENTAL_API \
-DCOGL_ENABLE_EXPERIMENTAL_2_0_API \
$(MUTTER_CFLAGS) \
$(MUTTER_NATIVE_BACKEND_CFLAGS) \
-I$(srcdir) \
-I$(srcdir)/backends \
-I$(srcdir)/core \
-I$(srcdir)/ui \
-I$(srcdir)/compositor \
@ -30,58 +27,17 @@ INCLUDES= \
-DMUTTER_PLUGIN_API_VERSION=$(MUTTER_PLUGIN_API_VERSION) \
-DMUTTER_PKGLIBDIR=\"$(pkglibdir)\" \
-DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\" \
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \
-DXWAYLAND_PATH='"@XWAYLAND_PATH@"'
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\"
mutter_built_sources = \
$(dbus_idle_built_sources) \
$(dbus_display_config_built_sources) \
$(dbus_login1_built_sources) \
mutter-enum-types.h \
mutter-enum-types.c \
gtk-shell-protocol.c \
gtk-shell-server-protocol.h \
xdg-shell-protocol.c \
xdg-shell-server-protocol.h
wayland_protocols = \
wayland/protocol/gtk-shell.xml \
wayland/protocol/xdg-shell.xml
$(dbus_idle_built_sources) \
$(dbus_xrandr_built_sources) \
mutter-enum-types.h \
mutter-enum-types.c
libmutter_la_SOURCES = \
backends/meta-backend.c \
backends/meta-backend.h \
backends/meta-backend-private.h \
backends/meta-cursor.c \
backends/meta-cursor.h \
backends/meta-cursor-private.h \
backends/meta-cursor-tracker.c \
backends/meta-cursor-tracker-private.h \
backends/meta-cursor-renderer.c \
backends/meta-cursor-renderer.h \
backends/meta-display-config-shared.h \
backends/meta-idle-monitor.c \
backends/meta-idle-monitor-private.h \
backends/meta-idle-monitor-dbus.c \
backends/meta-idle-monitor-dbus.h \
backends/meta-monitor-config.c \
backends/meta-monitor-config.h \
backends/meta-monitor-manager.c \
backends/meta-monitor-manager.h \
backends/meta-monitor-manager-dummy.c \
backends/meta-monitor-manager-dummy.h \
backends/edid-parse.c \
backends/edid.h \
backends/x11/meta-backend-x11.c \
backends/x11/meta-backend-x11.h \
backends/x11/meta-cursor-renderer-x11.c \
backends/x11/meta-cursor-renderer-x11.h \
backends/x11/meta-idle-monitor-xsync.c \
backends/x11/meta-idle-monitor-xsync.h \
backends/x11/meta-monitor-manager-xrandr.c \
backends/x11/meta-monitor-manager-xrandr.h \
core/meta-accel-parse.c \
core/meta-accel-parse.h \
core/async-getprop.c \
core/async-getprop.h \
core/barrier.c \
meta/barrier.h \
core/bell.c \
@ -109,17 +65,6 @@ libmutter_la_SOURCES = \
compositor/meta-shadow-factory.c \
compositor/meta-shadow-factory-private.h \
compositor/meta-shaped-texture.c \
compositor/meta-shaped-texture-private.h \
compositor/meta-surface-actor.c \
compositor/meta-surface-actor.h \
compositor/meta-surface-actor-x11.c \
compositor/meta-surface-actor-x11.h \
compositor/meta-surface-actor-wayland.c \
compositor/meta-surface-actor-wayland.h \
compositor/meta-stage.h \
compositor/meta-stage.c \
compositor/meta-sync-ring.c \
compositor/meta-sync-ring.h \
compositor/meta-texture-rectangle.c \
compositor/meta-texture-rectangle.h \
compositor/meta-texture-tower.c \
@ -140,6 +85,7 @@ libmutter_la_SOURCES = \
meta/meta-shadow-factory.h \
meta/meta-window-actor.h \
meta/compositor-mutter.h \
core/above-tab-keycode.c \
core/constraints.c \
core/constraints.h \
core/core.c \
@ -147,19 +93,38 @@ libmutter_la_SOURCES = \
core/display.c \
core/display-private.h \
meta/display.h \
ui/draw-workspace.c \
ui/draw-workspace.h \
core/edge-resistance.c \
core/edge-resistance.h \
core/events.c \
core/events.h \
core/edid-parse.c \
core/edid.h \
core/errors.c \
meta/errors.h \
core/frame.c \
core/frame.h \
ui/gradient.c \
meta/gradient.h \
core/group-private.h \
core/group-props.c \
core/group-props.h \
core/group.c \
meta/group.h \
core/iconcache.c \
core/iconcache.h \
core/keybindings.c \
core/keybindings-private.h \
core/main.c \
core/meta-cursor-tracker.c \
core/meta-cursor-tracker-private.h \
core/meta-idle-monitor.c \
core/meta-idle-monitor-private.h \
core/meta-xrandr-shared.h \
core/monitor.c \
core/monitor-config.c \
core/monitor-private.h \
core/monitor-xrandr.c \
core/mutter-Xatomtype.h \
core/place.c \
core/place.h \
core/prefs.c \
@ -168,93 +133,49 @@ libmutter_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 \
core/stack-tracker.h \
core/util.c \
meta/util.h \
core/util-private.h \
core/window-props.c \
core/window-props.h \
core/window.c \
core/window-private.h \
meta/window.h \
core/workspace.c \
core/workspace-private.h \
core/xprops.c \
core/xprops.h \
meta/common.h \
core/core.h \
ui/ui.h \
ui/frames.c \
ui/frames.h \
ui/menu.c \
ui/menu.h \
ui/metaaccellabel.c \
ui/metaaccellabel.h \
ui/resizepopup.c \
ui/resizepopup.h \
ui/tabpopup.c \
ui/tabpopup.h \
ui/tile-preview.c \
ui/tile-preview.h \
ui/theme-parser.c \
ui/theme.c \
meta/theme.h \
ui/theme-private.h \
ui/ui.c \
x11/iconcache.c \
x11/iconcache.h \
x11/async-getprop.c \
x11/async-getprop.h \
x11/group-private.h \
x11/group-props.c \
x11/group-props.h \
x11/group.c \
meta/group.h \
x11/session.c \
x11/session.h \
x11/window-props.c \
x11/window-props.h \
x11/window-x11.c \
x11/window-x11.h \
x11/window-x11-private.h \
x11/xprops.c \
x11/xprops.h \
x11/mutter-Xatomtype.h \
wayland/meta-wayland.c \
wayland/meta-wayland.h \
wayland/meta-wayland-private.h \
wayland/meta-xwayland.c \
wayland/meta-xwayland.h \
wayland/meta-xwayland-private.h \
wayland/meta-wayland-data-device.c \
wayland/meta-wayland-data-device.h \
wayland/meta-wayland-keyboard.c \
wayland/meta-wayland-keyboard.h \
wayland/meta-wayland-pointer.c \
wayland/meta-wayland-pointer.h \
wayland/meta-wayland-seat.c \
wayland/meta-wayland-seat.h \
wayland/meta-wayland-surface.c \
wayland/meta-wayland-surface.h \
wayland/meta-wayland-types.h \
wayland/meta-wayland-versions.h \
wayland/meta-wayland-outputs.c \
wayland/meta-wayland-outputs.h \
wayland/window-wayland.c \
wayland/window-wayland.h
if HAVE_NATIVE_BACKEND
libmutter_la_SOURCES += \
backends/native/meta-backend-native.c \
backends/native/meta-backend-native.h \
backends/native/meta-cursor-renderer-native.c \
backends/native/meta-cursor-renderer-native.h \
backends/native/meta-idle-monitor-native.c \
backends/native/meta-idle-monitor-native.h \
backends/native/meta-monitor-manager-kms.c \
backends/native/meta-monitor-manager-kms.h \
backends/native/meta-launcher.c \
backends/native/meta-launcher.h \
backends/native/dbus-utils.c \
backends/native/dbus-utils.h
endif
ui/ui.c
nodist_libmutter_la_SOURCES = \
$(mutter_built_sources)
libmutter_la_LDFLAGS = -no-undefined
libmutter_la_LIBADD = $(MUTTER_LIBS) $(MUTTER_NATIVE_BACKEND_LIBS)
libmutter_la_LIBADD = $(MUTTER_LIBS)
# Headers installed for plugins; introspected information will
# be extracted into Mutter-<version>.gir
@ -338,7 +259,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
@ -353,6 +274,11 @@ desktopfiles_in_files=mutter.desktop.in
desktopfiles_files=$(desktopfiles_in_files:.desktop.in=.desktop)
desktopfiles_DATA = $(desktopfiles_files)
wmpropertiesdir=$(datadir)/gnome/wm-properties
wmproperties_in_files=mutter-wm.desktop.in
wmproperties_files=$(wmproperties_in_files:.desktop.in=.desktop)
wmproperties_DATA = $(wmproperties_files)
xmldir = @GNOME_KEYBINDINGS_KEYSDIR@
xml_in_files = \
50-mutter-navigation.xml.in \
@ -360,9 +286,7 @@ xml_in_files = \
50-mutter-windows.xml.in
xml_DATA = $(xml_in_files:.xml.in=.xml)
dbus_idle_built_sources = meta-dbus-idle-monitor.c meta-dbus-idle-monitor.h
gsettings_SCHEMAS = org.gnome.mutter.gschema.xml org.gnome.mutter.wayland.gschema.xml
gsettings_SCHEMAS = org.gnome.mutter.gschema.xml
@INTLTOOL_XML_NOMERGE_RULE@
@GSETTINGS_RULES@
@ -373,7 +297,6 @@ CLEANFILES = \
mutter.desktop \
mutter-wm.desktop \
org.gnome.mutter.gschema.xml \
org.gnome.mutter.wayland.gschema.xml \
$(xml_DATA) \
$(mutter_built_sources) \
$(typelib_DATA) \
@ -381,7 +304,7 @@ CLEANFILES = \
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libmutter.pc
pkgconfig_DATA = libmutter.pc mutter-plugins.pc
EXTRA_DIST=$(desktopfiles_files) \
$(wmproperties_files) \
@ -389,16 +312,14 @@ 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 \
idle-monitor.xml \
xrandr.xml \
mutter-schemas.convert \
libmutter.pc.in \
mutter-plugins.pc.in \
mutter-enum-types.h.in \
mutter-enum-types.c.in \
org.freedesktop.login1.xml \
org.gnome.Mutter.DisplayConfig.xml \
org.gnome.Mutter.IdleMonitor.xml
mutter-enum-types.c.in
BUILT_SOURCES = $(mutter_built_sources)
MUTTER_STAMP_FILES = stamp-mutter-enum-types.h
@ -423,33 +344,21 @@ mutter-enum-types.c: stamp-mutter-enum-types.h mutter-enum-types.c.in
cp xgen-tetc mutter-enum-types.c && \
rm -f xgen-tetc
dbus_display_config_built_sources = meta-dbus-display-config.c meta-dbus-display-config.h
dbus_xrandr_built_sources = meta-dbus-xrandr.c meta-dbus-xrandr.h
$(dbus_display_config_built_sources) : Makefile.am org.gnome.Mutter.DisplayConfig.xml
$(dbus_xrandr_built_sources) : Makefile.am xrandr.xml
$(AM_V_GEN)gdbus-codegen \
--interface-prefix org.gnome.Mutter \
--c-namespace MetaDBus \
--generate-c-code meta-dbus-display-config \
$(srcdir)/org.gnome.Mutter.DisplayConfig.xml
--generate-c-code meta-dbus-xrandr \
$(srcdir)/xrandr.xml
$(dbus_idle_built_sources) : Makefile.am org.gnome.Mutter.IdleMonitor.xml
dbus_idle_built_sources = meta-dbus-idle-monitor.c meta-dbus-idle-monitor.h
$(dbus_idle_built_sources) : Makefile.am idle-monitor.xml
$(AM_V_GEN)gdbus-codegen \
--interface-prefix org.gnome.Mutter \
--c-namespace MetaDBus \
--generate-c-code meta-dbus-idle-monitor \
--c-generate-object-manager \
$(srcdir)/org.gnome.Mutter.IdleMonitor.xml
dbus_login1_built_sources = meta-dbus-login1.c meta-dbus-login1.h
$(dbus_login1_built_sources) : Makefile.am org.freedesktop.login1.xml
$(AM_V_GEN)gdbus-codegen \
--interface-prefix org.freedesktop.login1 \
--c-namespace Login1 \
--generate-c-code meta-dbus-login1 \
$(srcdir)/org.freedesktop.login1.xml
%-protocol.c : $(srcdir)/wayland/protocol/%.xml
$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
%-server-protocol.h : $(srcdir)/wayland/protocol/%.xml
$(AM_V_GEN)$(WAYLAND_SCANNER) server-header < $< > $@
$(srcdir)/idle-monitor.xml

View File

@ -1,71 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#ifndef META_BACKEND_PRIVATE_H
#define META_BACKEND_PRIVATE_H
#include <glib-object.h>
#include "meta-backend.h"
#define META_TYPE_BACKEND (meta_backend_get_type ())
#define META_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BACKEND, MetaBackend))
#define META_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_BACKEND, MetaBackendClass))
#define META_IS_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_BACKEND))
#define META_IS_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_BACKEND))
#define META_BACKEND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_BACKEND, MetaBackendClass))
struct _MetaBackend
{
GObject parent;
MetaIdleMonitor *device_monitors[256];
int device_id_max;
};
struct _MetaBackendClass
{
GObjectClass parent_class;
void (* post_init) (MetaBackend *backend);
MetaIdleMonitor * (* create_idle_monitor) (MetaBackend *backend,
int device_id);
MetaMonitorManager * (* create_monitor_manager) (MetaBackend *backend);
MetaCursorRenderer * (* create_cursor_renderer) (MetaBackend *backend);
gboolean (* grab_device) (MetaBackend *backend,
int device_id,
uint32_t timestamp);
gboolean (* ungrab_device) (MetaBackend *backend,
int device_id,
uint32_t timestamp);
void (* warp_pointer) (MetaBackend *backend,
int x,
int y);
};
#endif /* META_BACKEND_PRIVATE_H */

View File

@ -1,299 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#include "config.h"
#include "meta-backend.h"
#include "meta-backend-private.h"
#include <clutter/clutter.h>
#include "backends/x11/meta-backend-x11.h"
#ifdef HAVE_NATIVE_BACKEND
#include "backends/native/meta-backend-native.h"
#endif
static MetaBackend *_backend;
MetaBackend *
meta_get_backend (void)
{
return _backend;
}
struct _MetaBackendPrivate
{
MetaMonitorManager *monitor_manager;
MetaCursorRenderer *cursor_renderer;
};
typedef struct _MetaBackendPrivate MetaBackendPrivate;
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaBackend, meta_backend, G_TYPE_OBJECT);
static void
meta_backend_finalize (GObject *object)
{
MetaBackend *backend = META_BACKEND (object);
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
int i;
g_clear_object (&priv->monitor_manager);
for (i = 0; i <= backend->device_id_max; i++)
{
if (backend->device_monitors[i])
g_object_unref (backend->device_monitors[i]);
}
G_OBJECT_CLASS (meta_backend_parent_class)->finalize (object);
}
static void
meta_backend_real_post_init (MetaBackend *backend)
{
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
priv->monitor_manager = META_BACKEND_GET_CLASS (backend)->create_monitor_manager (backend);
priv->cursor_renderer = META_BACKEND_GET_CLASS (backend)->create_cursor_renderer (backend);
}
static MetaCursorRenderer *
meta_backend_real_create_cursor_renderer (MetaBackend *backend)
{
return meta_cursor_renderer_new ();
}
static gboolean
meta_backend_real_grab_device (MetaBackend *backend,
int device_id,
uint32_t timestamp)
{
/* Do nothing */
return TRUE;
}
static gboolean
meta_backend_real_ungrab_device (MetaBackend *backend,
int device_id,
uint32_t timestamp)
{
/* Do nothing */
return TRUE;
}
static void
meta_backend_real_warp_pointer (MetaBackend *backend,
int x,
int y)
{
/* Do nothing */
}
static void
meta_backend_class_init (MetaBackendClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_backend_finalize;
klass->post_init = meta_backend_real_post_init;
klass->create_cursor_renderer = meta_backend_real_create_cursor_renderer;
klass->grab_device = meta_backend_real_grab_device;
klass->ungrab_device = meta_backend_real_ungrab_device;
klass->warp_pointer = meta_backend_real_warp_pointer;
}
static void
meta_backend_init (MetaBackend *backend)
{
_backend = backend;
}
/* FIXME -- destroy device monitors at some point */
G_GNUC_UNUSED static void
destroy_device_monitor (MetaBackend *backend,
int device_id)
{
g_clear_object (&backend->device_monitors[device_id]);
if (device_id == backend->device_id_max)
backend->device_id_max--;
}
static MetaIdleMonitor *
meta_backend_create_idle_monitor (MetaBackend *backend,
int device_id)
{
return META_BACKEND_GET_CLASS (backend)->create_idle_monitor (backend, device_id);
}
static void
meta_backend_post_init (MetaBackend *backend)
{
META_BACKEND_GET_CLASS (backend)->post_init (backend);
}
MetaIdleMonitor *
meta_backend_get_idle_monitor (MetaBackend *backend,
int device_id)
{
g_return_val_if_fail (device_id >= 0 && device_id < 256, NULL);
if (!backend->device_monitors[device_id])
{
backend->device_monitors[device_id] = meta_backend_create_idle_monitor (backend, device_id);
backend->device_id_max = MAX (backend->device_id_max, device_id);
}
return backend->device_monitors[device_id];
}
MetaMonitorManager *
meta_backend_get_monitor_manager (MetaBackend *backend)
{
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
return priv->monitor_manager;
}
MetaCursorRenderer *
meta_backend_get_cursor_renderer (MetaBackend *backend)
{
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
return priv->cursor_renderer;
}
gboolean
meta_backend_grab_device (MetaBackend *backend,
int device_id,
uint32_t timestamp)
{
return META_BACKEND_GET_CLASS (backend)->grab_device (backend, device_id, timestamp);
}
gboolean
meta_backend_ungrab_device (MetaBackend *backend,
int device_id,
uint32_t timestamp)
{
return META_BACKEND_GET_CLASS (backend)->ungrab_device (backend, device_id, timestamp);
}
void
meta_backend_warp_pointer (MetaBackend *backend,
int x,
int y)
{
META_BACKEND_GET_CLASS (backend)->warp_pointer (backend, x, y);
}
static GType
get_backend_type (void)
{
#if defined(CLUTTER_WINDOWING_X11)
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_X11))
return META_TYPE_BACKEND_X11;
#endif
#if defined(CLUTTER_WINDOWING_EGL) && defined(HAVE_NATIVE_BACKEND)
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
return META_TYPE_BACKEND_NATIVE;
#endif
g_assert_not_reached ();
}
static void
meta_create_backend (void)
{
/* meta_backend_init() above install the backend globally so
* so meta_get_backend() works even during initialization. */
g_object_new (get_backend_type (), NULL);
}
/* Mutter is responsible for pulling events off the X queue, so Clutter
* doesn't need (and shouldn't) run its normal event source which polls
* the X fd, but we do have to deal with dispatching events that accumulate
* in the clutter queue. This happens, for example, when clutter generate
* enter/leave events on mouse motion - several events are queued in the
* clutter queue but only one dispatched. It could also happen because of
* explicit calls to clutter_event_put(). We add a very simple custom
* event loop source which is simply responsible for pulling events off
* of the queue and dispatching them before we block for new events.
*/
static gboolean
event_prepare (GSource *source,
gint *timeout_)
{
*timeout_ = -1;
return clutter_events_pending ();
}
static gboolean
event_check (GSource *source)
{
return clutter_events_pending ();
}
static gboolean
event_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
ClutterEvent *event = clutter_event_get ();
if (event)
{
clutter_do_event (event);
clutter_event_free (event);
}
return TRUE;
}
static GSourceFuncs event_funcs = {
event_prepare,
event_check,
event_dispatch
};
void
meta_clutter_init (void)
{
GSource *source;
meta_create_backend ();
if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
g_error ("Unable to initialize Clutter.\n");
source = g_source_new (&event_funcs, sizeof (GSource));
g_source_attach (source, NULL);
g_source_unref (source);
meta_backend_post_init (_backend);
}

View File

@ -1,59 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#ifndef META_BACKEND_H
#define META_BACKEND_H
#include <glib-object.h>
#include <meta/meta-idle-monitor.h>
#include "meta-monitor-manager.h"
#include "meta-cursor-renderer.h"
typedef struct _MetaBackend MetaBackend;
typedef struct _MetaBackendClass MetaBackendClass;
GType meta_backend_get_type (void);
MetaBackend * meta_get_backend (void);
MetaIdleMonitor * meta_backend_get_idle_monitor (MetaBackend *backend,
int device_id);
MetaMonitorManager * meta_backend_get_monitor_manager (MetaBackend *backend);
MetaCursorRenderer * meta_backend_get_cursor_renderer (MetaBackend *backend);
gboolean meta_backend_grab_device (MetaBackend *backend,
int device_id,
uint32_t timestamp);
gboolean meta_backend_ungrab_device (MetaBackend *backend,
int device_id,
uint32_t timestamp);
void meta_backend_warp_pointer (MetaBackend *backend,
int x,
int y);
void meta_clutter_init (void);
#endif /* META_BACKEND_H */

View File

@ -1,51 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Giovanni Campagna <gcampagn@redhat.com>
*/
#ifndef META_CURSOR_PRIVATE_H
#define META_CURSOR_PRIVATE_H
#include "meta-cursor.h"
#include <cogl/cogl.h>
#include <gbm.h>
typedef struct {
CoglTexture2D *texture;
struct gbm_bo *bo;
int hot_x, hot_y;
} MetaCursorImage;
struct _MetaCursorReference {
int ref_count;
MetaCursor cursor;
MetaCursorImage image;
};
CoglTexture *meta_cursor_reference_get_cogl_texture (MetaCursorReference *cursor,
int *hot_x,
int *hot_y);
struct gbm_bo *meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
int *hot_x,
int *hot_y);
#endif /* META_CURSOR_PRIVATE_H */

View File

@ -1,172 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#include "config.h"
#include "meta-cursor-renderer.h"
#include "meta-cursor-private.h"
#include <cogl/cogl.h>
#include <cogl/cogl-wayland-server.h>
#include <clutter/clutter.h>
#include "meta-stage.h"
#include "wayland/meta-wayland-private.h"
struct _MetaCursorRendererPrivate
{
int current_x, current_y;
MetaRectangle current_rect;
MetaCursorReference *displayed_cursor;
gboolean handled_by_backend;
};
typedef struct _MetaCursorRendererPrivate MetaCursorRendererPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRenderer, meta_cursor_renderer, G_TYPE_OBJECT);
static void
queue_redraw (MetaCursorRenderer *renderer)
{
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
ClutterActor *stage = compositor->stage;
/* During early initialization, we can have no stage */
if (!stage)
return;
if (priv->handled_by_backend)
meta_stage_set_cursor (META_STAGE (stage), NULL, &priv->current_rect);
else
meta_stage_set_cursor (META_STAGE (stage), priv->displayed_cursor, &priv->current_rect);
}
static gboolean
meta_cursor_renderer_real_update_cursor (MetaCursorRenderer *renderer)
{
return FALSE;
}
static void
meta_cursor_renderer_class_init (MetaCursorRendererClass *klass)
{
klass->update_cursor = meta_cursor_renderer_real_update_cursor;
}
static void
meta_cursor_renderer_init (MetaCursorRenderer *renderer)
{
}
static void
update_cursor (MetaCursorRenderer *renderer)
{
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
gboolean handled_by_backend;
gboolean should_redraw = FALSE;
if (priv->displayed_cursor)
{
CoglTexture *texture;
int hot_x, hot_y;
texture = meta_cursor_reference_get_cogl_texture (priv->displayed_cursor, &hot_x, &hot_y);
priv->current_rect.x = priv->current_x - hot_x;
priv->current_rect.y = priv->current_y - hot_y;
priv->current_rect.width = cogl_texture_get_width (COGL_TEXTURE (texture));
priv->current_rect.height = cogl_texture_get_height (COGL_TEXTURE (texture));
}
else
{
priv->current_rect.x = 0;
priv->current_rect.y = 0;
priv->current_rect.width = 0;
priv->current_rect.height = 0;
}
handled_by_backend = META_CURSOR_RENDERER_GET_CLASS (renderer)->update_cursor (renderer);
if (handled_by_backend != priv->handled_by_backend)
{
priv->handled_by_backend = handled_by_backend;
should_redraw = TRUE;
}
if (!handled_by_backend)
should_redraw = TRUE;
if (should_redraw)
queue_redraw (renderer);
}
MetaCursorRenderer *
meta_cursor_renderer_new (void)
{
return g_object_new (META_TYPE_CURSOR_RENDERER, NULL);
}
void
meta_cursor_renderer_set_cursor (MetaCursorRenderer *renderer,
MetaCursorReference *cursor)
{
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
if (priv->displayed_cursor == cursor)
return;
priv->displayed_cursor = cursor;
update_cursor (renderer);
}
void
meta_cursor_renderer_set_position (MetaCursorRenderer *renderer,
int x, int y)
{
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
g_assert (meta_is_wayland_compositor ());
priv->current_x = x;
priv->current_y = y;
update_cursor (renderer);
}
MetaCursorReference *
meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer)
{
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
return priv->displayed_cursor;
}
const MetaRectangle *
meta_cursor_renderer_get_rect (MetaCursorRenderer *renderer)
{
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
return &priv->current_rect;
}

View File

@ -1,70 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#ifndef META_CURSOR_RENDERER_H
#define META_CURSOR_RENDERER_H
#include <glib-object.h>
#include <meta/screen.h>
#include "meta-cursor.h"
#include <gbm.h>
#define META_TYPE_CURSOR_RENDERER (meta_cursor_renderer_get_type ())
#define META_CURSOR_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CURSOR_RENDERER, MetaCursorRenderer))
#define META_CURSOR_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_CURSOR_RENDERER, MetaCursorRendererClass))
#define META_IS_CURSOR_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_CURSOR_RENDERER))
#define META_IS_CURSOR_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_CURSOR_RENDERER))
#define META_CURSOR_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_CURSOR_RENDERER, MetaCursorRendererClass))
typedef struct _MetaCursorRenderer MetaCursorRenderer;
typedef struct _MetaCursorRendererClass MetaCursorRendererClass;
struct _MetaCursorRenderer
{
GObject parent;
};
struct _MetaCursorRendererClass
{
GObjectClass parent_class;
gboolean (* update_cursor) (MetaCursorRenderer *renderer);
};
GType meta_cursor_renderer_get_type (void) G_GNUC_CONST;
MetaCursorRenderer * meta_cursor_renderer_new (void);
void meta_cursor_renderer_set_cursor (MetaCursorRenderer *renderer,
MetaCursorReference *cursor);
void meta_cursor_renderer_set_position (MetaCursorRenderer *renderer,
int x, int y);
MetaCursorReference * meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer);
const MetaRectangle * meta_cursor_renderer_get_rect (MetaCursorRenderer *renderer);
#endif /* META_CURSOR_RENDERER_H */

View File

@ -1,75 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Giovanni Campagna <gcampagn@redhat.com>
*/
#ifndef META_CURSOR_TRACKER_PRIVATE_H
#define META_CURSOR_TRACKER_PRIVATE_H
#include <meta/meta-cursor-tracker.h>
#include <wayland-server.h>
#include <gbm.h>
#include "meta-cursor.h"
#include "meta-cursor-renderer.h"
struct _MetaCursorTracker {
GObject parent_instance;
MetaScreen *screen;
MetaCursorRenderer *renderer;
gboolean is_showing;
MetaCursorReference *displayed_cursor;
/* Wayland clients can set a NULL buffer as their cursor
* explicitly, which means that we shouldn't display anything.
* So, we can't simply store a NULL in window_cursor to
* determine an unset window cursor; we need an extra boolean.
*/
gboolean has_window_cursor;
MetaCursorReference *window_cursor;
MetaCursorReference *root_cursor;
/* The cursor from the X11 server. */
MetaCursorReference *xfixes_cursor;
};
struct _MetaCursorTrackerClass {
GObjectClass parent_class;
};
gboolean meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
XEvent *xevent);
void meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
MetaCursorReference *cursor);
void meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker);
void meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
MetaCursorReference *cursor);
void meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
int new_x,
int new_y);
MetaCursorReference * meta_cursor_tracker_get_displayed_cursor (MetaCursorTracker *tracker);
#endif

View File

@ -1,478 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Giovanni Campagna <gcampagn@redhat.com>
*/
/**
* SECTION:cursor-tracker
* @title: MetaCursorTracker
* @short_description: Mutter cursor tracking helper. Originally only
* tracking the cursor image, now more of a "core
* pointer abstraction"
*/
#include <config.h>
#include <string.h>
#include <meta/main.h>
#include <meta/util.h>
#include <meta/errors.h>
#include <cogl/cogl.h>
#include <cogl/cogl-wayland-server.h>
#include <clutter/clutter.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include "meta-backend.h"
#include "meta-cursor-private.h"
#include "meta-cursor-tracker-private.h"
#include "screen-private.h"
#include "wayland/meta-wayland-private.h"
G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT);
enum {
CURSOR_CHANGED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
static MetaCursorReference *
get_displayed_cursor (MetaCursorTracker *tracker)
{
if (!tracker->is_showing)
return NULL;
if (tracker->screen->display->grab_op == META_GRAB_OP_NONE)
{
if (tracker->has_window_cursor)
return tracker->window_cursor;
}
return tracker->root_cursor;
}
static void
update_displayed_cursor (MetaCursorTracker *tracker)
{
meta_cursor_renderer_set_cursor (tracker->renderer, tracker->displayed_cursor);
}
static void
sync_cursor (MetaCursorTracker *tracker)
{
MetaCursorReference *displayed_cursor = get_displayed_cursor (tracker);
if (tracker->displayed_cursor == displayed_cursor)
return;
g_clear_pointer (&tracker->displayed_cursor, meta_cursor_reference_unref);
if (displayed_cursor)
tracker->displayed_cursor = meta_cursor_reference_ref (displayed_cursor);
update_displayed_cursor (tracker);
g_signal_emit (tracker, signals[CURSOR_CHANGED], 0);
}
static void
meta_cursor_tracker_init (MetaCursorTracker *self)
{
self->is_showing = TRUE;
}
static void
meta_cursor_tracker_finalize (GObject *object)
{
MetaCursorTracker *self = META_CURSOR_TRACKER (object);
if (self->displayed_cursor)
meta_cursor_reference_unref (self->displayed_cursor);
if (self->root_cursor)
meta_cursor_reference_unref (self->root_cursor);
G_OBJECT_CLASS (meta_cursor_tracker_parent_class)->finalize (object);
}
static void
meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_cursor_tracker_finalize;
signals[CURSOR_CHANGED] = g_signal_new ("cursor-changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 0);
}
static MetaCursorTracker *
make_wayland_cursor_tracker (MetaScreen *screen)
{
MetaBackend *backend = meta_get_backend ();
MetaWaylandCompositor *compositor;
MetaCursorTracker *self;
self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
self->screen = screen;
self->renderer = meta_backend_get_cursor_renderer (backend);
compositor = meta_wayland_compositor_get_default ();
compositor->seat->pointer.cursor_tracker = self;
meta_cursor_tracker_update_position (self, 0, 0);
return self;
}
static MetaCursorTracker *
make_x11_cursor_tracker (MetaScreen *screen)
{
MetaBackend *backend = meta_get_backend ();
MetaCursorTracker *self;
self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
self->screen = screen;
self->renderer = meta_backend_get_cursor_renderer (backend);
XFixesSelectCursorInput (screen->display->xdisplay,
screen->xroot,
XFixesDisplayCursorNotifyMask);
return self;
}
static MetaCursorTracker *
meta_cursor_tracker_new (MetaScreen *screen)
{
if (meta_is_wayland_compositor ())
return make_wayland_cursor_tracker (screen);
else
return make_x11_cursor_tracker (screen);
}
static MetaCursorTracker *_cursor_tracker;
/**
* meta_cursor_tracker_get_for_screen:
* @screen: the #MetaScreen
*
* Retrieves the cursor tracker object for @screen.
*
* Returns: (transfer none):
*/
MetaCursorTracker *
meta_cursor_tracker_get_for_screen (MetaScreen *screen)
{
if (!_cursor_tracker)
_cursor_tracker = meta_cursor_tracker_new (screen);
return _cursor_tracker;
}
static void
set_window_cursor (MetaCursorTracker *tracker,
gboolean has_cursor,
MetaCursorReference *cursor)
{
g_clear_pointer (&tracker->window_cursor, meta_cursor_reference_unref);
if (cursor)
tracker->window_cursor = meta_cursor_reference_ref (cursor);
tracker->has_window_cursor = has_cursor;
sync_cursor (tracker);
}
gboolean
meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
XEvent *xevent)
{
XFixesCursorNotifyEvent *notify_event;
if (meta_is_wayland_compositor ())
return FALSE;
if (xevent->xany.type != tracker->screen->display->xfixes_event_base + XFixesCursorNotify)
return FALSE;
notify_event = (XFixesCursorNotifyEvent *)xevent;
if (notify_event->subtype != XFixesDisplayCursorNotify)
return FALSE;
g_clear_pointer (&tracker->xfixes_cursor, meta_cursor_reference_unref);
return TRUE;
}
static MetaCursorReference *
meta_cursor_reference_take_texture (CoglTexture2D *texture,
int hot_x,
int hot_y)
{
MetaCursorReference *self;
self = g_slice_new0 (MetaCursorReference);
self->ref_count = 1;
self->image.texture = texture;
self->image.hot_x = hot_x;
self->image.hot_y = hot_y;
return self;
}
static void
ensure_xfixes_cursor (MetaCursorTracker *tracker)
{
XFixesCursorImage *cursor_image;
CoglTexture2D *sprite;
guint8 *cursor_data;
gboolean free_cursor_data;
CoglContext *ctx;
if (tracker->xfixes_cursor)
return;
cursor_image = XFixesGetCursorImage (tracker->screen->display->xdisplay);
if (!cursor_image)
return;
/* Like all X APIs, XFixesGetCursorImage() returns arrays of 32-bit
* quantities as arrays of long; we need to convert on 64 bit */
if (sizeof(long) == 4)
{
cursor_data = (guint8 *)cursor_image->pixels;
free_cursor_data = FALSE;
}
else
{
int i, j;
guint32 *cursor_words;
gulong *p;
guint32 *q;
cursor_words = g_new (guint32, cursor_image->width * cursor_image->height);
cursor_data = (guint8 *)cursor_words;
p = cursor_image->pixels;
q = cursor_words;
for (j = 0; j < cursor_image->height; j++)
for (i = 0; i < cursor_image->width; i++)
*(q++) = *(p++);
free_cursor_data = TRUE;
}
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
sprite = cogl_texture_2d_new_from_data (ctx,
cursor_image->width,
cursor_image->height,
CLUTTER_CAIRO_FORMAT_ARGB32,
cursor_image->width * 4, /* stride */
cursor_data,
NULL);
if (free_cursor_data)
g_free (cursor_data);
if (sprite != NULL)
{
MetaCursorReference *cursor = meta_cursor_reference_take_texture (sprite,
cursor_image->xhot,
cursor_image->yhot);
tracker->xfixes_cursor = cursor;
}
XFree (cursor_image);
}
/**
* meta_cursor_tracker_get_sprite:
*
* Returns: (transfer none):
*/
CoglTexture *
meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker)
{
MetaCursorReference *cursor;
g_return_val_if_fail (META_IS_CURSOR_TRACKER (tracker), NULL);
if (meta_is_wayland_compositor ())
{
cursor = tracker->displayed_cursor;
}
else
{
ensure_xfixes_cursor (tracker);
cursor = tracker->xfixes_cursor;
}
if (cursor)
return meta_cursor_reference_get_cogl_texture (cursor, NULL, NULL);
else
return NULL;
}
/**
* meta_cursor_tracker_get_hot:
* @tracker:
* @x: (out):
* @y: (out):
*
*/
void
meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
int *x,
int *y)
{
MetaCursorReference *cursor;
g_return_if_fail (META_IS_CURSOR_TRACKER (tracker));
if (meta_is_wayland_compositor ())
{
cursor = tracker->displayed_cursor;
}
else
{
ensure_xfixes_cursor (tracker);
cursor = tracker->xfixes_cursor;
}
if (cursor)
meta_cursor_reference_get_cogl_texture (cursor, x, y);
else
{
if (x)
*x = 0;
if (y)
*y = 0;
}
}
void
meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
MetaCursorReference *cursor)
{
set_window_cursor (tracker, TRUE, cursor);
}
void
meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker)
{
set_window_cursor (tracker, FALSE, NULL);
}
void
meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
MetaCursorReference *cursor)
{
g_clear_pointer (&tracker->root_cursor, meta_cursor_reference_unref);
if (cursor)
tracker->root_cursor = meta_cursor_reference_ref (cursor);
sync_cursor (tracker);
}
void
meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
int new_x,
int new_y)
{
g_assert (meta_is_wayland_compositor ());
meta_cursor_renderer_set_position (tracker->renderer, new_x, new_y);
}
static void
get_pointer_position_gdk (int *x,
int *y,
int *mods)
{
GdkDeviceManager *gmanager;
GdkDevice *gdevice;
GdkScreen *gscreen;
gmanager = gdk_display_get_device_manager (gdk_display_get_default ());
gdevice = gdk_x11_device_manager_lookup (gmanager, META_VIRTUAL_CORE_POINTER_ID);
gdk_device_get_position (gdevice, &gscreen, x, y);
if (mods)
gdk_device_get_state (gdevice,
gdk_screen_get_root_window (gscreen),
NULL, (GdkModifierType*)mods);
}
static void
get_pointer_position_clutter (int *x,
int *y,
int *mods)
{
ClutterDeviceManager *cmanager;
ClutterInputDevice *cdevice;
ClutterPoint point;
cmanager = clutter_device_manager_get_default ();
cdevice = clutter_device_manager_get_core_device (cmanager, CLUTTER_POINTER_DEVICE);
clutter_input_device_get_coords (cdevice, NULL, &point);
if (x)
*x = point.x;
if (y)
*y = point.y;
if (mods)
*mods = clutter_input_device_get_modifier_state (cdevice);
}
void
meta_cursor_tracker_get_pointer (MetaCursorTracker *tracker,
int *x,
int *y,
ClutterModifierType *mods)
{
/* We can't use the clutter interface when not running as a wayland compositor,
because we need to query the server, rather than using the last cached value.
OTOH, on wayland we can't use GDK, because that only sees the events
we forward to xwayland.
*/
if (meta_is_wayland_compositor ())
get_pointer_position_clutter (x, y, (int*)mods);
else
get_pointer_position_gdk (x, y, (int*)mods);
}
void
meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker,
gboolean visible)
{
if (visible == tracker->is_showing)
return;
tracker->is_showing = visible;
sync_cursor (tracker);
}
MetaCursorReference *
meta_cursor_tracker_get_displayed_cursor (MetaCursorTracker *tracker)
{
return tracker->displayed_cursor;
}

View File

@ -1,377 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Giovanni Campagna <gcampagn@redhat.com>
*/
#include "config.h"
#include "meta-cursor-private.h"
#include <meta/errors.h>
#include "display-private.h"
#include "screen-private.h"
#include "meta-backend.h"
#ifdef HAVE_NATIVE_BACKEND
#include "backends/native/meta-cursor-renderer-native.h"
#endif
#include <string.h>
#include <X11/cursorfont.h>
#include <X11/extensions/Xfixes.h>
#include <X11/Xcursor/Xcursor.h>
#include <cogl/cogl-wayland-server.h>
MetaCursorReference *
meta_cursor_reference_ref (MetaCursorReference *self)
{
g_assert (self->ref_count > 0);
self->ref_count++;
return self;
}
static void
meta_cursor_image_free (MetaCursorImage *image)
{
cogl_object_unref (image->texture);
if (image->bo)
gbm_bo_destroy (image->bo);
}
static void
meta_cursor_reference_free (MetaCursorReference *self)
{
meta_cursor_image_free (&self->image);
g_slice_free (MetaCursorReference, self);
}
void
meta_cursor_reference_unref (MetaCursorReference *self)
{
self->ref_count--;
if (self->ref_count == 0)
meta_cursor_reference_free (self);
}
static const char *
translate_meta_cursor (MetaCursor cursor)
{
switch (cursor)
{
case META_CURSOR_DEFAULT:
return "left_ptr";
case META_CURSOR_NORTH_RESIZE:
return "top_side";
case META_CURSOR_SOUTH_RESIZE:
return "bottom_side";
case META_CURSOR_WEST_RESIZE:
return "left_side";
case META_CURSOR_EAST_RESIZE:
return "right_side";
case META_CURSOR_SE_RESIZE:
return "bottom_right_corner";
case META_CURSOR_SW_RESIZE:
return "bottom_left_corner";
case META_CURSOR_NE_RESIZE:
return "top_right_corner";
case META_CURSOR_NW_RESIZE:
return "top_left_corner";
case META_CURSOR_MOVE_OR_RESIZE_WINDOW:
return "fleur";
case META_CURSOR_BUSY:
return "watch";
case META_CURSOR_DND_IN_DRAG:
return "dnd-none";
case META_CURSOR_DND_MOVE:
return "dnd-move";
case META_CURSOR_DND_COPY:
return "dnd-copy";
case META_CURSOR_DND_UNSUPPORTED_TARGET:
return "dnd-none";
case META_CURSOR_POINTING_HAND:
return "hand2";
case META_CURSOR_CROSSHAIR:
return "crosshair";
case META_CURSOR_IBEAM:
return "xterm";
default:
break;
}
g_assert_not_reached ();
}
Cursor
meta_cursor_create_x_cursor (Display *xdisplay,
MetaCursor cursor)
{
return XcursorLibraryLoadCursor (xdisplay, translate_meta_cursor (cursor));
}
static XcursorImage *
load_cursor_on_client (MetaCursor cursor)
{
return XcursorLibraryLoadImage (translate_meta_cursor (cursor),
meta_prefs_get_cursor_theme (),
meta_prefs_get_cursor_size ());
}
static void
meta_cursor_image_load_gbm_buffer (struct gbm_device *gbm,
MetaCursorImage *image,
uint8_t *pixels,
int width,
int height,
int rowstride,
uint32_t gbm_format)
{
if (width > 64 || height > 64)
{
meta_warning ("Invalid theme cursor size (must be at most 64x64)\n");
return;
}
if (gbm_device_is_format_supported (gbm, gbm_format,
GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE))
{
uint8_t buf[4 * 64 * 64];
int i;
image->bo = gbm_bo_create (gbm, 64, 64,
gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
memset (buf, 0, sizeof(buf));
for (i = 0; i < height; i++)
memcpy (buf + i * 4 * 64, pixels + i * rowstride, width * 4);
gbm_bo_write (image->bo, buf, 64 * 64 * 4);
}
else
meta_warning ("HW cursor for format %d not supported\n", gbm_format);
}
static struct gbm_device *
get_gbm_device (void)
{
#ifdef HAVE_NATIVE_BACKEND
MetaBackend *meta_backend = meta_get_backend ();
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend);
if (META_IS_CURSOR_RENDERER_NATIVE (renderer))
return meta_cursor_renderer_native_get_gbm_device (META_CURSOR_RENDERER_NATIVE (renderer));
#endif
return NULL;
}
static void
meta_cursor_image_load_from_xcursor_image (MetaCursorImage *image,
XcursorImage *xc_image)
{
int width, height, rowstride;
CoglPixelFormat cogl_format;
uint32_t gbm_format;
ClutterBackend *clutter_backend;
CoglContext *cogl_context;
struct gbm_device *gbm;
width = xc_image->width;
height = xc_image->height;
rowstride = width * 4;
gbm_format = GBM_FORMAT_ARGB8888;
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
cogl_format = COGL_PIXEL_FORMAT_BGRA_8888;
#else
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888;
#endif
image->hot_x = xc_image->xhot;
image->hot_y = xc_image->yhot;
clutter_backend = clutter_get_default_backend ();
cogl_context = clutter_backend_get_cogl_context (clutter_backend);
image->texture = cogl_texture_2d_new_from_data (cogl_context,
width, height,
cogl_format,
rowstride,
(uint8_t *) xc_image->pixels,
NULL);
gbm = get_gbm_device ();
if (gbm)
meta_cursor_image_load_gbm_buffer (gbm,
image,
(uint8_t *) xc_image->pixels,
width, height, rowstride,
gbm_format);
}
MetaCursorReference *
meta_cursor_reference_from_theme (MetaCursor cursor)
{
MetaCursorReference *self;
XcursorImage *image;
image = load_cursor_on_client (cursor);
if (!image)
return NULL;
self = g_slice_new0 (MetaCursorReference);
self->ref_count = 1;
self->cursor = cursor;
meta_cursor_image_load_from_xcursor_image (&self->image, image);
XcursorImageDestroy (image);
return self;
}
static void
meta_cursor_image_load_from_buffer (MetaCursorImage *image,
struct wl_resource *buffer,
int hot_x,
int hot_y)
{
struct gbm_device *gbm = get_gbm_device ();
ClutterBackend *backend;
CoglContext *cogl_context;
struct wl_shm_buffer *shm_buffer;
uint32_t gbm_format;
int width, height;
image->hot_x = hot_x;
image->hot_y = hot_y;
backend = clutter_get_default_backend ();
cogl_context = clutter_backend_get_cogl_context (backend);
image->texture = cogl_wayland_texture_2d_new_from_buffer (cogl_context, buffer, NULL);
width = cogl_texture_get_width (COGL_TEXTURE (image->texture));
height = cogl_texture_get_height (COGL_TEXTURE (image->texture));
shm_buffer = wl_shm_buffer_get (buffer);
if (shm_buffer)
{
if (gbm)
{
int rowstride = wl_shm_buffer_get_stride (shm_buffer);
switch (wl_shm_buffer_get_format (shm_buffer))
{
#if G_BYTE_ORDER == G_BIG_ENDIAN
case WL_SHM_FORMAT_ARGB8888:
gbm_format = GBM_FORMAT_ARGB8888;
break;
case WL_SHM_FORMAT_XRGB8888:
gbm_format = GBM_FORMAT_XRGB8888;
break;
#else
case WL_SHM_FORMAT_ARGB8888:
gbm_format = GBM_FORMAT_ARGB8888;
break;
case WL_SHM_FORMAT_XRGB8888:
gbm_format = GBM_FORMAT_XRGB8888;
break;
#endif
default:
g_warn_if_reached ();
gbm_format = GBM_FORMAT_ARGB8888;
}
meta_cursor_image_load_gbm_buffer (gbm,
image,
(uint8_t *) wl_shm_buffer_get_data (shm_buffer),
width, height, rowstride,
gbm_format);
}
}
else
{
/* HW cursors must be 64x64, but 64x64 is huge, and no cursor theme actually uses
that, so themed cursors must be padded with transparent pixels to fill the
overlay. This is trivial if we have CPU access to the data, but it's not
possible if the buffer is in GPU memory (and possibly tiled too), so if we
don't get the right size, we fallback to GL.
*/
if (width != 64 || height != 64)
{
meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n");
return;
}
if (gbm)
{
image->bo = gbm_bo_import (gbm, GBM_BO_IMPORT_WL_BUFFER,
buffer, GBM_BO_USE_CURSOR_64X64);
if (!image->bo)
meta_warning ("Importing HW cursor from wl_buffer failed\n");
}
}
}
MetaCursorReference *
meta_cursor_reference_from_buffer (struct wl_resource *buffer,
int hot_x,
int hot_y)
{
MetaCursorReference *self;
self = g_slice_new0 (MetaCursorReference);
self->ref_count = 1;
meta_cursor_image_load_from_buffer (&self->image, buffer, hot_x, hot_y);
return self;
}
CoglTexture *
meta_cursor_reference_get_cogl_texture (MetaCursorReference *cursor,
int *hot_x,
int *hot_y)
{
if (hot_x)
*hot_x = cursor->image.hot_x;
if (hot_y)
*hot_y = cursor->image.hot_y;
return COGL_TEXTURE (cursor->image.texture);
}
struct gbm_bo *
meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
int *hot_x,
int *hot_y)
{
if (hot_x)
*hot_x = cursor->image.hot_x;
if (hot_y)
*hot_y = cursor->image.hot_y;
return cursor->image.bo;
}
MetaCursor
meta_cursor_reference_get_meta_cursor (MetaCursorReference *cursor)
{
return cursor->cursor;
}

View File

@ -1,44 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Giovanni Campagna <gcampagn@redhat.com>
*/
#ifndef META_CURSOR_H
#define META_CURSOR_H
typedef struct _MetaCursorReference MetaCursorReference;
MetaCursorReference * meta_cursor_reference_ref (MetaCursorReference *cursor);
void meta_cursor_reference_unref (MetaCursorReference *cursor);
#include <meta/common.h>
#include <wayland-server.h>
MetaCursorReference * meta_cursor_reference_from_theme (MetaCursor cursor);
MetaCursorReference * meta_cursor_reference_from_buffer (struct wl_resource *buffer,
int hot_x,
int hot_y);
MetaCursor meta_cursor_reference_get_meta_cursor (MetaCursorReference *cursor);
Cursor meta_cursor_create_x_cursor (Display *xdisplay,
MetaCursor cursor);
#endif /* META_CURSOR_H */

View File

@ -1,289 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
*/
#include "config.h"
#include "meta-idle-monitor-dbus.h"
#include <meta/meta-idle-monitor.h>
#include "meta-dbus-idle-monitor.h"
#include <clutter/clutter.h>
#include <meta/util.h>
#include <meta/main.h> /* for meta_get_replace_current_wm () */
static gboolean
handle_get_idletime (MetaDBusIdleMonitor *skeleton,
GDBusMethodInvocation *invocation,
MetaIdleMonitor *monitor)
{
guint64 idletime;
idletime = meta_idle_monitor_get_idletime (monitor);
meta_dbus_idle_monitor_complete_get_idletime (skeleton, invocation, idletime);
return TRUE;
}
typedef struct {
MetaDBusIdleMonitor *dbus_monitor;
MetaIdleMonitor *monitor;
char *dbus_name;
guint watch_id;
guint name_watcher_id;
} DBusWatch;
static void
destroy_dbus_watch (gpointer data)
{
DBusWatch *watch = data;
g_object_unref (watch->dbus_monitor);
g_object_unref (watch->monitor);
g_free (watch->dbus_name);
g_bus_unwatch_name (watch->name_watcher_id);
g_slice_free (DBusWatch, watch);
}
static void
dbus_idle_callback (MetaIdleMonitor *monitor,
guint watch_id,
gpointer user_data)
{
DBusWatch *watch = user_data;
GDBusInterfaceSkeleton *skeleton = G_DBUS_INTERFACE_SKELETON (watch->dbus_monitor);
g_dbus_connection_emit_signal (g_dbus_interface_skeleton_get_connection (skeleton),
watch->dbus_name,
g_dbus_interface_skeleton_get_object_path (skeleton),
"org.gnome.Mutter.IdleMonitor",
"WatchFired",
g_variant_new ("(u)", watch_id),
NULL);
}
static void
name_vanished_callback (GDBusConnection *connection,
const char *name,
gpointer user_data)
{
DBusWatch *watch = user_data;
meta_idle_monitor_remove_watch (watch->monitor, watch->watch_id);
}
static DBusWatch *
make_dbus_watch (MetaDBusIdleMonitor *skeleton,
GDBusMethodInvocation *invocation,
MetaIdleMonitor *monitor)
{
DBusWatch *watch;
watch = g_slice_new (DBusWatch);
watch->dbus_monitor = g_object_ref (skeleton);
watch->monitor = g_object_ref (monitor);
watch->dbus_name = g_strdup (g_dbus_method_invocation_get_sender (invocation));
watch->name_watcher_id = g_bus_watch_name_on_connection (g_dbus_method_invocation_get_connection (invocation),
watch->dbus_name,
G_BUS_NAME_WATCHER_FLAGS_NONE,
NULL, /* appeared */
name_vanished_callback,
watch, NULL);
return watch;
}
static gboolean
handle_add_idle_watch (MetaDBusIdleMonitor *skeleton,
GDBusMethodInvocation *invocation,
guint64 interval,
MetaIdleMonitor *monitor)
{
DBusWatch *watch;
watch = make_dbus_watch (skeleton, invocation, monitor);
watch->watch_id = meta_idle_monitor_add_idle_watch (monitor, interval,
dbus_idle_callback, watch, destroy_dbus_watch);
meta_dbus_idle_monitor_complete_add_idle_watch (skeleton, invocation, watch->watch_id);
return TRUE;
}
static gboolean
handle_add_user_active_watch (MetaDBusIdleMonitor *skeleton,
GDBusMethodInvocation *invocation,
MetaIdleMonitor *monitor)
{
DBusWatch *watch;
watch = make_dbus_watch (skeleton, invocation, monitor);
watch->watch_id = meta_idle_monitor_add_user_active_watch (monitor,
dbus_idle_callback, watch,
destroy_dbus_watch);
meta_dbus_idle_monitor_complete_add_user_active_watch (skeleton, invocation, watch->watch_id);
return TRUE;
}
static gboolean
handle_remove_watch (MetaDBusIdleMonitor *skeleton,
GDBusMethodInvocation *invocation,
guint id,
MetaIdleMonitor *monitor)
{
meta_idle_monitor_remove_watch (monitor, id);
meta_dbus_idle_monitor_complete_remove_watch (skeleton, invocation);
return TRUE;
}
static void
create_monitor_skeleton (GDBusObjectManagerServer *manager,
MetaIdleMonitor *monitor,
const char *path)
{
MetaDBusIdleMonitor *skeleton;
MetaDBusObjectSkeleton *object;
skeleton = meta_dbus_idle_monitor_skeleton_new ();
g_signal_connect_object (skeleton, "handle-add-idle-watch",
G_CALLBACK (handle_add_idle_watch), monitor, 0);
g_signal_connect_object (skeleton, "handle-add-user-active-watch",
G_CALLBACK (handle_add_user_active_watch), monitor, 0);
g_signal_connect_object (skeleton, "handle-remove-watch",
G_CALLBACK (handle_remove_watch), monitor, 0);
g_signal_connect_object (skeleton, "handle-get-idletime",
G_CALLBACK (handle_get_idletime), monitor, 0);
object = meta_dbus_object_skeleton_new (path);
meta_dbus_object_skeleton_set_idle_monitor (object, skeleton);
g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (object));
g_object_unref (skeleton);
g_object_unref (object);
}
static void
on_device_added (ClutterDeviceManager *device_manager,
ClutterInputDevice *device,
GDBusObjectManagerServer *manager)
{
MetaIdleMonitor *monitor;
int device_id;
char *path;
device_id = clutter_input_device_get_device_id (device);
monitor = meta_idle_monitor_get_for_device (device_id);
path = g_strdup_printf ("/org/gnome/Mutter/IdleMonitor/Device%d", device_id);
create_monitor_skeleton (manager, monitor, path);
g_free (path);
}
static void
on_device_removed (ClutterDeviceManager *device_manager,
ClutterInputDevice *device,
GDBusObjectManagerServer *manager)
{
int device_id;
char *path;
device_id = clutter_input_device_get_device_id (device);
path = g_strdup_printf ("/org/gnome/Mutter/IdleMonitor/Device%d", device_id);
g_dbus_object_manager_server_unexport (manager, path);
g_free (path);
}
static void
on_bus_acquired (GDBusConnection *connection,
const char *name,
gpointer user_data)
{
GDBusObjectManagerServer *manager;
ClutterDeviceManager *device_manager;
MetaIdleMonitor *monitor;
GSList *devices, *iter;
char *path;
manager = g_dbus_object_manager_server_new ("/org/gnome/Mutter/IdleMonitor");
/* We never clear the core monitor, as that's supposed to cumulate idle times from
all devices */
monitor = meta_idle_monitor_get_core ();
path = g_strdup ("/org/gnome/Mutter/IdleMonitor/Core");
create_monitor_skeleton (manager, monitor, path);
g_free (path);
device_manager = clutter_device_manager_get_default ();
devices = clutter_device_manager_list_devices (device_manager);
for (iter = devices; iter; iter = iter->next)
on_device_added (device_manager, iter->data, manager);
g_slist_free (devices);
g_signal_connect_object (device_manager, "device-added",
G_CALLBACK (on_device_added), manager, 0);
g_signal_connect_object (device_manager, "device-removed",
G_CALLBACK (on_device_removed), manager, 0);
g_dbus_object_manager_server_set_connection (manager, connection);
}
static void
on_name_acquired (GDBusConnection *connection,
const char *name,
gpointer user_data)
{
meta_verbose ("Acquired name %s\n", name);
}
static void
on_name_lost (GDBusConnection *connection,
const char *name,
gpointer user_data)
{
meta_verbose ("Lost or failed to acquire name %s\n", name);
}
void
meta_idle_monitor_init_dbus (void)
{
static int dbus_name_id;
if (dbus_name_id > 0)
return;
dbus_name_id = g_bus_own_name (G_BUS_TYPE_SESSION,
"org.gnome.Mutter.IdleMonitor",
G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
(meta_get_replace_current_wm () ?
G_BUS_NAME_OWNER_FLAGS_REPLACE : 0),
on_bus_acquired,
on_name_acquired,
on_name_lost,
NULL, NULL);
}

View File

@ -1,65 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
*/
#ifndef META_IDLE_MONITOR_PRIVATE_H
#define META_IDLE_MONITOR_PRIVATE_H
#include <meta/meta-idle-monitor.h>
#include "display-private.h"
#include <X11/Xlib.h>
#include <X11/extensions/sync.h>
typedef struct
{
MetaIdleMonitor *monitor;
guint id;
MetaIdleMonitorWatchFunc callback;
gpointer user_data;
GDestroyNotify notify;
guint64 timeout_msec;
int idle_source_id;
} MetaIdleMonitorWatch;
struct _MetaIdleMonitor
{
GObject parent_instance;
GHashTable *watches;
int device_id;
};
struct _MetaIdleMonitorClass
{
GObjectClass parent_class;
gint64 (*get_idletime) (MetaIdleMonitor *monitor);
MetaIdleMonitorWatch * (*make_watch) (MetaIdleMonitor *monitor,
guint64 timeout_msec,
MetaIdleMonitorWatchFunc callback,
gpointer user_data,
GDestroyNotify notify);
};
void _meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch);
#endif /* META_IDLE_MONITOR_PRIVATE_H */

View File

@ -1,318 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
*/
/**
* SECTION:idle-monitor
* @title: MetaIdleMonitor
* @short_description: Mutter idle counter (similar to X's IDLETIME)
*/
#include "config.h"
#include <string.h>
#include <clutter/clutter.h>
#include <X11/Xlib.h>
#include <X11/extensions/sync.h>
#include <meta/util.h>
#include <meta/main.h>
#include <meta/meta-idle-monitor.h>
#include "meta-idle-monitor-private.h"
#include "meta-idle-monitor-dbus.h"
#include "meta-backend.h"
G_STATIC_ASSERT(sizeof(unsigned long) == sizeof(gpointer));
enum
{
PROP_0,
PROP_DEVICE_ID,
PROP_LAST,
};
static GParamSpec *obj_props[PROP_LAST];
G_DEFINE_TYPE (MetaIdleMonitor, meta_idle_monitor, G_TYPE_OBJECT)
void
_meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch)
{
MetaIdleMonitor *monitor;
guint id;
gboolean is_user_active_watch;
monitor = watch->monitor;
g_object_ref (monitor);
if (watch->idle_source_id)
{
g_source_remove (watch->idle_source_id);
watch->idle_source_id = 0;
}
id = watch->id;
is_user_active_watch = (watch->timeout_msec == 0);
if (watch->callback)
watch->callback (monitor, id, watch->user_data);
if (is_user_active_watch)
meta_idle_monitor_remove_watch (monitor, id);
g_object_unref (monitor);
}
static void
meta_idle_monitor_dispose (GObject *object)
{
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
g_clear_pointer (&monitor->watches, g_hash_table_destroy);
G_OBJECT_CLASS (meta_idle_monitor_parent_class)->dispose (object);
}
static void
meta_idle_monitor_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
switch (prop_id)
{
case PROP_DEVICE_ID:
g_value_set_int (value, monitor->device_id);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_idle_monitor_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
switch (prop_id)
{
case PROP_DEVICE_ID:
monitor->device_id = g_value_get_int (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_idle_monitor_class_init (MetaIdleMonitorClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = meta_idle_monitor_dispose;
object_class->get_property = meta_idle_monitor_get_property;
object_class->set_property = meta_idle_monitor_set_property;
/**
* MetaIdleMonitor:device_id:
*
* The device to listen to idletime on.
*/
obj_props[PROP_DEVICE_ID] =
g_param_spec_int ("device-id",
"Device ID",
"The device to listen to idletime on",
0, 255, 0,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_property (object_class, PROP_DEVICE_ID, obj_props[PROP_DEVICE_ID]);
}
static void
meta_idle_monitor_init (MetaIdleMonitor *monitor)
{
}
/**
* meta_idle_monitor_get_core:
*
* Returns: (transfer none): the #MetaIdleMonitor that tracks the server-global
* idletime for all devices. To track device-specific idletime,
* use meta_idle_monitor_get_for_device().
*/
MetaIdleMonitor *
meta_idle_monitor_get_core (void)
{
MetaBackend *backend = meta_get_backend ();
return meta_backend_get_idle_monitor (backend, 0);
}
/**
* meta_idle_monitor_get_for_device:
* @device_id: the device to get the idle time for.
*
* Returns: (transfer none): a new #MetaIdleMonitor that tracks the
* device-specific idletime for @device. To track server-global idletime
* for all devices, use meta_idle_monitor_get_core().
*/
MetaIdleMonitor *
meta_idle_monitor_get_for_device (int device_id)
{
MetaBackend *backend = meta_get_backend ();
return meta_backend_get_idle_monitor (backend, device_id);
}
static MetaIdleMonitorWatch *
make_watch (MetaIdleMonitor *monitor,
guint64 timeout_msec,
MetaIdleMonitorWatchFunc callback,
gpointer user_data,
GDestroyNotify notify)
{
MetaIdleMonitorWatch *watch;
watch = META_IDLE_MONITOR_GET_CLASS (monitor)->make_watch (monitor,
timeout_msec,
callback,
user_data,
notify);
g_hash_table_insert (monitor->watches,
GUINT_TO_POINTER (watch->id),
watch);
return watch;
}
/**
* meta_idle_monitor_add_idle_watch:
* @monitor: A #MetaIdleMonitor
* @interval_msec: The idletime interval, in milliseconds
* @callback: (nullable): The callback to call when the user has
* accumulated @interval_msec milliseconds of idle time.
* @user_data: (nullable): The user data to pass to the callback
* @notify: A #GDestroyNotify
*
* Returns: a watch id
*
* Adds a watch for a specific idle time. The callback will be called
* when the user has accumulated @interval_msec milliseconds of idle time.
* This function will return an ID that can either be passed to
* meta_idle_monitor_remove_watch(), or can be used to tell idle time
* watches apart if you have more than one.
*
* Also note that this function will only care about positive transitions
* (user's idle time exceeding a certain time). If you want to know about
* when the user has become active, use
* meta_idle_monitor_add_user_active_watch().
*/
guint
meta_idle_monitor_add_idle_watch (MetaIdleMonitor *monitor,
guint64 interval_msec,
MetaIdleMonitorWatchFunc callback,
gpointer user_data,
GDestroyNotify notify)
{
MetaIdleMonitorWatch *watch;
g_return_val_if_fail (META_IS_IDLE_MONITOR (monitor), 0);
g_return_val_if_fail (interval_msec > 0, 0);
watch = make_watch (monitor,
interval_msec,
callback,
user_data,
notify);
return watch->id;
}
/**
* meta_idle_monitor_add_user_active_watch:
* @monitor: A #MetaIdleMonitor
* @callback: (nullable): The callback to call when the user is
* active again.
* @user_data: (nullable): The user data to pass to the callback
* @notify: A #GDestroyNotify
*
* Returns: a watch id
*
* Add a one-time watch to know when the user is active again.
* Note that this watch is one-time and will de-activate after the
* function is called, for efficiency purposes. It's most convenient
* to call this when an idle watch, as added by
* meta_idle_monitor_add_idle_watch(), has triggered.
*/
guint
meta_idle_monitor_add_user_active_watch (MetaIdleMonitor *monitor,
MetaIdleMonitorWatchFunc callback,
gpointer user_data,
GDestroyNotify notify)
{
MetaIdleMonitorWatch *watch;
g_return_val_if_fail (META_IS_IDLE_MONITOR (monitor), 0);
watch = make_watch (monitor,
0,
callback,
user_data,
notify);
return watch->id;
}
/**
* meta_idle_monitor_remove_watch:
* @monitor: A #MetaIdleMonitor
* @id: A watch ID
*
* Removes an idle time watcher, previously added by
* meta_idle_monitor_add_idle_watch() or
* meta_idle_monitor_add_user_active_watch().
*/
void
meta_idle_monitor_remove_watch (MetaIdleMonitor *monitor,
guint id)
{
g_return_if_fail (META_IS_IDLE_MONITOR (monitor));
g_object_ref (monitor);
g_hash_table_remove (monitor->watches,
GUINT_TO_POINTER (id));
g_object_unref (monitor);
}
/**
* meta_idle_monitor_get_idletime:
* @monitor: A #MetaIdleMonitor
*
* Returns: The current idle time, in milliseconds, or -1 for not supported
*/
gint64
meta_idle_monitor_get_idletime (MetaIdleMonitor *monitor)
{
return META_IDLE_MONITOR_GET_CLASS (monitor)->get_idletime (monitor);
}

View File

@ -1,55 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2001 Havoc Pennington
* Copyright (C) 2003 Rob Adams
* Copyright (C) 2004-2006 Elijah Newren
* Copyright (C) 2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_MONITOR_CONFIG_H
#define META_MONITOR_CONFIG_H
#include "meta-monitor-manager.h"
#define META_TYPE_MONITOR_CONFIG (meta_monitor_config_get_type ())
#define META_MONITOR_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_CONFIG, MetaMonitorConfig))
#define META_MONITOR_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_CONFIG, MetaMonitorConfigClass))
#define META_IS_MONITOR_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_CONFIG))
#define META_IS_MONITOR_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MONITOR_CONFIG))
#define META_MONITOR_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MONITOR_CONFIG, MetaMonitorConfigClass))
GType meta_monitor_config_get_type (void) G_GNUC_CONST;
MetaMonitorConfig *meta_monitor_config_new (void);
gboolean meta_monitor_config_match_current (MetaMonitorConfig *config,
MetaMonitorManager *manager);
gboolean meta_monitor_config_apply_stored (MetaMonitorConfig *config,
MetaMonitorManager *manager);
void meta_monitor_config_make_default (MetaMonitorConfig *config,
MetaMonitorManager *manager);
void meta_monitor_config_update_current (MetaMonitorConfig *config,
MetaMonitorManager *manager);
void meta_monitor_config_make_persistent (MetaMonitorConfig *config);
void meta_monitor_config_restore_previous (MetaMonitorConfig *config,
MetaMonitorManager *manager);
#endif /* META_MONITOR_CONFIG_H */

View File

@ -1,227 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2001, 2002 Havoc Pennington
* Copyright (C) 2002, 2003 Red Hat Inc.
* Some ICCCM manager selection code derived from fvwm2,
* Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team
* Copyright (C) 2003 Rob Adams
* Copyright (C) 2004-2006 Elijah Newren
* Copyright (C) 2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "meta-monitor-manager-dummy.h"
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
struct _MetaMonitorManagerDummy
{
MetaMonitorManager parent_instance;
};
struct _MetaMonitorManagerDummyClass
{
MetaMonitorManagerClass parent_class;
};
G_DEFINE_TYPE (MetaMonitorManagerDummy, meta_monitor_manager_dummy, META_TYPE_MONITOR_MANAGER);
static void
meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
{
manager->max_screen_width = 65535;
manager->max_screen_height = 65535;
manager->screen_width = 1024;
manager->screen_height = 768;
manager->modes = g_new0 (MetaMonitorMode, 1);
manager->n_modes = 1;
manager->modes[0].mode_id = 0;
manager->modes[0].width = 1024;
manager->modes[0].height = 768;
manager->modes[0].refresh_rate = 60.0;
manager->crtcs = g_new0 (MetaCRTC, 1);
manager->n_crtcs = 1;
manager->crtcs[0].crtc_id = 1;
manager->crtcs[0].rect.x = 0;
manager->crtcs[0].rect.y = 0;
manager->crtcs[0].rect.width = manager->modes[0].width;
manager->crtcs[0].rect.height = manager->modes[0].height;
manager->crtcs[0].current_mode = &manager->modes[0];
manager->crtcs[0].transform = WL_OUTPUT_TRANSFORM_NORMAL;
manager->crtcs[0].all_transforms = ALL_WL_TRANSFORMS;
manager->crtcs[0].is_dirty = FALSE;
manager->crtcs[0].logical_monitor = NULL;
manager->outputs = g_new0 (MetaOutput, 1);
manager->n_outputs = 1;
manager->outputs[0].crtc = &manager->crtcs[0];
manager->outputs[0].output_id = 1;
manager->outputs[0].name = g_strdup ("LVDS");
manager->outputs[0].vendor = g_strdup ("MetaProducts Inc.");
manager->outputs[0].product = g_strdup ("unknown");
manager->outputs[0].serial = g_strdup ("0xC0FFEE");
manager->outputs[0].width_mm = 222;
manager->outputs[0].height_mm = 125;
manager->outputs[0].subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
manager->outputs[0].preferred_mode = &manager->modes[0];
manager->outputs[0].n_modes = 1;
manager->outputs[0].modes = g_new0 (MetaMonitorMode *, 1);
manager->outputs[0].modes[0] = &manager->modes[0];
manager->outputs[0].n_possible_crtcs = 1;
manager->outputs[0].possible_crtcs = g_new0 (MetaCRTC *, 1);
manager->outputs[0].possible_crtcs[0] = &manager->crtcs[0];
manager->outputs[0].n_possible_clones = 0;
manager->outputs[0].possible_clones = g_new0 (MetaOutput *, 0);
manager->outputs[0].backlight = -1;
manager->outputs[0].backlight_min = 0;
manager->outputs[0].backlight_max = 0;
}
static void
meta_monitor_manager_dummy_apply_config (MetaMonitorManager *manager,
MetaCRTCInfo **crtcs,
unsigned int n_crtcs,
MetaOutputInfo **outputs,
unsigned int n_outputs)
{
unsigned i;
int screen_width = 0, screen_height = 0;
for (i = 0; i < n_crtcs; i++)
{
MetaCRTCInfo *crtc_info = crtcs[i];
MetaCRTC *crtc = crtc_info->crtc;
crtc->is_dirty = TRUE;
if (crtc_info->mode == NULL)
{
crtc->rect.x = 0;
crtc->rect.y = 0;
crtc->rect.width = 0;
crtc->rect.height = 0;
crtc->current_mode = NULL;
}
else
{
MetaMonitorMode *mode;
MetaOutput *output;
int i, n_outputs;
int width, height;
mode = crtc_info->mode;
if (meta_monitor_transform_is_rotated (crtc_info->transform))
{
width = mode->height;
height = mode->width;
}
else
{
width = mode->width;
height = mode->height;
}
crtc->rect.x = crtc_info->x;
crtc->rect.y = crtc_info->y;
crtc->rect.width = width;
crtc->rect.height = height;
crtc->current_mode = mode;
crtc->transform = crtc_info->transform;
screen_width = MAX (screen_width, crtc_info->x + width);
screen_height = MAX (screen_height, crtc_info->y + height);
n_outputs = crtc_info->outputs->len;
for (i = 0; i < n_outputs; i++)
{
output = ((MetaOutput**)crtc_info->outputs->pdata)[i];
output->is_dirty = TRUE;
output->crtc = crtc;
}
}
}
for (i = 0; i < n_outputs; i++)
{
MetaOutputInfo *output_info = outputs[i];
MetaOutput *output = output_info->output;
output->is_primary = output_info->is_primary;
output->is_presentation = output_info->is_presentation;
}
/* Disable CRTCs not mentioned in the list */
for (i = 0; i < manager->n_crtcs; i++)
{
MetaCRTC *crtc = &manager->crtcs[i];
crtc->logical_monitor = NULL;
if (crtc->is_dirty)
{
crtc->is_dirty = FALSE;
continue;
}
crtc->rect.x = 0;
crtc->rect.y = 0;
crtc->rect.width = 0;
crtc->rect.height = 0;
crtc->current_mode = NULL;
}
/* Disable outputs not mentioned in the list */
for (i = 0; i < manager->n_outputs; i++)
{
MetaOutput *output = &manager->outputs[i];
if (output->is_dirty)
{
output->is_dirty = FALSE;
continue;
}
output->crtc = NULL;
output->is_primary = FALSE;
}
manager->screen_width = screen_width;
manager->screen_height = screen_height;
meta_monitor_manager_rebuild_derived (manager);
}
static void
meta_monitor_manager_dummy_class_init (MetaMonitorManagerDummyClass *klass)
{
MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass);
manager_class->read_current = meta_monitor_manager_dummy_read_current;
manager_class->apply_configuration = meta_monitor_manager_dummy_apply_config;
}
static void
meta_monitor_manager_dummy_init (MetaMonitorManagerDummy *manager)
{
}

View File

@ -1,40 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2001 Havoc Pennington
* Copyright (C) 2003 Rob Adams
* Copyright (C) 2004-2006 Elijah Newren
* Copyright (C) 2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_MONITOR_MANAGER_DUMMY_H
#define META_MONITOR_MANAGER_DUMMY_H
#include "meta-monitor-manager.h"
#define META_TYPE_MONITOR_MANAGER_DUMMY (meta_monitor_manager_dummy_get_type ())
#define META_MONITOR_MANAGER_DUMMY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_DUMMY, MetaMonitorManagerDummy))
#define META_MONITOR_MANAGER_DUMMY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_MANAGER_DUMMY, MetaMonitorManagerDummyClass))
#define META_IS_MONITOR_MANAGER_DUMMY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_MANAGER_DUMMY))
#define META_IS_MONITOR_MANAGER_DUMMY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MONITOR_MANAGER_DUMMY))
#define META_MONITOR_MANAGER_DUMMY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MONITOR_MANAGER_DUMMY, MetaMonitorManagerDummyClass))
typedef struct _MetaMonitorManagerDummyClass MetaMonitorManagerDummyClass;
typedef struct _MetaMonitorManagerDummy MetaMonitorManagerDummy;
GType meta_monitor_manager_dummy_get_type (void);
#endif /* META_MONITOR_MANAGER_DUMMY_H */

View File

@ -1,107 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#include "config.h"
#include "dbus-utils.h"
#include <glib.h>
/* Stolen from tp_escape_as_identifier, from tp-glib,
* which follows the same escaping convention as systemd.
*/
static inline gboolean
_esc_ident_bad (gchar c, gboolean is_first)
{
return ((c < 'a' || c > 'z') &&
(c < 'A' || c > 'Z') &&
(c < '0' || c > '9' || is_first));
}
static gchar *
escape_dbus_component (const gchar *name)
{
gboolean bad = FALSE;
size_t len = 0;
GString *op;
const gchar *ptr, *first_ok;
g_return_val_if_fail (name != NULL, NULL);
/* fast path for empty name */
if (name[0] == '\0')
return g_strdup ("_");
for (ptr = name; *ptr; ptr++)
{
if (_esc_ident_bad (*ptr, ptr == name))
{
bad = TRUE;
len += 3;
}
else
len++;
}
/* fast path if it's clean */
if (!bad)
return g_strdup (name);
/* If strictly less than ptr, first_ok is the first uncopied safe character.
*/
first_ok = name;
op = g_string_sized_new (len);
for (ptr = name; *ptr; ptr++)
{
if (_esc_ident_bad (*ptr, ptr == name))
{
/* copy preceding safe characters if any */
if (first_ok < ptr)
{
g_string_append_len (op, first_ok, ptr - first_ok);
}
/* escape the unsafe character */
g_string_append_printf (op, "_%02x", (unsigned char)(*ptr));
/* restart after it */
first_ok = ptr + 1;
}
}
/* copy trailing safe characters if any */
if (first_ok < ptr)
{
g_string_append_len (op, first_ok, ptr - first_ok);
}
return g_string_free (op, FALSE);
}
char *
get_escaped_dbus_path (const char *prefix,
const char *component)
{
char *escaped_component = escape_dbus_component (component);
char *path = g_strconcat (prefix, "/", escaped_component, NULL);
g_free (escaped_component);
return path;
}

View File

@ -1,32 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#ifndef DBUS_UTILS_H
#define DBUS_UTILS_H
char *
get_escaped_dbus_path (const char *prefix,
const char *component);
#endif /* DBUS_UTILS_H */

View File

@ -1,235 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#include "config.h"
#include <meta/main.h>
#include <clutter/evdev/clutter-evdev.h>
#include "meta-backend-native.h"
#include "meta-idle-monitor-native.h"
#include "meta-monitor-manager-kms.h"
#include "meta-cursor-renderer-native.h"
#include "meta-launcher.h"
struct _MetaBackendNativePrivate
{
MetaLauncher *launcher;
};
typedef struct _MetaBackendNativePrivate MetaBackendNativePrivate;
G_DEFINE_TYPE_WITH_PRIVATE (MetaBackendNative, meta_backend_native, META_TYPE_BACKEND);
/*
* The pointer constrain code is mostly a rip-off of the XRandR code from Xorg.
* (from xserver/randr/rrcrtc.c, RRConstrainCursorHarder)
*
* Copyright © 2006 Keith Packard
* Copyright 2010 Red Hat, Inc
*
*/
static gboolean
check_all_screen_monitors(MetaMonitorInfo *monitors,
unsigned n_monitors,
float x,
float y)
{
unsigned int i;
for (i = 0; i < n_monitors; i++)
{
MetaMonitorInfo *monitor = &monitors[i];
int left, right, top, bottom;
left = monitor->rect.x;
right = left + monitor->rect.width;
top = monitor->rect.y;
bottom = left + monitor->rect.height;
if ((x >= left) && (x < right) && (y >= top) && (y < bottom))
return TRUE;
}
return FALSE;
}
static void
constrain_all_screen_monitors (ClutterInputDevice *device,
MetaMonitorInfo *monitors,
unsigned n_monitors,
float *x,
float *y)
{
ClutterPoint current;
unsigned int i;
clutter_input_device_get_coords (device, NULL, &current);
/* if we're trying to escape, clamp to the CRTC we're coming from */
for (i = 0; i < n_monitors; i++)
{
MetaMonitorInfo *monitor = &monitors[i];
int left, right, top, bottom;
float nx, ny;
left = monitor->rect.x;
right = left + monitor->rect.width;
top = monitor->rect.y;
bottom = left + monitor->rect.height;
nx = current.x;
ny = current.y;
if ((nx >= left) && (nx < right) && (ny >= top) && (ny < bottom))
{
if (*x < left)
*x = left;
if (*x >= right)
*x = right - 1;
if (*y < top)
*y = top;
if (*y >= bottom)
*y = bottom - 1;
return;
}
}
}
static void
pointer_constrain_callback (ClutterInputDevice *device,
guint32 time,
float *new_x,
float *new_y,
gpointer user_data)
{
MetaMonitorManager *monitor_manager;
MetaMonitorInfo *monitors;
unsigned int n_monitors;
gboolean ret;
monitor_manager = meta_monitor_manager_get ();
monitors = meta_monitor_manager_get_monitor_infos (monitor_manager, &n_monitors);
/* if we're moving inside a monitor, we're fine */
ret = check_all_screen_monitors(monitors, n_monitors, *new_x, *new_y);
if (ret == TRUE)
return;
/* if we're trying to escape, clamp to the CRTC we're coming from */
constrain_all_screen_monitors(device, monitors, n_monitors, new_x, new_y);
}
static void
meta_backend_native_post_init (MetaBackend *backend)
{
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
META_BACKEND_CLASS (meta_backend_native_parent_class)->post_init (backend);
clutter_evdev_set_pointer_constrain_callback (manager, pointer_constrain_callback,
NULL, NULL);
}
static MetaIdleMonitor *
meta_backend_native_create_idle_monitor (MetaBackend *backend,
int device_id)
{
return g_object_new (META_TYPE_IDLE_MONITOR_NATIVE,
"device-id", device_id,
NULL);
}
static MetaMonitorManager *
meta_backend_native_create_monitor_manager (MetaBackend *backend)
{
return g_object_new (META_TYPE_MONITOR_MANAGER_KMS, NULL);
}
static MetaCursorRenderer *
meta_backend_native_create_cursor_renderer (MetaBackend *backend)
{
return g_object_new (META_TYPE_CURSOR_RENDERER_NATIVE, NULL);
}
static void
meta_backend_native_class_init (MetaBackendNativeClass *klass)
{
MetaBackendClass *backend_class = META_BACKEND_CLASS (klass);
backend_class->post_init = meta_backend_native_post_init;
backend_class->create_idle_monitor = meta_backend_native_create_idle_monitor;
backend_class->create_monitor_manager = meta_backend_native_create_monitor_manager;
backend_class->create_cursor_renderer = meta_backend_native_create_cursor_renderer;
}
static void
meta_backend_native_init (MetaBackendNative *native)
{
MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native);
/* We're a display server, so start talking to weston-launch. */
priv->launcher = meta_launcher_new ();
}
gboolean
meta_activate_vt (int vt, GError **error)
{
MetaBackend *backend = meta_get_backend ();
MetaBackendNative *native = META_BACKEND_NATIVE (backend);
MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native);
return meta_launcher_activate_vt (priv->launcher, vt, error);
}
/**
* meta_activate_session:
*
* Tells mutter to activate the session. When mutter is a
* Wayland compositor, this tells logind to switch over to
* the new session.
*/
gboolean
meta_activate_session (void)
{
GError *error = NULL;
MetaBackend *backend = meta_get_backend ();
/* Do nothing. */
if (!META_IS_BACKEND_NATIVE (backend))
return TRUE;
MetaBackendNative *native = META_BACKEND_NATIVE (backend);
MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native);
if (!meta_launcher_activate_session (priv->launcher, &error))
{
g_warning ("Could not activate session: %s\n", error->message);
g_error_free (error);
return FALSE;
}
return TRUE;
}

View File

@ -1,54 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#ifndef META_BACKEND_NATIVE_H
#define META_BACKEND_NATIVE_H
#include "backends/meta-backend-private.h"
#define META_TYPE_BACKEND_NATIVE (meta_backend_native_get_type ())
#define META_BACKEND_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BACKEND_NATIVE, MetaBackendNative))
#define META_BACKEND_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_BACKEND_NATIVE, MetaBackendNativeClass))
#define META_IS_BACKEND_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_BACKEND_NATIVE))
#define META_IS_BACKEND_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_BACKEND_NATIVE))
#define META_BACKEND_NATIVE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_BACKEND_NATIVE, MetaBackendNativeClass))
typedef struct _MetaBackendNative MetaBackendNative;
typedef struct _MetaBackendNativeClass MetaBackendNativeClass;
struct _MetaBackendNative
{
MetaBackend parent;
};
struct _MetaBackendNativeClass
{
MetaBackendClass parent_class;
};
GType meta_backend_native_get_type (void) G_GNUC_CONST;
gboolean meta_activate_vt (int vt, GError **error);
#endif /* META_BACKEND_NATIVE_H */

View File

@ -1,205 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#include "config.h"
#include "meta-cursor-renderer-native.h"
#include <gbm.h>
#include "meta-cursor-private.h"
#include "meta-monitor-manager.h"
struct _MetaCursorRendererNativePrivate
{
gboolean has_hw_cursor;
int drm_fd;
struct gbm_device *gbm;
};
typedef struct _MetaCursorRendererNativePrivate MetaCursorRendererNativePrivate;
G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRendererNative, meta_cursor_renderer_native, META_TYPE_CURSOR_RENDERER);
static void
meta_cursor_renderer_native_finalize (GObject *object)
{
MetaCursorRendererNative *renderer = META_CURSOR_RENDERER_NATIVE (object);
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (renderer);
if (priv->gbm)
gbm_device_destroy (priv->gbm);
G_OBJECT_CLASS (meta_cursor_renderer_native_parent_class)->finalize (object);
}
static void
set_crtc_cursor (MetaCursorRendererNative *native,
MetaCRTC *crtc,
MetaCursorReference *cursor,
gboolean force)
{
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
if (crtc->cursor == cursor && !force)
return;
crtc->cursor = cursor;
if (cursor)
{
struct gbm_bo *bo;
union gbm_bo_handle handle;
int width, height;
int hot_x, hot_y;
bo = meta_cursor_reference_get_gbm_bo (cursor, &hot_x, &hot_y);
handle = gbm_bo_get_handle (bo);
width = gbm_bo_get_width (bo);
height = gbm_bo_get_height (bo);
drmModeSetCursor2 (priv->drm_fd, crtc->crtc_id, handle.u32,
width, height, hot_x, hot_y);
}
else
{
drmModeSetCursor2 (priv->drm_fd, crtc->crtc_id, 0, 0, 0, 0, 0);
}
}
static void
update_hw_cursor (MetaCursorRendererNative *native,
gboolean force)
{
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native);
const MetaRectangle *cursor_rect = meta_cursor_renderer_get_rect (renderer);
MetaCursorReference *cursor = meta_cursor_renderer_get_cursor (renderer);
MetaMonitorManager *monitors;
MetaCRTC *crtcs;
unsigned int i, n_crtcs;
monitors = meta_monitor_manager_get ();
meta_monitor_manager_get_resources (monitors, NULL, NULL, &crtcs, &n_crtcs, NULL, NULL);
for (i = 0; i < n_crtcs; i++)
{
gboolean crtc_should_have_cursor;
MetaCursorReference *crtc_cursor;
MetaRectangle *crtc_rect;
crtc_rect = &crtcs[i].rect;
crtc_should_have_cursor = (priv->has_hw_cursor && meta_rectangle_overlap (cursor_rect, crtc_rect));
if (crtc_should_have_cursor)
crtc_cursor = cursor;
else
crtc_cursor = NULL;
set_crtc_cursor (native, &crtcs[i], crtc_cursor, force);
if (crtc_cursor)
{
drmModeMoveCursor (priv->drm_fd, crtcs[i].crtc_id,
cursor_rect->x - crtc_rect->x,
cursor_rect->y - crtc_rect->y);
}
}
}
static gboolean
should_have_hw_cursor (MetaCursorRenderer *renderer)
{
MetaCursorReference *cursor = meta_cursor_renderer_get_cursor (renderer);
if (cursor)
return (meta_cursor_reference_get_gbm_bo (cursor, NULL, NULL) != NULL);
else
return FALSE;
}
static gboolean
meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer)
{
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
priv->has_hw_cursor = should_have_hw_cursor (renderer);
update_hw_cursor (native, FALSE);
return priv->has_hw_cursor;
}
static void
meta_cursor_renderer_native_class_init (MetaCursorRendererNativeClass *klass)
{
MetaCursorRendererClass *renderer_class = META_CURSOR_RENDERER_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_cursor_renderer_native_finalize;
renderer_class->update_cursor = meta_cursor_renderer_native_update_cursor;
}
static void
on_monitors_changed (MetaMonitorManager *monitors,
MetaCursorRendererNative *native)
{
/* Our tracking is all messed up, so force an update. */
update_hw_cursor (native, TRUE);
}
static void
meta_cursor_renderer_native_init (MetaCursorRendererNative *native)
{
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
MetaMonitorManager *monitors;
monitors = meta_monitor_manager_get ();
g_signal_connect_object (monitors, "monitors-changed",
G_CALLBACK (on_monitors_changed), native, 0);
#if defined(CLUTTER_WINDOWING_EGL)
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
{
CoglRenderer *cogl_renderer = cogl_display_get_renderer (cogl_context_get_display (ctx));
priv->drm_fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
priv->gbm = gbm_create_device (priv->drm_fd);
}
#endif
}
struct gbm_device *
meta_cursor_renderer_native_get_gbm_device (MetaCursorRendererNative *native)
{
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
return priv->gbm;
}
void
meta_cursor_renderer_native_force_update (MetaCursorRendererNative *native)
{
update_hw_cursor (native, TRUE);
}

View File

@ -1,55 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#ifndef META_CURSOR_RENDERER_NATIVE_H
#define META_CURSOR_RENDERER_NATIVE_H
#include "meta-cursor-renderer.h"
#define META_TYPE_CURSOR_RENDERER_NATIVE (meta_cursor_renderer_native_get_type ())
#define META_CURSOR_RENDERER_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CURSOR_RENDERER_NATIVE, MetaCursorRendererNative))
#define META_CURSOR_RENDERER_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_CURSOR_RENDERER_NATIVE, MetaCursorRendererNativeClass))
#define META_IS_CURSOR_RENDERER_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_CURSOR_RENDERER_NATIVE))
#define META_IS_CURSOR_RENDERER_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_CURSOR_RENDERER_NATIVE))
#define META_CURSOR_RENDERER_NATIVE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_CURSOR_RENDERER_NATIVE, MetaCursorRendererNativeClass))
typedef struct _MetaCursorRendererNative MetaCursorRendererNative;
typedef struct _MetaCursorRendererNativeClass MetaCursorRendererNativeClass;
struct _MetaCursorRendererNative
{
MetaCursorRenderer parent;
};
struct _MetaCursorRendererNativeClass
{
MetaCursorRendererClass parent_class;
};
GType meta_cursor_renderer_native_get_type (void) G_GNUC_CONST;
struct gbm_device * meta_cursor_renderer_native_get_gbm_device (MetaCursorRendererNative *renderer);
void meta_cursor_renderer_native_force_update (MetaCursorRendererNative *renderer);
#endif /* META_CURSOR_RENDERER_NATIVE_H */

View File

@ -1,219 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
*/
#include "config.h"
#include "meta-idle-monitor-native.h"
#include "meta-idle-monitor-private.h"
#include <meta/util.h>
#include "display-private.h"
#include <string.h>
struct _MetaIdleMonitorNative
{
MetaIdleMonitor parent;
guint64 last_event_time;
};
struct _MetaIdleMonitorNativeClass
{
MetaIdleMonitorClass parent_class;
};
typedef struct {
MetaIdleMonitorWatch base;
GSource *timeout_source;
} MetaIdleMonitorWatchNative;
G_DEFINE_TYPE (MetaIdleMonitorNative, meta_idle_monitor_native, META_TYPE_IDLE_MONITOR)
static gint64
meta_idle_monitor_native_get_idletime (MetaIdleMonitor *monitor)
{
MetaIdleMonitorNative *monitor_native = META_IDLE_MONITOR_NATIVE (monitor);
return (g_get_monotonic_time () - monitor_native->last_event_time) / 1000;
}
static guint32
get_next_watch_serial (void)
{
static guint32 serial = 0;
g_atomic_int_inc (&serial);
return serial;
}
static gboolean
native_dispatch_timeout (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
MetaIdleMonitorWatchNative *watch_native = user_data;
MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_native;
_meta_idle_monitor_watch_fire (watch);
g_source_set_ready_time (watch_native->timeout_source, -1);
return TRUE;
}
static GSourceFuncs native_source_funcs = {
NULL, /* prepare */
NULL, /* check */
native_dispatch_timeout,
NULL, /* finalize */
};
static void
free_watch (gpointer data)
{
MetaIdleMonitorWatchNative *watch_native = data;
MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_native;
MetaIdleMonitor *monitor = watch->monitor;
g_object_ref (monitor);
if (watch->idle_source_id)
{
g_source_remove (watch->idle_source_id);
watch->idle_source_id = 0;
}
if (watch->notify != NULL)
watch->notify (watch->user_data);
if (watch_native->timeout_source != NULL)
g_source_destroy (watch_native->timeout_source);
g_object_unref (monitor);
g_slice_free (MetaIdleMonitorWatchNative, watch_native);
}
static MetaIdleMonitorWatch *
meta_idle_monitor_native_make_watch (MetaIdleMonitor *monitor,
guint64 timeout_msec,
MetaIdleMonitorWatchFunc callback,
gpointer user_data,
GDestroyNotify notify)
{
MetaIdleMonitorWatchNative *watch_native;
MetaIdleMonitorWatch *watch;
MetaIdleMonitorNative *monitor_native = META_IDLE_MONITOR_NATIVE (monitor);
watch_native = g_slice_new0 (MetaIdleMonitorWatchNative);
watch = (MetaIdleMonitorWatch *) watch_native;
watch->monitor = monitor;
watch->id = get_next_watch_serial ();
watch->callback = callback;
watch->user_data = user_data;
watch->notify = notify;
watch->timeout_msec = timeout_msec;
if (timeout_msec != 0)
{
GSource *source = g_source_new (&native_source_funcs, sizeof (GSource));
g_source_set_callback (source, NULL, watch, NULL);
g_source_set_ready_time (source, monitor_native->last_event_time + timeout_msec * 1000);
g_source_attach (source, NULL);
g_source_unref (source);
watch_native->timeout_source = source;
}
return watch;
}
static void
meta_idle_monitor_native_class_init (MetaIdleMonitorNativeClass *klass)
{
MetaIdleMonitorClass *idle_monitor_class = META_IDLE_MONITOR_CLASS (klass);
idle_monitor_class->get_idletime = meta_idle_monitor_native_get_idletime;
idle_monitor_class->make_watch = meta_idle_monitor_native_make_watch;
}
static void
meta_idle_monitor_native_init (MetaIdleMonitorNative *monitor_native)
{
MetaIdleMonitor *monitor = META_IDLE_MONITOR (monitor_native);
monitor->watches = g_hash_table_new_full (NULL, NULL, NULL, free_watch);
}
typedef struct {
MetaIdleMonitorNative *monitor_native;
GList *fired_watches;
} CheckNativeClosure;
static gboolean
check_native_watch (gpointer key,
gpointer value,
gpointer user_data)
{
MetaIdleMonitorWatchNative *watch_native = value;
MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_native;
CheckNativeClosure *closure = user_data;
gboolean steal;
if (watch->timeout_msec == 0)
{
closure->fired_watches = g_list_prepend (closure->fired_watches, watch);
steal = TRUE;
}
else
{
g_source_set_ready_time (watch_native->timeout_source,
closure->monitor_native->last_event_time +
watch->timeout_msec * 1000);
steal = FALSE;
}
return steal;
}
static void
fire_native_watch (gpointer watch,
gpointer data)
{
_meta_idle_monitor_watch_fire (watch);
}
void
meta_idle_monitor_native_reset_idletime (MetaIdleMonitor *monitor)
{
MetaIdleMonitorNative *monitor_native = META_IDLE_MONITOR_NATIVE (monitor);
CheckNativeClosure closure;
monitor_native->last_event_time = g_get_monotonic_time ();
closure.monitor_native = monitor_native;
closure.fired_watches = NULL;
g_hash_table_foreach_steal (monitor->watches, check_native_watch, &closure);
g_list_foreach (closure.fired_watches, fire_native_watch, NULL);
g_list_free (closure.fired_watches);
}

View File

@ -1,43 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
*/
#ifndef META_IDLE_MONITOR_NATIVE_H
#define META_IDLE_MONITOR_NATIVE_H
#include <glib-object.h>
#include <meta/meta-idle-monitor.h>
#define META_TYPE_IDLE_MONITOR_NATIVE (meta_idle_monitor_native_get_type ())
#define META_IDLE_MONITOR_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_IDLE_MONITOR_NATIVE, MetaIdleMonitorNative))
#define META_IDLE_MONITOR_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_IDLE_MONITOR_NATIVE, MetaIdleMonitorNativeClass))
#define META_IS_IDLE_MONITOR_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_IDLE_MONITOR_NATIVE))
#define META_IS_IDLE_MONITOR_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_IDLE_MONITOR_NATIVE))
#define META_IDLE_MONITOR_NATIVE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_IDLE_MONITOR_NATIVE, MetaIdleMonitorNativeClass))
typedef struct _MetaIdleMonitorNative MetaIdleMonitorNative;
typedef struct _MetaIdleMonitorNativeClass MetaIdleMonitorNativeClass;
GType meta_idle_monitor_native_get_type (void);
void meta_idle_monitor_native_reset_idletime (MetaIdleMonitor *monitor);
#endif /* META_IDLE_MONITOR_NATIVE_H */

View File

@ -1,368 +0,0 @@
/*
* Copyright (C) 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include "config.h"
#include "meta-launcher.h"
#include <gio/gunixfdlist.h>
#include <clutter/clutter.h>
#include <clutter/egl/clutter-egl.h>
#include <clutter/evdev/clutter-evdev.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <malloc.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <systemd/sd-login.h>
#include "dbus-utils.h"
#include "meta-dbus-login1.h"
#include "wayland/meta-wayland-private.h"
#include "backends/meta-backend.h"
#include "meta-cursor-renderer-native.h"
struct _MetaLauncher
{
Login1Session *session_proxy;
Login1Seat *seat_proxy;
gboolean session_active;
};
static Login1Session *
get_session_proxy (GCancellable *cancellable)
{
char *proxy_path;
char *session_id;
Login1Session *session_proxy;
if (sd_pid_get_session (getpid (), &session_id) < 0)
return NULL;
proxy_path = get_escaped_dbus_path ("/org/freedesktop/login1/session", session_id);
session_proxy = login1_session_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
"org.freedesktop.login1",
proxy_path,
cancellable, NULL);
free (proxy_path);
return session_proxy;
}
static Login1Seat *
get_seat_proxy (GCancellable *cancellable)
{
return login1_seat_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
"org.freedesktop.login1",
"/org/freedesktop/login1/seat/self",
cancellable, NULL);
}
static void
session_unpause (void)
{
ClutterBackend *backend;
CoglContext *cogl_context;
CoglDisplay *cogl_display;
backend = clutter_get_default_backend ();
cogl_context = clutter_backend_get_cogl_context (backend);
cogl_display = cogl_context_get_display (cogl_context);
cogl_kms_display_queue_modes_reset (cogl_display);
clutter_evdev_reclaim_devices ();
clutter_egl_thaw_master_clock ();
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
MetaBackend *backend = meta_get_backend ();
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (backend);
/* When we mode-switch back, we need to immediately queue a redraw
* in case nothing else queued one for us, and force the cursor to
* update. */
clutter_actor_queue_redraw (compositor->stage);
meta_cursor_renderer_native_force_update (META_CURSOR_RENDERER_NATIVE (renderer));
}
}
static void
session_pause (void)
{
clutter_evdev_release_devices ();
clutter_egl_freeze_master_clock ();
}
static gboolean
take_device (Login1Session *session_proxy,
int dev_major,
int dev_minor,
int *out_fd,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
GVariant *fd_variant = NULL;
int fd = -1;
GUnixFDList *fd_list;
if (!login1_session_call_take_device_sync (session_proxy,
dev_major,
dev_minor,
NULL,
&fd_variant,
NULL, /* paused */
&fd_list,
cancellable,
error))
goto out;
fd = g_unix_fd_list_get (fd_list, g_variant_get_handle (fd_variant), error);
if (fd == -1)
goto out;
*out_fd = fd;
ret = TRUE;
out:
if (fd_variant)
g_variant_unref (fd_variant);
if (fd_list)
g_object_unref (fd_list);
return ret;
}
static gboolean
get_device_info_from_path (const char *path,
int *out_major,
int *out_minor)
{
gboolean ret = FALSE;
int r;
struct stat st;
r = stat (path, &st);
if (r < 0)
goto out;
if (!S_ISCHR (st.st_mode))
goto out;
*out_major = major (st.st_rdev);
*out_minor = minor (st.st_rdev);
ret = TRUE;
out:
return ret;
}
static gboolean
get_device_info_from_fd (int fd,
int *out_major,
int *out_minor)
{
gboolean ret = FALSE;
int r;
struct stat st;
r = fstat (fd, &st);
if (r < 0)
goto out;
if (!S_ISCHR (st.st_mode))
goto out;
*out_major = major (st.st_rdev);
*out_minor = minor (st.st_rdev);
ret = TRUE;
out:
return ret;
}
static int
on_evdev_device_open (const char *path,
int flags,
gpointer user_data,
GError **error)
{
MetaLauncher *self = user_data;
int fd;
int major, minor;
if (!get_device_info_from_path (path, &major, &minor))
{
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_NOT_FOUND,
"Could not get device info for path %s: %m", path);
return -1;
}
if (!take_device (self->session_proxy, major, minor, &fd, NULL, error))
return -1;
return fd;
}
static void
on_evdev_device_close (int fd,
gpointer user_data)
{
MetaLauncher *self = user_data;
int major, minor;
GError *error = NULL;
if (!get_device_info_from_fd (fd, &major, &minor))
{
g_warning ("Could not get device info for fd %d: %m", fd);
return;
}
if (!login1_session_call_release_device_sync (self->session_proxy,
major, minor,
NULL, &error))
{
g_warning ("Could not release device %d,%d: %s", major, minor, error->message);
}
}
static void
sync_active (MetaLauncher *self)
{
gboolean active = login1_session_get_active (LOGIN1_SESSION (self->session_proxy));
if (active == self->session_active)
return;
self->session_active = active;
if (active)
session_unpause ();
else
session_pause ();
}
static void
on_active_changed (Login1Session *session,
GParamSpec *pspec,
gpointer user_data)
{
MetaLauncher *self = user_data;
sync_active (self);
}
static gboolean
get_kms_fd (Login1Session *session_proxy,
int *fd_out)
{
int major, minor;
int fd;
GError *error = NULL;
/* XXX -- use udev to find the DRM master device */
if (!get_device_info_from_path ("/dev/dri/card0", &major, &minor))
{
g_warning ("Could not stat /dev/dri/card0: %m");
return FALSE;
}
if (!take_device (session_proxy, major, minor, &fd, NULL, &error))
{
g_warning ("Could not open DRM device: %s\n", error->message);
g_error_free (error);
return FALSE;
}
*fd_out = fd;
return TRUE;
}
MetaLauncher *
meta_launcher_new (void)
{
MetaLauncher *self;
Login1Session *session_proxy;
GError *error = NULL;
int kms_fd;
session_proxy = get_session_proxy (NULL);
if (!login1_session_call_take_control_sync (session_proxy, FALSE, NULL, &error))
{
g_warning ("Could not take control: %s", error->message);
g_error_free (error);
return NULL;
}
if (!get_kms_fd (session_proxy, &kms_fd))
return NULL;
self = g_slice_new0 (MetaLauncher);
self->session_proxy = session_proxy;
self->seat_proxy = get_seat_proxy (NULL);
self->session_active = TRUE;
clutter_egl_set_kms_fd (kms_fd);
clutter_evdev_set_device_callbacks (on_evdev_device_open,
on_evdev_device_close,
self);
g_signal_connect (self->session_proxy, "notify::active", G_CALLBACK (on_active_changed), self);
return self;
}
void
meta_launcher_free (MetaLauncher *self)
{
g_object_unref (self->seat_proxy);
g_object_unref (self->session_proxy);
g_slice_free (MetaLauncher, self);
}
gboolean
meta_launcher_activate_session (MetaLauncher *launcher,
GError **error)
{
if (!login1_session_call_activate_sync (launcher->session_proxy, NULL, error))
return FALSE;
sync_active (launcher);
return TRUE;
}
gboolean
meta_launcher_activate_vt (MetaLauncher *launcher,
signed char vt,
GError **error)
{
return login1_seat_call_switch_to_sync (launcher->seat_proxy, vt, NULL, error);
}

View File

@ -1,37 +0,0 @@
/*
* Copyright (C) 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_LAUNCHER_H
#define META_LAUNCHER_H
#include <glib-object.h>
typedef struct _MetaLauncher MetaLauncher;
MetaLauncher *meta_launcher_new (void);
void meta_launcher_free (MetaLauncher *self);
gboolean meta_launcher_activate_session (MetaLauncher *self,
GError **error);
gboolean meta_launcher_activate_vt (MetaLauncher *self,
signed char vt,
GError **error);
#endif /* META_LAUNCHER_H */

View File

@ -1,939 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Author: Giovanni Campagna <gcampagn@redhat.com>
*/
#include "config.h"
#include "meta-monitor-manager-kms.h"
#include <string.h>
#include <stdlib.h>
#include <clutter/clutter.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <meta/main.h>
#include <meta/errors.h>
#include "edid.h"
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
typedef struct {
drmModeConnector *connector;
unsigned n_encoders;
drmModeEncoderPtr *encoders;
drmModeEncoderPtr current_encoder;
/* bitmasks of encoder position in the resources array */
uint32_t encoder_mask;
uint32_t enc_clone_mask;
uint32_t dpms_prop_id;
uint32_t edid_blob_id;
} MetaOutputKms;
struct _MetaMonitorManagerKms
{
MetaMonitorManager parent_instance;
int fd;
drmModeConnector **connectors;
unsigned int n_connectors;
drmModeEncoder **encoders;
unsigned int n_encoders;
drmModeEncoder *current_encoder;
};
struct _MetaMonitorManagerKmsClass
{
MetaMonitorManagerClass parent_class;
};
G_DEFINE_TYPE (MetaMonitorManagerKms, meta_monitor_manager_kms, META_TYPE_MONITOR_MANAGER);
static void
free_resources (MetaMonitorManagerKms *manager_kms)
{
unsigned i;
for (i = 0; i < manager_kms->n_encoders; i++)
drmModeFreeEncoder (manager_kms->encoders[i]);
for (i = 0; i < manager_kms->n_connectors; i++)
drmModeFreeConnector (manager_kms->connectors[i]);
g_free (manager_kms->encoders);
g_free (manager_kms->connectors);
}
static int
compare_outputs (const void *one,
const void *two)
{
const MetaOutput *o_one = one, *o_two = two;
return strcmp (o_one->name, o_two->name);
}
static char *
make_output_name (drmModeConnector *connector)
{
static const char * const connector_type_names[] = {
"unknown", "VGA", "DVII", "DVID", "DVID", "Composite",
"SVIDEO", "LVDS", "Component", "9PinDIN", "DisplayPort",
"HDMIA", "HDMIB", "TV", "eDP"
};
const char *connector_type_name;
if (connector->connector_type < G_N_ELEMENTS (connector_type_names))
connector_type_name = connector_type_names[connector->connector_type];
else
connector_type_name = "unknown";
return g_strdup_printf ("%s%d", connector_type_name, connector->connector_id);
}
static void
meta_output_destroy_notify (MetaOutput *output)
{
MetaOutputKms *output_kms;
unsigned i;
output_kms = output->driver_private;
for (i = 0; i < output_kms->n_encoders; i++)
drmModeFreeEncoder (output_kms->encoders[i]);
g_free (output_kms->encoders);
g_slice_free (MetaOutputKms, output_kms);
}
static void
meta_monitor_mode_destroy_notify (MetaMonitorMode *output)
{
g_slice_free (drmModeModeInfo, output->driver_private);
}
static gboolean
drm_mode_equal (gconstpointer one,
gconstpointer two)
{
const drmModeModeInfo *m_one = one;
const drmModeModeInfo *m_two = two;
return m_one->clock == m_two->clock &&
m_one->hdisplay == m_two->hdisplay &&
m_one->hsync_start == m_two->hsync_start &&
m_one->hsync_end == m_two->hsync_end &&
m_one->htotal == m_two->htotal &&
m_one->hskew == m_two->hskew &&
m_one->vdisplay == m_two->vdisplay &&
m_one->vsync_start == m_two->vsync_start &&
m_one->vsync_end == m_two->vsync_end &&
m_one->vtotal == m_two->vtotal &&
m_one->vscan == m_two->vscan &&
m_one->vrefresh == m_two->vrefresh &&
m_one->flags == m_two->flags &&
m_one->type == m_two->type &&
strncmp (m_one->name, m_two->name, DRM_DISPLAY_MODE_LEN) == 0;
}
static guint
drm_mode_hash (gconstpointer ptr)
{
const drmModeModeInfo *mode = ptr;
guint hash = 0;
/* We don't include the name in the hash because it's generally
derived from the other fields (hdisplay, vdisplay and flags)
*/
hash ^= mode->clock;
hash ^= mode->hdisplay ^ mode->hsync_start ^ mode->hsync_end;
hash ^= mode->vdisplay ^ mode->vsync_start ^ mode->vsync_end;
hash ^= mode->vrefresh;
hash ^= mode->flags ^ mode->type;
return hash;
}
static void
find_properties (MetaMonitorManagerKms *manager_kms,
MetaOutputKms *output_kms)
{
drmModePropertyPtr prop;
int i;
for (i = 0; i < output_kms->connector->count_props; i++)
{
prop = drmModeGetProperty (manager_kms->fd, output_kms->connector->props[i]);
if (!prop)
continue;
if ((prop->flags & DRM_MODE_PROP_ENUM) &&
strcmp(prop->name, "DPMS") == 0)
output_kms->dpms_prop_id = prop->prop_id;
else if ((prop->flags & DRM_MODE_PROP_BLOB) &&
strcmp (prop->name, "EDID") == 0)
output_kms->edid_blob_id = output_kms->connector->prop_values[i];
drmModeFreeProperty(prop);
}
}
static GBytes *
read_output_edid (MetaMonitorManagerKms *manager_kms,
MetaOutput *output)
{
MetaOutputKms *output_kms = output->driver_private;
drmModePropertyBlobPtr edid_blob = NULL;
if (output_kms->edid_blob_id == 0)
return NULL;
edid_blob = drmModeGetPropertyBlob (manager_kms->fd, output_kms->edid_blob_id);
if (!edid_blob)
{
meta_warning ("Failed to read EDID of output %s: %s\n", output->name, strerror(errno));
return NULL;
}
if (edid_blob->length > 0)
return g_bytes_new_with_free_func (edid_blob->data, edid_blob->length,
(GDestroyNotify)drmModeFreePropertyBlob, edid_blob);
else
{
drmModeFreePropertyBlob (edid_blob);
return NULL;
}
}
static MetaMonitorMode *
find_meta_mode (MetaMonitorManager *manager,
const drmModeModeInfo *drm_mode)
{
unsigned k;
for (k = 0; k < manager->n_modes; k++)
{
if (drm_mode_equal (drm_mode, manager->modes[k].driver_private))
return &manager->modes[k];
}
g_assert_not_reached ();
return NULL;
}
static MetaOutput *
find_output_by_id (MetaOutput *outputs,
unsigned n_outputs,
glong id)
{
unsigned i;
for (i = 0; i < n_outputs; i++)
if (outputs[i].output_id == id)
return &outputs[i];
return NULL;
}
static void
meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
{
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
drmModeRes *resources;
GHashTable *modes;
GHashTableIter iter;
drmModeModeInfo *mode;
unsigned int i, j, k;
unsigned int n_actual_outputs;
int width, height;
MetaOutput *old_outputs;
unsigned int n_old_outputs;
resources = drmModeGetResources(manager_kms->fd);
modes = g_hash_table_new (drm_mode_hash, drm_mode_equal);
manager->max_screen_width = resources->max_width;
manager->max_screen_height = resources->max_height;
manager->power_save_mode = META_POWER_SAVE_ON;
old_outputs = manager->outputs;
n_old_outputs = manager->n_outputs;
/* Note: we must not free the public structures (output, crtc, monitor
mode and monitor info) here, they must be kept alive until the API
users are done with them after we emit monitors-changed, and thus
are freed by the platform-independent layer. */
free_resources (manager_kms);
manager_kms->n_connectors = resources->count_connectors;
manager_kms->connectors = g_new (drmModeConnector *, manager_kms->n_connectors);
for (i = 0; i < manager_kms->n_connectors; i++)
{
drmModeConnector *connector;
connector = drmModeGetConnector (manager_kms->fd, resources->connectors[i]);
manager_kms->connectors[i] = connector;
if (connector->connection == DRM_MODE_CONNECTED)
{
/* Collect all modes for this connector */
for (j = 0; j < (unsigned)connector->count_modes; j++)
g_hash_table_add (modes, &connector->modes[j]);
}
}
manager_kms->n_encoders = resources->count_encoders;
manager_kms->encoders = g_new (drmModeEncoder *, manager_kms->n_encoders);
for (i = 0; i < manager_kms->n_encoders; i++)
{
manager_kms->encoders[i] = drmModeGetEncoder (manager_kms->fd,
resources->encoders[i]);
}
manager->n_modes = g_hash_table_size (modes);
manager->modes = g_new0 (MetaMonitorMode, manager->n_modes);
g_hash_table_iter_init (&iter, modes);
i = 0;
while (g_hash_table_iter_next (&iter, NULL, (gpointer)&mode))
{
MetaMonitorMode *meta_mode;
meta_mode = &manager->modes[i];
meta_mode->mode_id = i;
meta_mode->name = g_strndup (mode->name, DRM_DISPLAY_MODE_LEN);
meta_mode->width = mode->hdisplay;
meta_mode->height = mode->vdisplay;
meta_mode->refresh_rate = (1000 * mode->clock /
((float)mode->htotal * mode->vtotal));
meta_mode->driver_private = g_slice_dup (drmModeModeInfo, mode);
meta_mode->driver_notify = (GDestroyNotify)meta_monitor_mode_destroy_notify;
i++;
}
g_hash_table_destroy (modes);
manager->n_crtcs = resources->count_crtcs;
manager->crtcs = g_new0 (MetaCRTC, manager->n_crtcs);
width = 0; height = 0;
for (i = 0; i < (unsigned)resources->count_crtcs; i++)
{
drmModeCrtc *crtc;
MetaCRTC *meta_crtc;
crtc = drmModeGetCrtc (manager_kms->fd, resources->crtcs[i]);
meta_crtc = &manager->crtcs[i];
meta_crtc->crtc_id = crtc->crtc_id;
meta_crtc->rect.x = crtc->x;
meta_crtc->rect.y = crtc->y;
meta_crtc->rect.width = crtc->width;
meta_crtc->rect.height = crtc->height;
meta_crtc->is_dirty = FALSE;
meta_crtc->transform = WL_OUTPUT_TRANSFORM_NORMAL;
/* FIXME: implement! */
meta_crtc->all_transforms = 1 << WL_OUTPUT_TRANSFORM_NORMAL;
if (crtc->mode_valid)
{
for (j = 0; j < manager->n_modes; j++)
{
if (drm_mode_equal (&crtc->mode, manager->modes[j].driver_private))
{
meta_crtc->current_mode = &manager->modes[j];
break;
}
}
width = MAX (width, meta_crtc->rect.x + meta_crtc->rect.width);
height = MAX (height, meta_crtc->rect.y + meta_crtc->rect.height);
}
drmModeFreeCrtc (crtc);
}
manager->screen_width = width;
manager->screen_height = height;
manager->outputs = g_new0 (MetaOutput, manager_kms->n_connectors);
n_actual_outputs = 0;
for (i = 0; i < manager_kms->n_connectors; i++)
{
MetaOutput *meta_output, *old_output;
MetaOutputKms *output_kms;
drmModeConnector *connector;
GArray *crtcs;
unsigned int crtc_mask;
GBytes *edid;
connector = manager_kms->connectors[i];
meta_output = &manager->outputs[n_actual_outputs];
if (connector->connection == DRM_MODE_CONNECTED)
{
meta_output->driver_private = output_kms = g_slice_new0 (MetaOutputKms);
meta_output->driver_notify = (GDestroyNotify)meta_output_destroy_notify;
meta_output->output_id = connector->connector_id;
meta_output->name = make_output_name (connector);
meta_output->width_mm = connector->mmWidth;
meta_output->height_mm = connector->mmHeight;
switch (connector->subpixel)
{
case DRM_MODE_SUBPIXEL_NONE:
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_NONE;
break;
case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB:
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_HORIZONTAL_RGB;
break;
case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR:
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_HORIZONTAL_BGR;
break;
case DRM_MODE_SUBPIXEL_VERTICAL_RGB:
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_VERTICAL_RGB;
break;
case DRM_MODE_SUBPIXEL_VERTICAL_BGR:
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_VERTICAL_BGR;
break;
case DRM_MODE_SUBPIXEL_UNKNOWN:
default:
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
break;
}
meta_output->n_modes = connector->count_modes;
meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
for (j = 0; j < meta_output->n_modes; j++)
meta_output->modes[j] = find_meta_mode (manager, &connector->modes[j]);
meta_output->preferred_mode = meta_output->modes[0];
output_kms->connector = connector;
output_kms->n_encoders = connector->count_encoders;
output_kms->encoders = g_new0 (drmModeEncoderPtr, output_kms->n_encoders);
crtc_mask = ~(unsigned int)0;
for (j = 0; j < output_kms->n_encoders; j++)
{
output_kms->encoders[j] = drmModeGetEncoder (manager_kms->fd, connector->encoders[j]);
/* We only list CRTCs as supported if they are supported by all encoders
for this connectors.
This is what xf86-video-modesetting does (see drmmode_output_init())
*/
crtc_mask &= output_kms->encoders[j]->possible_crtcs;
if (output_kms->encoders[j]->encoder_id == connector->encoder_id)
output_kms->current_encoder = output_kms->encoders[j];
}
crtcs = g_array_new (FALSE, FALSE, sizeof (MetaCRTC*));
for (j = 0; j < manager->n_crtcs; j++)
{
if (crtc_mask & (1 << j))
{
MetaCRTC *crtc = &manager->crtcs[j];
g_array_append_val (crtcs, crtc);
}
}
meta_output->n_possible_crtcs = crtcs->len;
meta_output->possible_crtcs = (void*)g_array_free (crtcs, FALSE);
if (output_kms->current_encoder && output_kms->current_encoder->crtc_id != 0)
{
for (j = 0; j < manager->n_crtcs; j++)
{
if (manager->crtcs[j].crtc_id == output_kms->current_encoder->crtc_id)
{
meta_output->crtc = &manager->crtcs[j];
break;
}
}
}
else
meta_output->crtc = NULL;
old_output = find_output_by_id (old_outputs, n_old_outputs,
meta_output->output_id);
if (old_output)
{
meta_output->is_primary = old_output->is_primary;
meta_output->is_presentation = old_output->is_presentation;
}
else
{
meta_output->is_primary = FALSE;
meta_output->is_presentation = FALSE;
}
find_properties (manager_kms, output_kms);
edid = read_output_edid (manager_kms, meta_output);
if (edid)
{
MonitorInfo *parsed_edid;
gsize len;
parsed_edid = decode_edid (g_bytes_get_data (edid, &len));
if (parsed_edid)
{
meta_output->vendor = g_strndup (parsed_edid->manufacturer_code, 4);
meta_output->product = g_strndup (parsed_edid->dsc_product_name, 14);
meta_output->serial = g_strndup (parsed_edid->dsc_serial_number, 14);
g_free (parsed_edid);
}
g_bytes_unref (edid);
}
if (!meta_output->vendor)
{
meta_output->vendor = g_strdup ("unknown");
meta_output->product = g_strdup ("unknown");
meta_output->serial = g_strdup ("unknown");
}
/* FIXME: backlight is a very driver specific thing unfortunately,
every DDX does its own thing, and the dumb KMS API does not include it.
For example, xf86-video-intel has a list of paths to probe in /sys/class/backlight
(one for each major HW maker, and then some).
We can't do the same because we're not root.
It might be best to leave backlight out of the story and rely on the setuid
helper in gnome-settings-daemon.
*/
meta_output->backlight_min = 0;
meta_output->backlight_max = 0;
meta_output->backlight = -1;
n_actual_outputs++;
}
}
manager->n_outputs = n_actual_outputs;
manager->outputs = g_renew (MetaOutput, manager->outputs, manager->n_outputs);
/* Sort the outputs for easier handling in MetaMonitorConfig */
qsort (manager->outputs, manager->n_outputs, sizeof (MetaOutput), compare_outputs);
/* Now fix the clones.
Code mostly inspired by xf86-video-modesetting. */
/* XXX: intel hardware doesn't usually have clones, but I only have laptops with
intel cards, so this code was never tested! */
for (i = 0; i < manager->n_outputs; i++)
{
MetaOutput *meta_output;
MetaOutputKms *output_kms;
meta_output = &manager->outputs[i];
output_kms = meta_output->driver_private;
output_kms->enc_clone_mask = 0xff;
output_kms->encoder_mask = 0;
for (j = 0; j < output_kms->n_encoders; j++)
{
for (k = 0; k < manager_kms->n_encoders; k++)
{
if (output_kms->encoders[j]->encoder_id == manager_kms->encoders[k]->encoder_id)
{
output_kms->encoder_mask |= (1 << k);
break;
}
}
output_kms->enc_clone_mask &= output_kms->encoders[j]->possible_clones;
}
}
for (i = 0; i < manager->n_outputs; i++)
{
MetaOutput *meta_output;
MetaOutputKms *output_kms;
meta_output = &manager->outputs[i];
output_kms = meta_output->driver_private;
if (output_kms->enc_clone_mask == 0)
continue;
for (j = 0; j < manager->n_outputs; j++)
{
MetaOutput *meta_clone;
MetaOutputKms *clone_kms;
meta_clone = &manager->outputs[i];
clone_kms = meta_clone->driver_private;
if (meta_clone == meta_output)
continue;
if (clone_kms->encoder_mask == 0)
continue;
if (clone_kms->encoder_mask == output_kms->enc_clone_mask)
{
meta_output->n_possible_clones++;
meta_output->possible_clones = g_renew (MetaOutput *,
meta_output->possible_clones,
meta_output->n_possible_clones);
meta_output->possible_clones[meta_output->n_possible_clones - 1] = meta_clone;
}
}
}
drmModeFreeResources (resources);
}
static GBytes *
meta_monitor_manager_kms_read_edid (MetaMonitorManager *manager,
MetaOutput *output)
{
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
return read_output_edid (manager_kms, output);
}
static void
meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
MetaPowerSave mode)
{
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
uint64_t state;
unsigned i;
switch (mode) {
case META_POWER_SAVE_ON:
state = DRM_MODE_DPMS_ON;
break;
case META_POWER_SAVE_STANDBY:
state = DRM_MODE_DPMS_STANDBY;
break;
case META_POWER_SAVE_SUSPEND:
state = DRM_MODE_DPMS_SUSPEND;
break;
case META_POWER_SAVE_OFF:
state = DRM_MODE_DPMS_OFF;
break;
default:
return;
}
for (i = 0; i < manager->n_outputs; i++)
{
MetaOutput *meta_output;
MetaOutputKms *output_kms;
meta_output = &manager->outputs[i];
output_kms = meta_output->driver_private;
if (output_kms->dpms_prop_id != 0)
{
int ok = drmModeConnectorSetProperty(manager_kms->fd, meta_output->output_id,
output_kms->dpms_prop_id, state);
if (ok < 0)
meta_warning ("Failed to set power save mode for output %s: %s\n",
meta_output->name, strerror (errno));
}
}
}
static void
crtc_free (CoglKmsCrtc *crtc)
{
g_free (crtc->connectors);
g_slice_free (CoglKmsCrtc, crtc);
}
static void
meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
MetaCRTCInfo **crtcs,
unsigned int n_crtcs,
MetaOutputInfo **outputs,
unsigned int n_outputs)
{
ClutterBackend *backend;
CoglContext *cogl_context;
CoglDisplay *cogl_display;
unsigned i;
GPtrArray *cogl_crtcs;
int screen_width, screen_height;
gboolean ok;
GError *error;
cogl_crtcs = g_ptr_array_new_full (manager->n_crtcs, (GDestroyNotify)crtc_free);
screen_width = 0; screen_height = 0;
for (i = 0; i < n_crtcs; i++)
{
MetaCRTCInfo *crtc_info = crtcs[i];
MetaCRTC *crtc = crtc_info->crtc;
CoglKmsCrtc *cogl_crtc;
crtc->is_dirty = TRUE;
cogl_crtc = g_slice_new0 (CoglKmsCrtc);
g_ptr_array_add (cogl_crtcs, cogl_crtc);
if (crtc_info->mode == NULL)
{
cogl_crtc->id = crtc->crtc_id;
cogl_crtc->x = 0;
cogl_crtc->y = 0;
cogl_crtc->count = 0;
memset (&cogl_crtc->mode, 0, sizeof (drmModeModeInfo));
cogl_crtc->connectors = NULL;
cogl_crtc->count = 0;
crtc->rect.x = 0;
crtc->rect.y = 0;
crtc->rect.width = 0;
crtc->rect.height = 0;
crtc->current_mode = NULL;
}
else
{
MetaMonitorMode *mode;
uint32_t *connectors;
unsigned int j, n_connectors;
int width, height;
mode = crtc_info->mode;
cogl_crtc->id = crtc->crtc_id;
cogl_crtc->x = crtc_info->x;
cogl_crtc->y = crtc_info->y;
cogl_crtc->count = n_connectors = crtc_info->outputs->len;
cogl_crtc->connectors = connectors = g_new (uint32_t, n_connectors);
for (j = 0; j < n_connectors; j++)
{
MetaOutput *output = g_ptr_array_index (crtc_info->outputs, j);
connectors[j] = output->output_id;
output->is_dirty = TRUE;
output->crtc = crtc;
}
memcpy (&cogl_crtc->mode, crtc_info->mode->driver_private,
sizeof (drmModeModeInfo));
if (meta_monitor_transform_is_rotated (crtc_info->transform))
{
width = mode->height;
height = mode->width;
}
else
{
width = mode->width;
height = mode->height;
}
screen_width = MAX (screen_width, crtc_info->x + width);
screen_height = MAX (screen_height, crtc_info->y + height);
crtc->rect.x = crtc_info->x;
crtc->rect.y = crtc_info->y;
crtc->rect.width = width;
crtc->rect.height = height;
crtc->current_mode = mode;
crtc->transform = crtc_info->transform;
}
}
/* Disable CRTCs not mentioned in the list (they have is_dirty == FALSE,
because they weren't seen in the first loop) */
for (i = 0; i < manager->n_crtcs; i++)
{
MetaCRTC *crtc = &manager->crtcs[i];
CoglKmsCrtc *cogl_crtc;
crtc->logical_monitor = NULL;
if (crtc->is_dirty)
{
crtc->is_dirty = FALSE;
continue;
}
cogl_crtc = g_slice_new0 (CoglKmsCrtc);
g_ptr_array_add (cogl_crtcs, cogl_crtc);
cogl_crtc->id = crtc->crtc_id;
cogl_crtc->x = 0;
cogl_crtc->y = 0;
cogl_crtc->count = 0;
memset (&cogl_crtc->mode, 0, sizeof (drmModeModeInfo));
cogl_crtc->connectors = NULL;
cogl_crtc->count = 0;
crtc->rect.x = 0;
crtc->rect.y = 0;
crtc->rect.width = 0;
crtc->rect.height = 0;
crtc->current_mode = NULL;
}
backend = clutter_get_default_backend ();
cogl_context = clutter_backend_get_cogl_context (backend);
cogl_display = cogl_context_get_display (cogl_context);
error = NULL;
ok = cogl_kms_display_set_layout (cogl_display, screen_width, screen_height,
(CoglKmsCrtc**)cogl_crtcs->pdata, cogl_crtcs->len, &error);
g_ptr_array_unref (cogl_crtcs);
if (!ok)
{
meta_warning ("Applying display configuration failed: %s\n", error->message);
g_error_free (error);
return;
}
for (i = 0; i < n_outputs; i++)
{
MetaOutputInfo *output_info = outputs[i];
MetaOutput *output = output_info->output;
output->is_primary = output_info->is_primary;
output->is_presentation = output_info->is_presentation;
}
/* Disable outputs not mentioned in the list */
for (i = 0; i < manager->n_outputs; i++)
{
MetaOutput *output = &manager->outputs[i];
if (output->is_dirty)
{
output->is_dirty = FALSE;
continue;
}
output->crtc = NULL;
output->is_primary = FALSE;
}
manager->screen_width = screen_width;
manager->screen_height = screen_height;
meta_monitor_manager_rebuild_derived (manager);
}
static void
meta_monitor_manager_kms_get_crtc_gamma (MetaMonitorManager *manager,
MetaCRTC *crtc,
gsize *size,
unsigned short **red,
unsigned short **green,
unsigned short **blue)
{
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
drmModeCrtc *kms_crtc;
kms_crtc = drmModeGetCrtc (manager_kms->fd, crtc->crtc_id);
*size = kms_crtc->gamma_size;
*red = g_new (unsigned short, *size);
*green = g_new (unsigned short, *size);
*blue = g_new (unsigned short, *size);
drmModeCrtcGetGamma (manager_kms->fd, crtc->crtc_id, *size, *red, *green, *blue);
drmModeFreeCrtc (kms_crtc);
}
static void
meta_monitor_manager_kms_set_crtc_gamma (MetaMonitorManager *manager,
MetaCRTC *crtc,
gsize size,
unsigned short *red,
unsigned short *green,
unsigned short *blue)
{
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
drmModeCrtcSetGamma (manager_kms->fd, crtc->crtc_id, size, red, green, blue);
}
static void
meta_monitor_manager_kms_init (MetaMonitorManagerKms *manager_kms)
{
ClutterBackend *backend;
CoglContext *cogl_context;
CoglDisplay *cogl_display;
CoglRenderer *cogl_renderer;
backend = clutter_get_default_backend ();
cogl_context = clutter_backend_get_cogl_context (backend);
cogl_display = cogl_context_get_display (cogl_context);
cogl_renderer = cogl_display_get_renderer (cogl_display);
manager_kms->fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
}
static void
meta_monitor_manager_kms_finalize (GObject *object)
{
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (object);
free_resources (manager_kms);
G_OBJECT_CLASS (meta_monitor_manager_kms_parent_class)->finalize (object);
}
static void
meta_monitor_manager_kms_class_init (MetaMonitorManagerKmsClass *klass)
{
MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_monitor_manager_kms_finalize;
manager_class->read_current = meta_monitor_manager_kms_read_current;
manager_class->read_edid = meta_monitor_manager_kms_read_edid;
manager_class->apply_configuration = meta_monitor_manager_kms_apply_configuration;
manager_class->set_power_save_mode = meta_monitor_manager_kms_set_power_save_mode;
manager_class->get_crtc_gamma = meta_monitor_manager_kms_get_crtc_gamma;
manager_class->set_crtc_gamma = meta_monitor_manager_kms_set_crtc_gamma;
}

View File

@ -1,40 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2001 Havoc Pennington
* Copyright (C) 2003 Rob Adams
* Copyright (C) 2004-2006 Elijah Newren
* Copyright (C) 2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_MONITOR_MANAGER_KMS_H
#define META_MONITOR_MANAGER_KMS_H
#include "meta-monitor-manager.h"
#define META_TYPE_MONITOR_MANAGER_KMS (meta_monitor_manager_kms_get_type ())
#define META_MONITOR_MANAGER_KMS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKms))
#define META_MONITOR_MANAGER_KMS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKmsClass))
#define META_IS_MONITOR_MANAGER_KMS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_MANAGER_KMS))
#define META_IS_MONITOR_MANAGER_KMS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MONITOR_MANAGER_KMS))
#define META_MONITOR_MANAGER_KMS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKmsClass))
typedef struct _MetaMonitorManagerKmsClass MetaMonitorManagerKmsClass;
typedef struct _MetaMonitorManagerKms MetaMonitorManagerKms;
GType meta_monitor_manager_kms_get_type (void);
#endif /* META_MONITOR_MANAGER_KMS_H */

View File

@ -1,406 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#include "config.h"
#include "meta-backend-x11.h"
#include <clutter/x11/clutter-x11.h>
#include <X11/extensions/sync.h>
#include "meta-idle-monitor-xsync.h"
#include "meta-monitor-manager-xrandr.h"
#include "backends/meta-monitor-manager-dummy.h"
#include "meta-cursor-renderer-x11.h"
#include <meta/util.h>
#include "display-private.h"
#include "compositor/compositor-private.h"
struct _MetaBackendX11Private
{
/* The host X11 display */
Display *xdisplay;
GSource *source;
int xsync_event_base;
int xsync_error_base;
int xinput_opcode;
int xinput_event_base;
int xinput_error_base;
};
typedef struct _MetaBackendX11Private MetaBackendX11Private;
G_DEFINE_TYPE_WITH_PRIVATE (MetaBackendX11, meta_backend_x11, META_TYPE_BACKEND);
static void
handle_alarm_notify (MetaBackend *backend,
XEvent *event)
{
int i;
for (i = 0; i <= backend->device_id_max; i++)
if (backend->device_monitors[i])
meta_idle_monitor_xsync_handle_xevent (backend->device_monitors[i], (XSyncAlarmNotifyEvent*) event);
}
static void
translate_device_event (MetaBackendX11 *x11,
XIDeviceEvent *device_event)
{
Window stage_window = meta_backend_x11_get_xwindow (x11);
if (device_event->event != stage_window)
{
/* This codepath should only ever trigger as an X11 compositor,
* and never under nested, as under nested all backend events
* should be reported with respect to the stage window. */
g_assert (!meta_is_wayland_compositor ());
device_event->event = stage_window;
/* As an X11 compositor, the stage window is always at 0,0, so
* using root coordinates will give us correct stage coordinates
* as well... */
device_event->event_x = device_event->root_x;
device_event->event_y = device_event->root_y;
}
}
/* Clutter makes the assumption that there is only one X window
* per stage, which is a valid assumption to make for a generic
* application toolkit. As such, it will ignore any events sent
* to the a stage that isn't its X window.
*
* When running as an X window manager, we need to respond to
* events from lots of windows. Trick Clutter into translating
* these events by pretending we got an event on the stage window.
*/
static void
maybe_spoof_event_as_stage_event (MetaBackendX11 *x11,
XEvent *event)
{
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
if (event->type == GenericEvent &&
event->xcookie.extension == priv->xinput_opcode)
{
XIEvent *input_event = (XIEvent *) event->xcookie.data;
switch (input_event->evtype)
{
case XI_Motion:
case XI_ButtonPress:
case XI_ButtonRelease:
case XI_KeyPress:
case XI_KeyRelease:
translate_device_event (x11, (XIDeviceEvent *) input_event);
break;
default:
break;
}
}
}
static void
handle_host_xevent (MetaBackend *backend,
XEvent *event)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
gboolean bypass_clutter = FALSE;
XGetEventData (priv->xdisplay, &event->xcookie);
if (event->type == (priv->xsync_event_base + XSyncAlarmNotify))
handle_alarm_notify (backend, event);
{
MetaMonitorManager *manager = meta_backend_get_monitor_manager (backend);
if (META_IS_MONITOR_MANAGER_XRANDR (manager) &&
meta_monitor_manager_xrandr_handle_xevent (META_MONITOR_MANAGER_XRANDR (manager), event))
{
bypass_clutter = TRUE;
goto out;
}
}
maybe_spoof_event_as_stage_event (x11, event);
out:
if (!bypass_clutter)
clutter_x11_handle_event (event);
XFreeEventData (priv->xdisplay, &event->xcookie);
}
typedef struct {
GSource base;
GPollFD event_poll_fd;
MetaBackend *backend;
} XEventSource;
static gboolean
x_event_source_prepare (GSource *source,
int *timeout)
{
XEventSource *x_source = (XEventSource *) source;
MetaBackend *backend = x_source->backend;
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
*timeout = -1;
return XPending (priv->xdisplay);
}
static gboolean
x_event_source_check (GSource *source)
{
XEventSource *x_source = (XEventSource *) source;
MetaBackend *backend = x_source->backend;
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
return XPending (priv->xdisplay);
}
static gboolean
x_event_source_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
XEventSource *x_source = (XEventSource *) source;
MetaBackend *backend = x_source->backend;
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
while (XPending (priv->xdisplay))
{
XEvent event;
XNextEvent (priv->xdisplay, &event);
handle_host_xevent (backend, &event);
}
return TRUE;
}
static GSourceFuncs x_event_funcs = {
x_event_source_prepare,
x_event_source_check,
x_event_source_dispatch,
};
static GSource *
x_event_source_new (MetaBackend *backend)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
GSource *source;
XEventSource *x_source;
source = g_source_new (&x_event_funcs, sizeof (XEventSource));
x_source = (XEventSource *) source;
x_source->backend = backend;
x_source->event_poll_fd.fd = ConnectionNumber (priv->xdisplay);
x_source->event_poll_fd.events = G_IO_IN;
g_source_add_poll (source, &x_source->event_poll_fd);
g_source_attach (source, NULL);
return source;
}
static void
meta_backend_x11_post_init (MetaBackend *backend)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
int major, minor;
priv->xdisplay = clutter_x11_get_default_display ();
priv->source = x_event_source_new (backend);
if (!XSyncQueryExtension (priv->xdisplay, &priv->xsync_event_base, &priv->xsync_error_base) ||
!XSyncInitialize (priv->xdisplay, &major, &minor))
meta_fatal ("Could not initialize XSync");
{
int major = 2, minor = 3;
gboolean has_xi = FALSE;
if (XQueryExtension (priv->xdisplay,
"XInputExtension",
&priv->xinput_opcode,
&priv->xinput_error_base,
&priv->xinput_event_base))
{
if (XIQueryVersion (priv->xdisplay, &major, &minor) == Success)
{
int version = (major * 10) + minor;
if (version >= 22)
has_xi = TRUE;
}
}
if (!has_xi)
meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer\n");
}
META_BACKEND_CLASS (meta_backend_x11_parent_class)->post_init (backend);
}
static MetaIdleMonitor *
meta_backend_x11_create_idle_monitor (MetaBackend *backend,
int device_id)
{
return g_object_new (META_TYPE_IDLE_MONITOR_XSYNC,
"device-id", device_id,
NULL);
}
static MetaMonitorManager *
meta_backend_x11_create_monitor_manager (MetaBackend *backend)
{
/* If we're a Wayland compositor using the X11 backend,
* we're a nested configuration, so return the dummy
* monitor setup. */
if (meta_is_wayland_compositor ())
return g_object_new (META_TYPE_MONITOR_MANAGER_DUMMY, NULL);
return g_object_new (META_TYPE_MONITOR_MANAGER_XRANDR, NULL);
}
static MetaCursorRenderer *
meta_backend_x11_create_cursor_renderer (MetaBackend *backend)
{
return g_object_new (META_TYPE_CURSOR_RENDERER_X11, NULL);
}
static gboolean
meta_backend_x11_grab_device (MetaBackend *backend,
int device_id,
uint32_t timestamp)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
int ret;
XISetMask (mask.mask, XI_ButtonPress);
XISetMask (mask.mask, XI_ButtonRelease);
XISetMask (mask.mask, XI_Enter);
XISetMask (mask.mask, XI_Leave);
XISetMask (mask.mask, XI_Motion);
XISetMask (mask.mask, XI_KeyPress);
XISetMask (mask.mask, XI_KeyRelease);
ret = XIGrabDevice (priv->xdisplay, device_id,
meta_backend_x11_get_xwindow (x11),
timestamp,
None,
XIGrabModeAsync, XIGrabModeAsync,
False, /* owner_events */
&mask);
return (ret == Success);
}
static gboolean
meta_backend_x11_ungrab_device (MetaBackend *backend,
int device_id,
uint32_t timestamp)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
int ret;
ret = XIUngrabDevice (priv->xdisplay, device_id, timestamp);
return (ret == Success);
}
static void
meta_backend_x11_warp_pointer (MetaBackend *backend,
int x,
int y)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
XIWarpPointer (priv->xdisplay,
META_VIRTUAL_CORE_POINTER_ID,
None,
meta_backend_x11_get_xwindow (x11),
0, 0, 0, 0,
x, y);
}
static void
meta_backend_x11_class_init (MetaBackendX11Class *klass)
{
MetaBackendClass *backend_class = META_BACKEND_CLASS (klass);
backend_class->post_init = meta_backend_x11_post_init;
backend_class->create_idle_monitor = meta_backend_x11_create_idle_monitor;
backend_class->create_monitor_manager = meta_backend_x11_create_monitor_manager;
backend_class->create_cursor_renderer = meta_backend_x11_create_cursor_renderer;
backend_class->grab_device = meta_backend_x11_grab_device;
backend_class->ungrab_device = meta_backend_x11_ungrab_device;
backend_class->warp_pointer = meta_backend_x11_warp_pointer;
}
static void
meta_backend_x11_init (MetaBackendX11 *x11)
{
/* We do X11 event retrieval ourselves */
clutter_x11_disable_event_retrieval ();
}
Display *
meta_backend_x11_get_xdisplay (MetaBackendX11 *x11)
{
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
return priv->xdisplay;
}
Window
meta_backend_x11_get_xwindow (MetaBackendX11 *x11)
{
MetaDisplay *display = meta_get_display ();
MetaCompositor *compositor = display->compositor;
if (compositor == NULL)
return None;
ClutterStage *stage = CLUTTER_STAGE (compositor->stage);
return clutter_x11_get_stage_window (stage);
}

View File

@ -1,58 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#ifndef META_BACKEND_X11_H
#define META_BACKEND_X11_H
#include "backends/meta-backend-private.h"
#include <X11/Xlib.h>
#define META_TYPE_BACKEND_X11 (meta_backend_x11_get_type ())
#define META_BACKEND_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BACKEND_X11, MetaBackendX11))
#define META_BACKEND_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_BACKEND_X11, MetaBackendX11Class))
#define META_IS_BACKEND_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_BACKEND_X11))
#define META_IS_BACKEND_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_BACKEND_X11))
#define META_BACKEND_X11_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_BACKEND_X11, MetaBackendX11Class))
typedef struct _MetaBackendX11 MetaBackendX11;
typedef struct _MetaBackendX11Class MetaBackendX11Class;
struct _MetaBackendX11
{
MetaBackend parent;
};
struct _MetaBackendX11Class
{
MetaBackendClass parent_class;
};
GType meta_backend_x11_get_type (void) G_GNUC_CONST;
Display * meta_backend_x11_get_xdisplay (MetaBackendX11 *backend);
Window meta_backend_x11_get_xwindow (MetaBackendX11 *backend);
#endif /* META_BACKEND_X11_H */

View File

@ -1,99 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#include "config.h"
#include "meta-cursor-renderer-x11.h"
#include "meta-backend-x11.h"
#include "meta-stage.h"
struct _MetaCursorRendererX11Private
{
gboolean server_cursor_visible;
};
typedef struct _MetaCursorRendererX11Private MetaCursorRendererX11Private;
G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRendererX11, meta_cursor_renderer_x11, META_TYPE_CURSOR_RENDERER);
static gboolean
meta_cursor_renderer_x11_update_cursor (MetaCursorRenderer *renderer)
{
MetaCursorRendererX11 *x11 = META_CURSOR_RENDERER_X11 (renderer);
MetaCursorRendererX11Private *priv = meta_cursor_renderer_x11_get_instance_private (x11);
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
Window xwindow = meta_backend_x11_get_xwindow (backend);
if (xwindow == None)
return FALSE;
Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
MetaCursorReference *cursor_ref = meta_cursor_renderer_get_cursor (renderer);
gboolean has_server_cursor = FALSE;
if (cursor_ref)
{
MetaCursor cursor = meta_cursor_reference_get_meta_cursor (cursor_ref);
if (cursor != META_CURSOR_NONE)
{
Cursor xcursor = meta_cursor_create_x_cursor (xdisplay, cursor);
XDefineCursor (xdisplay, xwindow, xcursor);
XFlush (xdisplay);
XFreeCursor (xdisplay, xcursor);
has_server_cursor = TRUE;
}
}
if (has_server_cursor != priv->server_cursor_visible)
{
if (has_server_cursor)
XFixesShowCursor (xdisplay, xwindow);
else
XFixesHideCursor (xdisplay, xwindow);
priv->server_cursor_visible = has_server_cursor;
}
return priv->server_cursor_visible;
}
static void
meta_cursor_renderer_x11_class_init (MetaCursorRendererX11Class *klass)
{
MetaCursorRendererClass *renderer_class = META_CURSOR_RENDERER_CLASS (klass);
renderer_class->update_cursor = meta_cursor_renderer_x11_update_cursor;
}
static void
meta_cursor_renderer_x11_init (MetaCursorRendererX11 *x11)
{
MetaCursorRendererX11Private *priv = meta_cursor_renderer_x11_get_instance_private (x11);
/* XFixes has no way to retrieve the current cursor visibility. */
priv->server_cursor_visible = TRUE;
}

View File

@ -1,52 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#ifndef META_CURSOR_RENDERER_X11_H
#define META_CURSOR_RENDERER_X11_H
#include "meta-cursor-renderer.h"
#define META_TYPE_CURSOR_RENDERER_X11 (meta_cursor_renderer_x11_get_type ())
#define META_CURSOR_RENDERER_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CURSOR_RENDERER_X11, MetaCursorRendererX11))
#define META_CURSOR_RENDERER_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_CURSOR_RENDERER_X11, MetaCursorRendererX11Class))
#define META_IS_CURSOR_RENDERER_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_CURSOR_RENDERER_X11))
#define META_IS_CURSOR_RENDERER_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_CURSOR_RENDERER_X11))
#define META_CURSOR_RENDERER_X11_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_CURSOR_RENDERER_X11, MetaCursorRendererX11Class))
typedef struct _MetaCursorRendererX11 MetaCursorRendererX11;
typedef struct _MetaCursorRendererX11Class MetaCursorRendererX11Class;
struct _MetaCursorRendererX11
{
MetaCursorRenderer parent;
};
struct _MetaCursorRendererX11Class
{
MetaCursorRendererClass parent_class;
};
GType meta_cursor_renderer_x11_get_type (void) G_GNUC_CONST;
#endif /* META_CURSOR_RENDERER_X11_H */

View File

@ -1,367 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
*/
#include "config.h"
#include "meta-idle-monitor-xsync.h"
#include "meta-idle-monitor-private.h"
#include "meta-backend-x11.h"
#include <string.h>
struct _MetaIdleMonitorXSync
{
MetaIdleMonitor parent;
GHashTable *alarms;
Display *display;
XSyncCounter counter;
XSyncAlarm user_active_alarm;
};
struct _MetaIdleMonitorXSyncClass
{
MetaIdleMonitorClass parent_class;
};
typedef struct {
MetaIdleMonitorWatch base;
XSyncAlarm xalarm;
} MetaIdleMonitorWatchXSync;
G_DEFINE_TYPE (MetaIdleMonitorXSync, meta_idle_monitor_xsync, META_TYPE_IDLE_MONITOR)
static gint64
_xsyncvalue_to_int64 (XSyncValue value)
{
return ((guint64) XSyncValueHigh32 (value)) << 32
| (guint64) XSyncValueLow32 (value);
}
#define GUINT64_TO_XSYNCVALUE(value, ret) XSyncIntsToValue (ret, (value) & 0xFFFFFFFF, ((guint64)(value)) >> 32)
static XSyncAlarm
_xsync_alarm_set (MetaIdleMonitorXSync *monitor_xsync,
XSyncTestType test_type,
guint64 interval,
gboolean want_events)
{
XSyncAlarmAttributes attr;
XSyncValue delta;
guint flags;
flags = XSyncCACounter | XSyncCAValueType | XSyncCATestType |
XSyncCAValue | XSyncCADelta | XSyncCAEvents;
XSyncIntToValue (&delta, 0);
attr.trigger.counter = monitor_xsync->counter;
attr.trigger.value_type = XSyncAbsolute;
attr.delta = delta;
attr.events = want_events;
GUINT64_TO_XSYNCVALUE (interval, &attr.trigger.wait_value);
attr.trigger.test_type = test_type;
return XSyncCreateAlarm (monitor_xsync->display, flags, &attr);
}
static void
ensure_alarm_rescheduled (Display *dpy,
XSyncAlarm alarm)
{
XSyncAlarmAttributes attr;
/* Some versions of Xorg have an issue where alarms aren't
* always rescheduled. Calling XSyncChangeAlarm, even
* without any attributes, will reschedule the alarm. */
XSyncChangeAlarm (dpy, alarm, 0, &attr);
}
static void
set_alarm_enabled (Display *dpy,
XSyncAlarm alarm,
gboolean enabled)
{
XSyncAlarmAttributes attr;
attr.events = enabled;
XSyncChangeAlarm (dpy, alarm, XSyncCAEvents, &attr);
}
static void
check_x11_watch (gpointer data,
gpointer user_data)
{
MetaIdleMonitorWatchXSync *watch_xsync = data;
MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_xsync;
XSyncAlarm alarm = (XSyncAlarm) user_data;
if (watch_xsync->xalarm != alarm)
return;
_meta_idle_monitor_watch_fire (watch);
}
static char *
counter_name_for_device (int device_id)
{
if (device_id > 0)
return g_strdup_printf ("DEVICEIDLETIME %d", device_id);
return g_strdup ("IDLETIME");
}
static XSyncCounter
find_idletime_counter (MetaIdleMonitorXSync *monitor_xsync)
{
MetaIdleMonitor *monitor = META_IDLE_MONITOR (monitor_xsync);
int i;
int ncounters;
XSyncSystemCounter *counters;
XSyncCounter counter = None;
char *counter_name;
counter_name = counter_name_for_device (monitor->device_id);
counters = XSyncListSystemCounters (monitor_xsync->display, &ncounters);
for (i = 0; i < ncounters; i++)
{
if (counters[i].name != NULL && strcmp (counters[i].name, counter_name) == 0)
{
counter = counters[i].counter;
break;
}
}
XSyncFreeSystemCounterList (counters);
g_free (counter_name);
return counter;
}
static void
init_xsync (MetaIdleMonitorXSync *monitor_xsync)
{
monitor_xsync->counter = find_idletime_counter (monitor_xsync);
/* IDLETIME counter not found? */
if (monitor_xsync->counter == None)
{
g_warning ("IDLETIME counter not found\n");
return;
}
monitor_xsync->user_active_alarm = _xsync_alarm_set (monitor_xsync, XSyncNegativeTransition, 1, FALSE);
}
static void
meta_idle_monitor_xsync_dispose (GObject *object)
{
MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (object);
if (monitor_xsync->user_active_alarm != None)
{
XSyncDestroyAlarm (monitor_xsync->display, monitor_xsync->user_active_alarm);
monitor_xsync->user_active_alarm = None;
}
g_clear_pointer (&monitor_xsync->alarms, g_hash_table_destroy);
G_OBJECT_CLASS (meta_idle_monitor_xsync_parent_class)->dispose (object);
}
static void
meta_idle_monitor_xsync_constructed (GObject *object)
{
MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (object);
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
monitor_xsync->display = meta_backend_x11_get_xdisplay (backend);
init_xsync (monitor_xsync);
G_OBJECT_CLASS (meta_idle_monitor_xsync_parent_class)->constructed (object);
}
static gint64
meta_idle_monitor_xsync_get_idletime (MetaIdleMonitor *monitor)
{
MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (monitor);
XSyncValue value;
if (!XSyncQueryCounter (monitor_xsync->display, monitor_xsync->counter, &value))
return -1;
return _xsyncvalue_to_int64 (value);
}
static gboolean
fire_watch_idle (gpointer data)
{
MetaIdleMonitorWatch *watch = data;
watch->idle_source_id = 0;
_meta_idle_monitor_watch_fire (watch);
return FALSE;
}
static guint32
get_next_watch_serial (void)
{
static guint32 serial = 0;
g_atomic_int_inc (&serial);
return serial;
}
static void
free_watch (gpointer data)
{
MetaIdleMonitorWatchXSync *watch_xsync = data;
MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_xsync;
MetaIdleMonitor *monitor = watch->monitor;
MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (monitor);
g_object_ref (monitor);
if (watch->idle_source_id)
{
g_source_remove (watch->idle_source_id);
watch->idle_source_id = 0;
}
if (watch->notify != NULL)
watch->notify (watch->user_data);
if (watch_xsync->xalarm != monitor_xsync->user_active_alarm &&
watch_xsync->xalarm != None)
{
XSyncDestroyAlarm (monitor_xsync->display, watch_xsync->xalarm);
g_hash_table_remove (monitor_xsync->alarms, (gpointer) watch_xsync->xalarm);
}
g_object_unref (monitor);
g_slice_free (MetaIdleMonitorWatchXSync, watch_xsync);
}
static MetaIdleMonitorWatch *
meta_idle_monitor_xsync_make_watch (MetaIdleMonitor *monitor,
guint64 timeout_msec,
MetaIdleMonitorWatchFunc callback,
gpointer user_data,
GDestroyNotify notify)
{
MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (monitor);
MetaIdleMonitorWatchXSync *watch_xsync;
MetaIdleMonitorWatch *watch;
watch_xsync = g_slice_new0 (MetaIdleMonitorWatchXSync);
watch = (MetaIdleMonitorWatch *) watch_xsync;
watch->monitor = monitor;
watch->id = get_next_watch_serial ();
watch->callback = callback;
watch->user_data = user_data;
watch->notify = notify;
watch->timeout_msec = timeout_msec;
if (monitor_xsync->user_active_alarm != None)
{
if (timeout_msec != 0)
{
watch_xsync->xalarm = _xsync_alarm_set (monitor_xsync, XSyncPositiveTransition, timeout_msec, TRUE);
g_hash_table_add (monitor_xsync->alarms, (gpointer) watch_xsync->xalarm);
if (meta_idle_monitor_get_idletime (monitor) > (gint64)timeout_msec)
{
watch->idle_source_id = g_idle_add (fire_watch_idle, watch);
g_source_set_name_by_id (watch->idle_source_id, "[mutter] fire_watch_idle");
}
}
else
{
watch_xsync->xalarm = monitor_xsync->user_active_alarm;
set_alarm_enabled (monitor_xsync->display, monitor_xsync->user_active_alarm, TRUE);
}
}
return watch;
}
static void
meta_idle_monitor_xsync_class_init (MetaIdleMonitorXSyncClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
MetaIdleMonitorClass *idle_monitor_class = META_IDLE_MONITOR_CLASS (klass);
object_class->dispose = meta_idle_monitor_xsync_dispose;
object_class->constructed = meta_idle_monitor_xsync_constructed;
idle_monitor_class->get_idletime = meta_idle_monitor_xsync_get_idletime;
idle_monitor_class->make_watch = meta_idle_monitor_xsync_make_watch;
}
static void
meta_idle_monitor_xsync_init (MetaIdleMonitorXSync *monitor_xsync)
{
MetaIdleMonitor *monitor = META_IDLE_MONITOR (monitor_xsync);
monitor->watches = g_hash_table_new_full (NULL, NULL, NULL, free_watch);
monitor_xsync->alarms = g_hash_table_new (NULL, NULL);
}
void
meta_idle_monitor_xsync_handle_xevent (MetaIdleMonitor *monitor,
XSyncAlarmNotifyEvent *alarm_event)
{
MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (monitor);
XSyncAlarm alarm;
GList *watches;
gboolean has_alarm;
if (alarm_event->state != XSyncAlarmActive)
return;
alarm = alarm_event->alarm;
has_alarm = FALSE;
if (alarm == monitor_xsync->user_active_alarm)
{
set_alarm_enabled (monitor_xsync->display,
alarm,
FALSE);
has_alarm = TRUE;
}
else if (g_hash_table_contains (monitor_xsync->alarms, (gpointer) alarm))
{
ensure_alarm_rescheduled (monitor_xsync->display,
alarm);
has_alarm = TRUE;
}
if (has_alarm)
{
watches = g_hash_table_get_values (monitor->watches);
g_list_foreach (watches, check_x11_watch, (gpointer) alarm);
g_list_free (watches);
}
}

View File

@ -1,47 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
*/
#ifndef META_IDLE_MONITOR_XSYNC_H
#define META_IDLE_MONITOR_XSYNC_H
#include <glib-object.h>
#include <meta/meta-idle-monitor.h>
#include <X11/Xlib.h>
#include <X11/extensions/sync.h>
#define META_TYPE_IDLE_MONITOR_XSYNC (meta_idle_monitor_xsync_get_type ())
#define META_IDLE_MONITOR_XSYNC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_IDLE_MONITOR_XSYNC, MetaIdleMonitorXSync))
#define META_IDLE_MONITOR_XSYNC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_IDLE_MONITOR_XSYNC, MetaIdleMonitorXSyncClass))
#define META_IS_IDLE_MONITOR_XSYNC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_IDLE_MONITOR_XSYNC))
#define META_IS_IDLE_MONITOR_XSYNC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_IDLE_MONITOR_XSYNC))
#define META_IDLE_MONITOR_XSYNC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_IDLE_MONITOR_XSYNC, MetaIdleMonitorXSyncClass))
typedef struct _MetaIdleMonitorXSync MetaIdleMonitorXSync;
typedef struct _MetaIdleMonitorXSyncClass MetaIdleMonitorXSyncClass;
GType meta_idle_monitor_xsync_get_type (void);
void meta_idle_monitor_xsync_handle_xevent (MetaIdleMonitor *monitor,
XSyncAlarmNotifyEvent *xevent);
#endif /* META_IDLE_MONITOR_XSYNC_H */

View File

@ -1,43 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2001 Havoc Pennington
* Copyright (C) 2003 Rob Adams
* Copyright (C) 2004-2006 Elijah Newren
* Copyright (C) 2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef META_MONITOR_MANAGER_XRANDR_H
#define META_MONITOR_MANAGER_XRANDR_H
#include "meta-monitor-manager.h"
#define META_TYPE_MONITOR_MANAGER_XRANDR (meta_monitor_manager_xrandr_get_type ())
#define META_MONITOR_MANAGER_XRANDR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandr))
#define META_MONITOR_MANAGER_XRANDR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandrClass))
#define META_IS_MONITOR_MANAGER_XRANDR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_MANAGER_XRANDR))
#define META_IS_MONITOR_MANAGER_XRANDR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MONITOR_MANAGER_XRANDR))
#define META_MONITOR_MANAGER_XRANDR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandrClass))
typedef struct _MetaMonitorManagerXrandrClass MetaMonitorManagerXrandrClass;
typedef struct _MetaMonitorManagerXrandr MetaMonitorManagerXrandr;
GType meta_monitor_manager_xrandr_get_type (void);
gboolean meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager,
XEvent *event);
#endif /* META_MONITOR_MANAGER_XRANDR_H */

View File

@ -16,7 +16,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include "clutter-utils.h"
@ -93,10 +95,8 @@ meta_actor_vertices_are_untransformed (ClutterVertex *verts,
v3x != v1x || v3y != v2y)
return FALSE;
if (x_origin)
*x_origin = x;
if (y_origin)
*y_origin = y;
*x_origin = x;
*y_origin = y;
return TRUE;
}

View File

@ -15,7 +15,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __META_CLUTTER_UTILS_H__

View File

@ -16,7 +16,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <clutter/clutter.h>
@ -68,7 +70,7 @@ meta_create_color_texture_4ub (guint8 red,
/**
* meta_create_texture_pipeline:
* @src_texture: (nullable): texture to use initially for the layer
* @src_texture: (allow-none): texture to use initially for the layer
*
* Creates a pipeline with a single layer. Using a common template
* makes it easier for Cogl to share a shader for different uses in

View File

@ -15,7 +15,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __META_COGL_UTILS_H__

View File

@ -11,53 +11,68 @@
#include "meta-window-actor-private.h"
#include <clutter/clutter.h>
typedef struct _MetaCompScreen MetaCompScreen;
struct _MetaCompositor
{
MetaDisplay *display;
guint pre_paint_func_id;
guint post_paint_func_id;
guint repaint_func_id;
ClutterActor *shadow_src;
MetaPlugin *modal_plugin;
gint64 server_time_query_time;
gint64 server_time_offset;
guint server_time_is_monotonic_time : 1;
guint show_redraw : 1;
guint debug : 1;
guint no_mipmaps : 1;
};
ClutterActor *stage, *window_group, *top_window_group;
struct _MetaCompScreen
{
MetaScreen *screen;
ClutterActor *stage, *window_group, *top_window_group, *overlay_group;
ClutterActor *background_actor;
GList *windows;
GHashTable *windows_by_xid;
Window output;
CoglOnscreen *onscreen;
CoglFrameClosure *frame_closure;
/* Used for unredirecting fullscreen windows */
guint disable_unredirect_count;
MetaWindow *unredirected_window;
guint disable_unredirect_count;
MetaWindowActor *unredirected_window;
/* Before we create the output window */
XserverRegion pending_input_region;
gint switch_workspace_in_progress;
MetaPluginManager *plugin_mgr;
gboolean frame_has_updated_xsurfaces;
gboolean have_x11_sync_object;
};
/* Wait 2ms after vblank before starting to draw next frame */
#define META_SYNC_DELAY 2
void meta_switch_workspace_completed (MetaCompositor *compositor);
void meta_switch_workspace_completed (MetaScreen *screen);
gboolean meta_begin_modal_for_plugin (MetaCompositor *compositor,
gboolean meta_begin_modal_for_plugin (MetaScreen *screen,
MetaPlugin *plugin,
MetaModalOptions options,
guint32 timestamp);
void meta_end_modal_for_plugin (MetaCompositor *compositor,
void meta_end_modal_for_plugin (MetaScreen *screen,
MetaPlugin *plugin,
guint32 timestamp);
gint64 meta_compositor_monotonic_time_to_server_time (MetaDisplay *display,
gint64 monotonic_time);
void meta_check_end_modal (MetaScreen *screen);
#endif /* META_COMPOSITOR_PRIVATE_H */

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Portions adapted from gnome-shell/src/shell-global.c
*/

View File

@ -14,7 +14,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
/**
@ -26,6 +28,8 @@
#include <config.h>
#include <cogl/cogl-texture-pixmap-x11.h>
#include <clutter/clutter.h>
#include "cogl-utils.h"
@ -33,7 +37,6 @@
#include "mutter-enum-types.h"
#include <meta/errors.h>
#include <meta/meta-background.h>
#include "util-private.h"
#include "meta-background-actor-private.h"
#define FRAGMENT_SHADER_DECLARATIONS \
@ -753,6 +756,88 @@ set_filename (MetaBackground *self,
priv->filename = g_strdup (filename);
}
static Pixmap
get_still_frame_for_monitor (MetaScreen *screen,
int monitor)
{
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdisplay = meta_display_get_xdisplay (display);
Window xroot = meta_screen_get_xroot (screen);
Pixmap pixmap;
GC gc;
XGCValues values;
MetaRectangle geometry;
int depth;
meta_screen_get_monitor_geometry (screen, monitor, &geometry);
depth = DefaultDepth (xdisplay, meta_screen_get_screen_number (screen));
pixmap = XCreatePixmap (xdisplay,
xroot,
geometry.width, geometry.height, depth);
values.function = GXcopy;
values.plane_mask = AllPlanes;
values.fill_style = FillSolid;
values.subwindow_mode = IncludeInferiors;
gc = XCreateGC (xdisplay,
xroot,
GCFunction | GCPlaneMask | GCFillStyle | GCSubwindowMode,
&values);
XCopyArea (xdisplay,
xroot, pixmap, gc,
geometry.x, geometry.y,
geometry.width, geometry.height,
0, 0);
XFreeGC (xdisplay, gc);
return pixmap;
}
/**
* meta_background_load_still_frame:
* @self: the #MetaBackground
*
* Takes a screenshot of the desktop and uses it as the background
* source.
*/
void
meta_background_load_still_frame (MetaBackground *self)
{
MetaBackgroundPrivate *priv = self->priv;
MetaDisplay *display = meta_screen_get_display (priv->screen);
Pixmap still_frame;
CoglTexture *texture;
CoglContext *context = clutter_backend_get_cogl_context (clutter_get_default_backend ());
GError *error = NULL;
ensure_pipeline (self);
unset_texture (self);
set_style (self, G_DESKTOP_BACKGROUND_STYLE_STRETCHED);
still_frame = get_still_frame_for_monitor (priv->screen, priv->monitor);
XSync (meta_display_get_xdisplay (display), False);
meta_error_trap_push (display);
texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (context, still_frame, FALSE, &error));
meta_error_trap_pop (display);
if (error != NULL)
{
g_warning ("Failed to create background texture from pixmap: %s",
error->message);
g_error_free (error);
return;
}
set_texture (self, texture);
}
/**
* meta_background_load_gradient:
* @self: the #MetaBackground

View File

@ -13,7 +13,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Owen Taylor <otaylor@redhat.com>
@ -69,17 +71,11 @@ meta_cullable_cull_out_children (MetaCullable *cullable,
clutter_actor_iter_init (&iter, actor);
while (clutter_actor_iter_prev (&iter, &child))
{
float x, y;
gboolean needs_culling;
int x, y;
if (!META_IS_CULLABLE (child))
if (!CLUTTER_ACTOR_IS_VISIBLE (child))
continue;
needs_culling = (unobscured_region != NULL && clip_region != NULL);
if (needs_culling && !CLUTTER_ACTOR_IS_VISIBLE (child))
needs_culling = FALSE;
/* If an actor has effects applied, then that can change the area
* it paints and the opacity, so we no longer can figure out what
* portion of the actor is obscured and what portion of the screen
@ -96,29 +92,23 @@ meta_cullable_cull_out_children (MetaCullable *cullable,
* as well for the same reason, but omitted for simplicity in the
* hopes that no-one will do that.
*/
if (needs_culling && clutter_actor_has_effects (child))
needs_culling = FALSE;
if (clutter_actor_has_effects (child))
continue;
if (needs_culling && !meta_actor_is_untransformed (child, NULL, NULL))
needs_culling = FALSE;
if (!META_IS_CULLABLE (child))
continue;
if (needs_culling)
{
clutter_actor_get_position (child, &x, &y);
if (!meta_actor_is_untransformed (child, &x, &y))
continue;
/* Temporarily move to the coordinate system of the actor */
cairo_region_translate (unobscured_region, - x, - y);
cairo_region_translate (clip_region, - x, - y);
/* Temporarily move to the coordinate system of the actor */
cairo_region_translate (unobscured_region, - x, - y);
cairo_region_translate (clip_region, - x, - y);
meta_cullable_cull_out (META_CULLABLE (child), unobscured_region, clip_region);
meta_cullable_cull_out (META_CULLABLE (child), unobscured_region, clip_region);
cairo_region_translate (unobscured_region, x, y);
cairo_region_translate (clip_region, x, y);
}
else
{
meta_cullable_cull_out (META_CULLABLE (child), NULL, NULL);
}
cairo_region_translate (unobscured_region, x, y);
cairo_region_translate (clip_region, x, y);
}
}

View File

@ -14,7 +14,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Owen Taylor <otaylor@redhat.com>

View File

@ -16,7 +16,9 @@
* 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/>.
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <meta/meta-plugin.h>

Some files were not shown because too many files have changed in this diff Show More