Compare commits
4 Commits
wip/ui-on-
...
wip/surfac
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a3a2109c0c | ||
|
|
bdbeafc222 | ||
|
|
89ca36818a | ||
|
|
fe1a58b459 |
22
.gitignore
vendored
22
.gitignore
vendored
@@ -75,15 +75,15 @@ src/mutter-enum-types.[ch]
|
|||||||
src/stamp-mutter-enum-types.h
|
src/stamp-mutter-enum-types.h
|
||||||
src/mutter-marshal.[ch]
|
src/mutter-marshal.[ch]
|
||||||
src/stamp-mutter-marshal.h
|
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-idle-monitor.[ch]
|
||||||
src/mutter-plugins.pc
|
src/mutter-plugins.pc
|
||||||
src/gtk-shell-protocol.c
|
src/wayland/gtk-shell-protocol.c
|
||||||
src/gtk-shell-server-protocol.h
|
src/wayland/gtk-shell-server-protocol.h
|
||||||
src/xdg-shell-protocol.c
|
src/wayland/xdg-shell-protocol.c
|
||||||
src/xdg-shell-server-protocol.h
|
src/wayland/xdg-shell-server-protocol.h
|
||||||
src/xserver-protocol.c
|
src/wayland/xserver-protocol.c
|
||||||
src/xserver-server-protocol.h
|
src/wayland/xserver-server-protocol.h
|
||||||
doc/reference/*.args
|
doc/reference/*.args
|
||||||
doc/reference/*.bak
|
doc/reference/*.bak
|
||||||
doc/reference/*.hierarchy
|
doc/reference/*.hierarchy
|
||||||
@@ -101,11 +101,3 @@ doc/reference/meta-undocumented.txt
|
|||||||
doc/reference/meta-unused.txt
|
doc/reference/meta-unused.txt
|
||||||
doc/reference/meta-docs.sgml
|
doc/reference/meta-docs.sgml
|
||||||
doc/reference/meta.types
|
doc/reference/meta.types
|
||||||
gtk-doc.m4
|
|
||||||
intltool.m4
|
|
||||||
libtool.m4
|
|
||||||
ltoptions.m4
|
|
||||||
ltsugar.m4
|
|
||||||
ltversion.m4
|
|
||||||
lt~obsolete.m4
|
|
||||||
.dirstamp
|
|
||||||
|
|||||||
159
COMPLIANCE
Normal file
159
COMPLIANCE
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
Metacity Standards Compliance
|
||||||
|
=============================
|
||||||
|
$Id$
|
||||||
|
|
||||||
|
1) Introduction
|
||||||
|
2) EWMH Compliance
|
||||||
|
a. Root Window Properties
|
||||||
|
b. Root Window Messages
|
||||||
|
c. Application Window Properties
|
||||||
|
d. Window Manager Protocols
|
||||||
|
3) ICCCM Compliance
|
||||||
|
|
||||||
|
1) Introduction
|
||||||
|
---------------
|
||||||
|
|
||||||
|
This document details metacity compliance with the relevent standards.
|
||||||
|
The format of this document is as follows:
|
||||||
|
|
||||||
|
[-/+?] Hint Name/Feature Name (Version number)
|
||||||
|
Errata/Comments
|
||||||
|
|
||||||
|
The first character indicates the level of compliance as follows:
|
||||||
|
- none
|
||||||
|
/ partial
|
||||||
|
+ complete
|
||||||
|
? unknown
|
||||||
|
|
||||||
|
The title indicates a feature or a hint in the specification, and the
|
||||||
|
version number indicates the minimum version of the specification
|
||||||
|
supported by metacity. Later versions may be supported if no
|
||||||
|
incompatible changes have been made in the specification.
|
||||||
|
|
||||||
|
2) EWMH Compliance
|
||||||
|
------------------
|
||||||
|
|
||||||
|
The EWMH, or Extended Window Manager Hints is a freedesktop.org-
|
||||||
|
developed standard to support a number of conventions for
|
||||||
|
communication between the window manager and clients. It builds on
|
||||||
|
and extends the ICCCM (See Section 3). A copy of the current EWMH
|
||||||
|
standard is available at http://freedesktop.org/Standards/wm-spec/
|
||||||
|
|
||||||
|
a. Root Window Properties
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
+ _NET_SUPPORTED (1.3)
|
||||||
|
|
||||||
|
+ _NET_CLIENT_LIST (1.3)
|
||||||
|
|
||||||
|
+ _NET_NUMBER_OF_DESKTOPS (1.3)
|
||||||
|
|
||||||
|
+ _NET_DESKTOP_GEOMETRY (1.3)
|
||||||
|
Metacity does not implement large desktops, so this is kept set to
|
||||||
|
the screen size.
|
||||||
|
|
||||||
|
+ _NET_DESKTOP_VIEWPORT (1.3)
|
||||||
|
Metacity does not implement viewports, so this is a constant (0,0).
|
||||||
|
|
||||||
|
+ _NET_CURRENT_DESKTOP (1.3)
|
||||||
|
|
||||||
|
+ _NET_DESKTOP_NAMES (1.3)
|
||||||
|
|
||||||
|
+ _NET_ACTIVE_WINDOW (1.3)
|
||||||
|
|
||||||
|
+ _NET_WORKAREA (1.3)
|
||||||
|
|
||||||
|
+ _NET_SUPPORTING_WM_CHECK (1.3)
|
||||||
|
|
||||||
|
+ _NET_VIRTUAL_ROOTS (1.3)
|
||||||
|
Metacity does not read or set this property, but it does not use
|
||||||
|
virtual roots to implement virtual desktops, so it complies with the
|
||||||
|
specification.
|
||||||
|
|
||||||
|
+ _NET_DESKTOP_LAYOUT (1.3)
|
||||||
|
|
||||||
|
+ _NET_SHOWING_DESKTOP (1.3)
|
||||||
|
|
||||||
|
b. Root Window Messages
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
+ _NET_CLOSE_WINDOW (1.3)
|
||||||
|
|
||||||
|
- _NET_MOVERESIZE_WINDOW (1.3)
|
||||||
|
Metacity supports this message, but the specification is unclear on
|
||||||
|
the layout of the detail value, and as such it is #if 0'd in the code
|
||||||
|
|
||||||
|
+ _NET_WM_MOVERESIZE (1.3)
|
||||||
|
|
||||||
|
- _NET_RESTACK_WINDOW (1.3)
|
||||||
|
Metacity will raise or lower windows in response to this message,
|
||||||
|
but the sibling restack modes are not supported, and it is currently
|
||||||
|
#if 0'd in the code.
|
||||||
|
|
||||||
|
+ _NET_REQUEST_FRAME_EXTENTS (1.3)
|
||||||
|
|
||||||
|
c. Application Window Properties
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
+ _NET_WM_NAME (1.3)
|
||||||
|
|
||||||
|
+ _NET_WM_VISIBLE_NAME (1.3)
|
||||||
|
Metacity does not set this property, but metacity will never display
|
||||||
|
a name different from _NET_WM_NAME
|
||||||
|
|
||||||
|
+ _NET_WM_ICON_NAME (1.3)
|
||||||
|
|
||||||
|
+ _NET_WM_VISIBLE_ICON_NAME (1.3)
|
||||||
|
Metacity does not set this property, but metacity will never display
|
||||||
|
a name different from _NET_WM_NAME
|
||||||
|
|
||||||
|
+ _NET_WM_DESKTOP (1.3)
|
||||||
|
|
||||||
|
+ _NET_WM_WINDOW_TYPE (1.3)
|
||||||
|
|
||||||
|
/ _NET_WM_STATE (1.3)
|
||||||
|
This property is read and updated according to the specification,
|
||||||
|
but see caveat below.
|
||||||
|
Metacity does not recognize separate vertical and horizontal
|
||||||
|
maximization states. Currently metacity will do a two-dimensional
|
||||||
|
maximization if either property is set.
|
||||||
|
See: http://bugzilla.gnome.org/show_bug.cgi?id=113601
|
||||||
|
Metacity doesn't implement viewports so _NET_WM_STATE_STICKY is
|
||||||
|
unimplemented.
|
||||||
|
|
||||||
|
+ _NET_WM_ALLOWED_ACTIONS (1.3)
|
||||||
|
Metacity keeps this hint up to date. The code is somewhat crufty
|
||||||
|
and should be rewritten, though it is functional.
|
||||||
|
See: http://bugzilla.gnome.org/show_bug.cgi?id=90420
|
||||||
|
|
||||||
|
+ _NET_WM_STRUT (1.3)
|
||||||
|
|
||||||
|
+ _NET_WM_STRUT_PARTIAL (1.3)
|
||||||
|
|
||||||
|
+ _NET_WM_ICON_GEOMETRY (1.3)
|
||||||
|
Metacity uses this property to draw minimize/restore animations
|
||||||
|
|
||||||
|
+ _NET_WM_ICON (1.3)
|
||||||
|
|
||||||
|
+ _NET_WM_PID (1.3)
|
||||||
|
|
||||||
|
+ _NET_WM_HANDLED_ICONS (1.3)
|
||||||
|
Metacity does not read or set this property. However, metacity
|
||||||
|
never manages iconified windows, and so has no need to do so.
|
||||||
|
|
||||||
|
+ _NET_WM_USER_TIME (1.3)
|
||||||
|
Metacity uses this property to prevent applications from stealing
|
||||||
|
focus if supported by the toolkit.
|
||||||
|
|
||||||
|
+ _NET_FRAME_EXTENTS (1.3)
|
||||||
|
If set in response to a _NET_REQUEST_FRAME_EXTENTS message received
|
||||||
|
prior to the window being mapped, this may be an estimate. This is,
|
||||||
|
however, expressly allowed by the specification.
|
||||||
|
|
||||||
|
d. Window Manager Protocols
|
||||||
|
---------------------------
|
||||||
|
+ _NET_WM_PING (1.3)
|
||||||
|
|
||||||
|
3) ICCCM Compliance
|
||||||
|
-------------------
|
||||||
|
TODO
|
||||||
298
HACKING
Normal file
298
HACKING
Normal file
@@ -0,0 +1,298 @@
|
|||||||
|
Intro...
|
||||||
|
|
||||||
|
Window managers have a few ways in which they are significantly different
|
||||||
|
from other applications. This file, combined with the code overview in
|
||||||
|
doc/code-overview.txt, should hopefully provide a series of relatively
|
||||||
|
quick pointers (hopefully only a few minutes each) to some of the places
|
||||||
|
one can look to orient themselves and get started. Some of this will be
|
||||||
|
general to window managers on X, much will be specific to Metacity, and
|
||||||
|
there's probably some information that's common to programs in general but
|
||||||
|
is nonetheless useful.
|
||||||
|
|
||||||
|
Overview
|
||||||
|
Administrative issues
|
||||||
|
Minimal Building/Testing Environment
|
||||||
|
Relevant standards and X properties
|
||||||
|
Debugging and testing
|
||||||
|
Debugging logs
|
||||||
|
Adding information to the log
|
||||||
|
Valgrind
|
||||||
|
Testing Utilities
|
||||||
|
Technical gotchas to keep in mind
|
||||||
|
Other important reading
|
||||||
|
Extra reading
|
||||||
|
Ideas for tasks to work on
|
||||||
|
|
||||||
|
|
||||||
|
Administrative issues
|
||||||
|
Don't commit substantive code in here without asking hp@redhat.com.
|
||||||
|
Adding translations, no-brainer typo fixes, etc. is fine.
|
||||||
|
|
||||||
|
The code could use cleanup in a lot of places, feel free to do so.
|
||||||
|
|
||||||
|
See http://developer.gnome.org/dotplan/for_maintainers.html for
|
||||||
|
information on how to make a release. The only difference from those
|
||||||
|
instructions is that the minor version number of a Metacity release
|
||||||
|
should always be a number from the Fibonacci sequence.
|
||||||
|
|
||||||
|
Minimal Building/Testing Environment
|
||||||
|
You do not need to _install_ a development version of Metacity to
|
||||||
|
build, run and test it; you can run it from some temporary
|
||||||
|
directory. Also, you do not need to build all of Gnome in order to
|
||||||
|
build a development version of Metacity -- odds are, you may be able
|
||||||
|
to build metacity from CVS without building any other modules.
|
||||||
|
|
||||||
|
As long as you have gtk+ >= 3.0 and GIO >= 2.25.10 with your distro
|
||||||
|
(gtk+ >= 2.6 if you manually revert the change from bug 348633), you
|
||||||
|
should be able to install your distro's development packages
|
||||||
|
(e.g. gtk2-devel, glib-devel, startup-notification-devel on
|
||||||
|
Fedora; also, remember to install the gnome-common package which is
|
||||||
|
needed for building cvs versions of Gnome modules like Metacity) as
|
||||||
|
well as the standard development tools (gcc, autoconf, automake,
|
||||||
|
pkg-config, intltool, and libtool) and be ready to build and test
|
||||||
|
Metacity. Steps to do so:
|
||||||
|
|
||||||
|
$ svn checkout http://svn.gnome.org/svn/metacity/trunk metacity
|
||||||
|
$ cd metacity
|
||||||
|
$ ./autogen.sh --prefix /usr
|
||||||
|
$ make
|
||||||
|
$ ./src/metacity --replace
|
||||||
|
|
||||||
|
Again, note that you do not need to run 'make install'.
|
||||||
|
|
||||||
|
Relevant standards and X properties
|
||||||
|
There are two documents that describe some basics about how window
|
||||||
|
managers should behave: the ICCCM (Inter-Client Communication Conventions
|
||||||
|
Manual) and EWMH (Extended Window Manager Hints). You can find these at
|
||||||
|
the following locations:
|
||||||
|
ICCCM - http://tronche.com/gui/x/icccm/
|
||||||
|
EWMH - :pserver:anoncvs@pdx.freedesktop.org:/cvs
|
||||||
|
The ICCCM is usually available in RPM or DEB format as well. There is
|
||||||
|
actually an online version of the EWMH, but it is almost always woefully
|
||||||
|
out of date. Just get it from cvs with these commands (the backslash
|
||||||
|
means include the stuff from the next line):
|
||||||
|
cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/icccm-extensions login
|
||||||
|
cvs -d :pserver:anoncvs@cvs.freedesktop.org:/cvs/icccm-extensions \
|
||||||
|
checkout wm-spec
|
||||||
|
|
||||||
|
DO NOT GO AND READ THOSE THINGS. THEY ARE REALLY, REALLY BORING.
|
||||||
|
|
||||||
|
If you do, you'll probably end up catching up on your sleep instead of
|
||||||
|
hacking on Metacity. ;-) Instead, just look at the table of contents and
|
||||||
|
glance at a page or two to get an idea of what's in there. Then only
|
||||||
|
refer to it if you see something weird in the code and you don't know
|
||||||
|
what it is but has some funny looking name like you see in one of those
|
||||||
|
two documents.
|
||||||
|
|
||||||
|
You can refer to the COMPLIANCE file for additional information on these
|
||||||
|
specifications and Metacity's compliance therewith.
|
||||||
|
|
||||||
|
One of the major things those documents cover that are useful to learn
|
||||||
|
about immediately are X properties. The right way to learn about those,
|
||||||
|
though, is through hand on experimentation with the xprop command (and
|
||||||
|
then look up things you find from xprop in those two manuals if you're
|
||||||
|
curious enough). First, try running
|
||||||
|
xprop
|
||||||
|
in a terminal and click on one of the windows on your screen. That gives
|
||||||
|
you the x properties for that window. Look through them and get a basic
|
||||||
|
idea of what's there for kicks. Note that you can get rid of some of the
|
||||||
|
verboseness by grepping out the _NET_WM_ICON stuff, i.e.
|
||||||
|
xprop | grep -v _NET_WM_ICON
|
||||||
|
Next, try running
|
||||||
|
xprop -root
|
||||||
|
in a terminal. There's all the properties of the root window (which you
|
||||||
|
can think of as the "main" Xserver window). You can also manually
|
||||||
|
specify individual windows that you want the properties of with
|
||||||
|
xprop -id <id>
|
||||||
|
if you know the id of the window in question. You can get the id of a
|
||||||
|
given window by either running xwininfo, e.g.
|
||||||
|
xwininfo | grep "Window id" | cut -f 4 -d ' '
|
||||||
|
or by looking at the _NET_CLIENT_STACKING property of the root
|
||||||
|
window. Finally, it can also be useful to add "-spy" (without the
|
||||||
|
quotes) to the xprop command to get it to continually monitor that
|
||||||
|
window and report any changes to you.
|
||||||
|
|
||||||
|
Debugging information
|
||||||
|
Trying to run a window manager under a typical debugger, such as gdb,
|
||||||
|
unfortunately just doesn't work very well. So, we have to resort to
|
||||||
|
other methods.
|
||||||
|
|
||||||
|
Debugging logs
|
||||||
|
|
||||||
|
First, note that you can start a new version of metacity to replace the
|
||||||
|
existing one by running
|
||||||
|
metacity --replace
|
||||||
|
(which also comes in handy in the form "./src/metacity --replace" when
|
||||||
|
trying to quickly test a small change while hacking on metacity without
|
||||||
|
doing a full "make install", though I'm going off topic...) This will
|
||||||
|
allow you to see any warnings printed at the terminal. Sometimes it's
|
||||||
|
useful to have these directed to a logfile instead, which you can do by
|
||||||
|
running
|
||||||
|
METACITY_USE_LOGFILE=1 metacity --replace
|
||||||
|
The logfile it uses will be printed in the terminal. Sometimes, it's
|
||||||
|
useful to get more information than just warnings. You can set
|
||||||
|
METACITY_VERBOSE to do that, like so:
|
||||||
|
METACITY_VERBOSE=1 METACITY_USE_LOGFILE=1 metacity --replace
|
||||||
|
(note that METACITY_VERBOSE=1 can be problematic without
|
||||||
|
METACITY_USE_LOGFILE=1; avoid it unless running in from something that
|
||||||
|
won't be managed by the new Metacity--see bug 305091 for more details).
|
||||||
|
There are also other flags, such as METACITY_DEBUG, most of which I
|
||||||
|
haven't tried and don't know what they do. Go to the source code
|
||||||
|
directory and run
|
||||||
|
grep "METACITY_" * | grep getenv
|
||||||
|
to find out what the other ones are.
|
||||||
|
|
||||||
|
Adding information to the log
|
||||||
|
|
||||||
|
Since we can't single step with a debugger, we often have to fall back to
|
||||||
|
the primitive method of getting information we want to know: adding
|
||||||
|
"print" statements. Metacity has a fairly structured way to do this,
|
||||||
|
using the functions meta_warning, meta_topic, and meta_verbose. All
|
||||||
|
three have the same basic format as printf, except that meta_topic also
|
||||||
|
takes a leading enumeration parameter to specify the type of message
|
||||||
|
being shown (makes it easier for grepping in a verbose log). You'll find
|
||||||
|
tons of examples in the source code if you need them; just do a quick
|
||||||
|
grep or look in most any file. Note that meta_topic and meta_verbose
|
||||||
|
messages only appear if verbosity is turned on. I tend to frequently add
|
||||||
|
temporary meta_warning statements (or switch meta_topic or meta_verbose
|
||||||
|
ones to meta_warning ones) and then undo the changes once I've learned
|
||||||
|
the info that I needed.
|
||||||
|
|
||||||
|
There is also a meta_print_backtrace (which again is only active if
|
||||||
|
verbosity is turned on) that can also be useful if you want to learn how
|
||||||
|
a particular line of code gets called. And, of course, there's always
|
||||||
|
g_assert if you want to make sure some section isn't executed (or isn't
|
||||||
|
executed under certain conditions).
|
||||||
|
|
||||||
|
Valgrind
|
||||||
|
|
||||||
|
Valgrind is awesome for finding memory leaks or corruption and
|
||||||
|
uninitialized variables. But I also tend to use it in a non-traditional
|
||||||
|
way as a partial substitute for a normal debugger: it can provide me with
|
||||||
|
a stack trace of where metacity is crashing if I made a change that
|
||||||
|
caused it to do so, which is one of the major uses of debuggers. (And,
|
||||||
|
what makes it cooler than a debugger is that there will also often be
|
||||||
|
warnings pinpointing the cause of the crash from either some kind of
|
||||||
|
simple memory corruption or an uninitialized variable). Sometimes, when
|
||||||
|
I merely want to know what is calling a particular function I'll just
|
||||||
|
throw in an "int i; printf("%d\n", i);" just because valgrind will give
|
||||||
|
me a full stacktrace whenever it sees that uninitialized variable being
|
||||||
|
used (yes, I could use meta_print_backtrace, but that means I have to
|
||||||
|
turn verbosity on).
|
||||||
|
|
||||||
|
To run metacity under valgrind, use options typical for any Gnome
|
||||||
|
program, such as
|
||||||
|
valgrind --log-file=metacity.log --tool=memcheck --num-callers=48 \
|
||||||
|
--leak-check=yes --leak-resolution=high --show-reachable=yes \
|
||||||
|
./src/metacity --replace
|
||||||
|
where, again, the backslashes mean to join all the stuff on the following
|
||||||
|
line with the previous one.
|
||||||
|
|
||||||
|
However, there is a downside. Things run a little bit slowly, and it
|
||||||
|
appears that you'll need about 1.5GB of ram, which unfortunately prevents
|
||||||
|
most people from trying this.
|
||||||
|
|
||||||
|
Testing Utilities
|
||||||
|
|
||||||
|
src/run-metacity.sh
|
||||||
|
The script src/run-metacity.sh is useful to hack on the window manager.
|
||||||
|
It runs metacity in an Xnest. e.g.:
|
||||||
|
CLIENTS=3 ./run-metacity.sh
|
||||||
|
or
|
||||||
|
DEBUG=memprof ./run-metacity.sh
|
||||||
|
or
|
||||||
|
DEBUG_TEST=1 ./run-metacity-sh
|
||||||
|
or whatever.
|
||||||
|
|
||||||
|
metacity-message
|
||||||
|
The tool metacity-message can be used as follows:
|
||||||
|
metacity-message reload-theme
|
||||||
|
metacity-message restart
|
||||||
|
metacity-message enable-keybindings
|
||||||
|
metacity-message disable-keybindings
|
||||||
|
The first of these is useful for testing themes, the second is just
|
||||||
|
another way (besides the --restart flag to metacity itself) of
|
||||||
|
restarting metacity, and the third is useful for testing Metacity when
|
||||||
|
running it under an Xnest (typically, the Metacity under the Xnest
|
||||||
|
wouldn't get keybinding notifications--making keyboard navigation not
|
||||||
|
work--but if you disable the keybindings for the global Metacity then
|
||||||
|
the Metacity under the Xnest can then get those keybinding notifications).
|
||||||
|
|
||||||
|
metacity-window-demo
|
||||||
|
metacity-window-demo is good for trying behavior of various kinds
|
||||||
|
of window without launching a full desktop.
|
||||||
|
|
||||||
|
Technical gotchas to keep in mind
|
||||||
|
Files that include gdk.h or gtk.h are not supposed to include
|
||||||
|
display.h or window.h or other core files. Files in the core
|
||||||
|
(display.[hc], window.[hc]) are not supposed to include gdk.h or
|
||||||
|
gtk.h. Reasons:
|
||||||
|
|
||||||
|
"Basically you don't want GDK most of the time. It adds
|
||||||
|
abstractions that cause problems, because they aren't designed to
|
||||||
|
be used in a WM where we do weird stuff (display grabs, and just
|
||||||
|
being the WM). At best GDK adds inefficiency, at worst it breaks
|
||||||
|
things in weird ways where you have to be a GDK guru to figure
|
||||||
|
them out. Owen also told me that they didn't want to start adding
|
||||||
|
a lot of hacks to GDK to let a WM use it; we both agreed back in
|
||||||
|
the mists of time that metacity would only use it for the "UI"
|
||||||
|
bits as it does.
|
||||||
|
|
||||||
|
Having the split in the source code contains and makes very clear
|
||||||
|
the interface between the WM and GDK/GTK. This keeps people from
|
||||||
|
introducing extra GDK/GTK usage when it isn't needed or
|
||||||
|
appropriate. Also, it speeds up the compilation a bit, though this
|
||||||
|
was perhaps more relevant 5 years ago than it is now.
|
||||||
|
|
||||||
|
There was also a very old worry that the GDK stuff might have to
|
||||||
|
be in a separate process to work right; that turned out to be
|
||||||
|
untrue. Though who knows what issues the CM will introduce."
|
||||||
|
|
||||||
|
Remember that strings stored in X properties are not in UTF-8, and they
|
||||||
|
have to end up in UTF-8 before we try putting them through Pango.
|
||||||
|
|
||||||
|
If you make any X request involving a client window, you have to
|
||||||
|
meta_error_trap_push() around the call; this is not necessary for X
|
||||||
|
requests on the frame windows.
|
||||||
|
|
||||||
|
Remember that not all windows have frames, and window->frame can be NULL.
|
||||||
|
|
||||||
|
Other important reading & where to get started
|
||||||
|
Extra reading
|
||||||
|
|
||||||
|
There are some other important things to read to get oriented as well.
|
||||||
|
These are:
|
||||||
|
http://pobox.com/~hp/features.html
|
||||||
|
rationales.txt
|
||||||
|
doc/code-overview.txt
|
||||||
|
|
||||||
|
It pays to read http://pobox.com/~hp/features.html in order
|
||||||
|
to understand the philosophy of Metacity.
|
||||||
|
|
||||||
|
The rationales.txt file has two things: (1) a list of design choices with
|
||||||
|
links in the form of bugzilla bugs that discuss the issue, and (2) a list
|
||||||
|
outstanding bug categories, each of which is tracked by a particular
|
||||||
|
tracker bug in bugzilla from which you can find several closely related
|
||||||
|
bug reports.
|
||||||
|
|
||||||
|
doc/code-overview.txt provides a fairly good overview of the code,
|
||||||
|
including coverage of the function of the various files, the main
|
||||||
|
structures and their relationships, and places to start looking in the
|
||||||
|
code tailored to general categories of tasks.
|
||||||
|
|
||||||
|
Ideas for tasks to work on
|
||||||
|
|
||||||
|
There are a variety of things you could work on in the code. You may
|
||||||
|
have ideas of your own, but in case you don't, let me provide a list of
|
||||||
|
ideas you could choose from:
|
||||||
|
|
||||||
|
If you're ambitious, there's a list of things Havoc made that he'd really
|
||||||
|
like to see tackled, which you can find at
|
||||||
|
http://log.ometer.com/2004-05.html. Be sure to double check with someone
|
||||||
|
to make sure the item is still relevant if you're interested in one of
|
||||||
|
these. Another place to look for ideas, of course, is bugzilla. One can
|
||||||
|
just do queries and look for things that look fixable.
|
||||||
|
|
||||||
|
However, perhaps the best way of getting ideas of related tasks to work
|
||||||
|
on, is to look at the second half of the rationales.txt file, which tries
|
||||||
|
to group bugs by type.
|
||||||
8
MAINTAINERS
Normal file
8
MAINTAINERS
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
Tomas Frydrych
|
||||||
|
Email: tf linux intel com
|
||||||
|
Userid: tomasf
|
||||||
|
|
||||||
|
Owen Taylor
|
||||||
|
Email: otaylor redhat com
|
||||||
|
Userid: otaylor
|
||||||
|
|
||||||
43
METACITY_MAINTAINERS
Normal file
43
METACITY_MAINTAINERS
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
Currently active maintainers
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
Elijah Newren
|
||||||
|
Email: newren gmail com
|
||||||
|
Userid: newren
|
||||||
|
|
||||||
|
- Usually won't touch the theme bugs (isn't interested) or the
|
||||||
|
compositor (until open source nvidia drivers are up to snuff).
|
||||||
|
Tends to be most interested in libwnck/gtk interactions, focus
|
||||||
|
issues, constraints problems, and raising/stacking, but works on
|
||||||
|
just about anything other than themes and the compositor.
|
||||||
|
|
||||||
|
Thomas Thurman
|
||||||
|
Email: thomas thurman org uk
|
||||||
|
Userid: tthurman
|
||||||
|
|
||||||
|
- Responsible for all theme bugs and the compositor (thank goodness
|
||||||
|
Thomas got involved, eh?). I'm sure he'll replace this sentence
|
||||||
|
with his interests when he reads it. ;-)
|
||||||
|
|
||||||
|
|
||||||
|
Semi-active maintainers
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
Havoc Pennington
|
||||||
|
Email: hp redhat com
|
||||||
|
Userid: hp
|
||||||
|
- Original author. Doesn't patch metacity anymore, but is active in
|
||||||
|
answering questions, responding to bugs, providing very helpful
|
||||||
|
suggestions and insight, and even assisting with debugging.
|
||||||
|
|
||||||
|
|
||||||
|
Important historical figureheads
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
Rob Adams (readams readams net)
|
||||||
|
- Was the main maintainer of metacity for a while; particular areas
|
||||||
|
of focus included xinerama, placement, and an older version of the
|
||||||
|
constraints code. Still responds to bugs every once in a while.
|
||||||
|
|
||||||
|
Søren Sandmann (sandmann redhat com)
|
||||||
|
- Wrote most of the current compositing manager code + libcm
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
|
|
||||||
SUBDIRS=src po doc
|
SUBDIRS=src protocol po doc
|
||||||
|
|
||||||
|
EXTRA_DIST = HACKING MAINTAINERS rationales.txt
|
||||||
|
|
||||||
DISTCLEANFILES = intltool-extract intltool-merge intltool-update po/stamp-it po/.intltool-merge-cache
|
DISTCLEANFILES = intltool-extract intltool-merge intltool-update po/stamp-it po/.intltool-merge-cache
|
||||||
|
|
||||||
|
|||||||
33
NEWS
33
NEWS
@@ -1,36 +1,3 @@
|
|||||||
3.12.0
|
|
||||||
======
|
|
||||||
* Fix grab issue with SSD xwayland windows [Rui; #726123]
|
|
||||||
* Misc. bug fixes [Jasper, Ray, Rui, Florian; #727011]
|
|
||||||
|
|
||||||
Contributors:
|
|
||||||
Rui Matos, Florian Müllner, Jasper St. Pierre, Ray Strode
|
|
||||||
|
|
||||||
3.11.92
|
|
||||||
=======
|
|
||||||
* Fix identification of CSD windows [Owen; #723029]
|
|
||||||
* Update keyboard state unconditionally [Rui; #722847]
|
|
||||||
* Misc bug fixes and cleanups [Owen, Rui, Giovanni, Matthias, Adel, Ryan,
|
|
||||||
Jasper, Marek, Florian; #723580, #726123, #726683]
|
|
||||||
|
|
||||||
Contributors:
|
|
||||||
Giovanni Campagna, Marek Chalupa, Matthias Clasen, Adel Gadllah, Ryan Lortie,
|
|
||||||
Rui Matos, Florian Müllner, Jasper St. Pierre, Owen W. Taylor
|
|
||||||
|
|
||||||
3.11.91
|
|
||||||
=======
|
|
||||||
* Don't use keysym to match keybindings [Rui; #678001]
|
|
||||||
* Fix message tray icons showing up blank (again) [Adel; #725180]
|
|
||||||
* Improve keybinding lookups [Rui; #725588]
|
|
||||||
* Fix dynamic updates of titlebar style properties [Owen; #725751]
|
|
||||||
* Fix positioning of manually positioned windows [Owen; #724049]
|
|
||||||
* Misc bug fixes and cleanups [Jasper, Carlos, Adel, Giovanni, Florian; #720631,
|
|
||||||
#724969, #725216, #724402, #722266, #725338, #725525]
|
|
||||||
|
|
||||||
Contributors:
|
|
||||||
Giovanni Campagna, Adel Gadllah, Carlos Garnacho, Rui Matos, Florian Müllner,
|
|
||||||
Jasper St. Pierre, Owen W. Taylor
|
|
||||||
|
|
||||||
3.11.90
|
3.11.90
|
||||||
=======
|
=======
|
||||||
* Fix double-scaling on high DPI resolutions [Adel; #723931]
|
* Fix double-scaling on high DPI resolutions [Adel; #723931]
|
||||||
|
|||||||
416
README
Normal file
416
README
Normal file
@@ -0,0 +1,416 @@
|
|||||||
|
The original codebase named "Metacity" is not a meta-City as in an
|
||||||
|
urban center, but rather Meta-ness as in the state of being
|
||||||
|
meta. i.e. metacity : meta as opacity : opaque. Also it may have
|
||||||
|
something to do with the Meta key on UNIX keyboards.
|
||||||
|
|
||||||
|
Since then, it has been renamed mutter after a rebase on top of
|
||||||
|
clutter as a compositing manager.
|
||||||
|
|
||||||
|
COMPILING MUTTER
|
||||||
|
===
|
||||||
|
|
||||||
|
You need GTK+ 2.2. For startup notification to work you need
|
||||||
|
libstartup-notification at
|
||||||
|
http://www.freedesktop.org/software/startup-notification/ or on the
|
||||||
|
GNOME ftp site.
|
||||||
|
You need Clutter 1.0. You need gobject-introspection 0.6.3.
|
||||||
|
|
||||||
|
REPORTING BUGS AND SUBMITTING PATCHES
|
||||||
|
===
|
||||||
|
|
||||||
|
Report new bugs on http://bugzilla.gnome.org. Please check for
|
||||||
|
duplicates, *especially* if you are reporting a feature request.
|
||||||
|
|
||||||
|
Please do *not* add "me too!" or "yes I really want this!" comments to
|
||||||
|
feature requests in bugzilla. Please read
|
||||||
|
http://pobox.com/~hp/features.html prior to adding any kind of flame
|
||||||
|
about missing features or misfeatures.
|
||||||
|
|
||||||
|
Feel free to send patches too; Metacity is relatively small and
|
||||||
|
simple, so if you find a bug or want to add a feature it should be
|
||||||
|
pretty easy. Send me mail, or put the patch in bugzilla.
|
||||||
|
|
||||||
|
See the HACKING file for some notes on hacking Mutter.
|
||||||
|
|
||||||
|
MUTTER FEATURES
|
||||||
|
===
|
||||||
|
|
||||||
|
- Uses GTK+ 2.0 for drawing window frames. This means colors, fonts,
|
||||||
|
etc. come from GTK+ theme.
|
||||||
|
|
||||||
|
- Does not expose the concept of "window manager" to the user. Some
|
||||||
|
of the features in the GNOME control panel and other parts of the
|
||||||
|
desktop happen to be implemented in metacity, such as changing your
|
||||||
|
window border theme, or changing your window navigation shortcuts,
|
||||||
|
but the user doesn't need to know this.
|
||||||
|
|
||||||
|
- Includes only the window manager; does not try to be a desktop
|
||||||
|
environment. The pager, configuration, etc. are all separate and
|
||||||
|
modular. The "libwnck" library (which I also wrote) is available
|
||||||
|
for writing metacity extensions, pagers, and so on. (But libwnck
|
||||||
|
isn't metacity specific, or GNOME-dependent; it requires only GTK,
|
||||||
|
and should work with KWin, fvwm2, and other EWMH-compliant WMs.)
|
||||||
|
|
||||||
|
- Has a simple theme system and a couple of extra themes come with it.
|
||||||
|
Change themes via gsettings:
|
||||||
|
gsettings set org.gnome.desktop.wm.preferences theme Crux
|
||||||
|
gsettings set org.gnome.desktop.wm.preferences theme Gorilla
|
||||||
|
gsettings set org.gnome.desktop.wm.preferences theme Atlanta
|
||||||
|
gsettings set org.gnome.desktop.wm.preferences theme Bright
|
||||||
|
|
||||||
|
See theme-format.txt for docs on the theme format. Use
|
||||||
|
metacity-theme-viewer to preview themes.
|
||||||
|
|
||||||
|
- Change number of workspaces via gsettings:
|
||||||
|
gsettings set org.gnome.desktop.wm.preferences num-workspaces 5
|
||||||
|
|
||||||
|
Can also change workspaces from GNOME 2 pager.
|
||||||
|
|
||||||
|
- Change focus mode:
|
||||||
|
gsettings set org.gnome.desktop.wm.preferences focus-mode mouse
|
||||||
|
gsettings set org.gnome.desktop.wm.preferences focus-mode sloppy
|
||||||
|
gsettings set org.gnome.desktop.wm.preferences focus-mode click
|
||||||
|
|
||||||
|
- Global keybinding defaults include:
|
||||||
|
|
||||||
|
Alt-Tab forward cycle window focus
|
||||||
|
Alt-Shift-Tab backward cycle focus
|
||||||
|
Alt-Ctrl-Tab forward cycle focus among panels
|
||||||
|
Alt-Ctrl-Shift-Tab backward cycle focus among panels
|
||||||
|
Alt-Escape cycle window focus without a popup thingy
|
||||||
|
Ctrl-Alt-Left Arrow previous workspace
|
||||||
|
Ctrl-Alt-Right Arrow next workspace
|
||||||
|
Ctrl-Alt-D minimize/unminimize all, to show desktop
|
||||||
|
|
||||||
|
Change keybindings for example:
|
||||||
|
|
||||||
|
gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-1 '[<Alt>F1]'
|
||||||
|
|
||||||
|
Also try the GNOME keyboard shortcuts control panel.
|
||||||
|
|
||||||
|
- Window keybindings:
|
||||||
|
|
||||||
|
Alt-space window menu
|
||||||
|
|
||||||
|
Mnemonics work in the menu. That is, Alt-space then underlined
|
||||||
|
letter in the menu item works.
|
||||||
|
|
||||||
|
Choose Move from menu, and arrow keys to move the window.
|
||||||
|
|
||||||
|
While moving, hold down Control to move slower, and
|
||||||
|
Shift to snap to edges.
|
||||||
|
|
||||||
|
Choose Resize from menu, and nothing happens yet, but
|
||||||
|
eventually I might implement something.
|
||||||
|
|
||||||
|
Keybindings for things like maximize window, vertical maximize,
|
||||||
|
etc. can be bound, but may not all exist by default. See
|
||||||
|
metacity.schemas.
|
||||||
|
|
||||||
|
- Window mouse bindings:
|
||||||
|
|
||||||
|
Clicking anywhere on frame with button 1 will raise/focus window
|
||||||
|
|
||||||
|
If you click a window control, such as the close button, then the
|
||||||
|
control will activate on button release if you are still over it
|
||||||
|
on release (as with most GUI toolkits)
|
||||||
|
|
||||||
|
If you click and drag borders with button 1 it resizes the window
|
||||||
|
|
||||||
|
If you click and drag the titlebar with button 1 it moves the
|
||||||
|
window.
|
||||||
|
|
||||||
|
If you click anywhere on the frame with button 2 it lowers the
|
||||||
|
window.
|
||||||
|
|
||||||
|
If you click anywhere on the frame with button 3 it shows the
|
||||||
|
window menu.
|
||||||
|
|
||||||
|
If you hold down Super (windows key) and click inside a window, it
|
||||||
|
will move the window (buttons 1 and 2) or show menu (button 3).
|
||||||
|
Or you can configure a different modifier for this.
|
||||||
|
|
||||||
|
If you pick up a window with button 1 and then switch workspaces
|
||||||
|
the window will come with you to the new workspace, this is
|
||||||
|
a feature copied from Enlightenment.
|
||||||
|
|
||||||
|
If you hold down Shift while moving a window, the window snaps
|
||||||
|
to edges of other windows and the screen.
|
||||||
|
|
||||||
|
- Session management:
|
||||||
|
|
||||||
|
Mutter connects to the session manager and will set itself up to
|
||||||
|
be respawned. It theoretically restores sizes/positions/workspace
|
||||||
|
for session-aware applications.
|
||||||
|
|
||||||
|
- Mutter implements much of the EWMH window manager specification
|
||||||
|
from freedesktop.org, as well as the older ICCCM. Please refer to
|
||||||
|
the COMPLIANCE file for information on mutter compliance with
|
||||||
|
these standards.
|
||||||
|
|
||||||
|
- Uses Pango to render text, so has cool i18n capabilities.
|
||||||
|
Supports UTF-8 window titles and such.
|
||||||
|
|
||||||
|
- There are simple animations for actions such as minimization,
|
||||||
|
to help users see what is happening. Should probably
|
||||||
|
have a few more of these and make them nicer.
|
||||||
|
|
||||||
|
- if you have the proper X setup, set the GDK_USE_XFT=1
|
||||||
|
environment variable to get antialiased window titles.
|
||||||
|
|
||||||
|
- considers the panel when placing windows and maximizing
|
||||||
|
them.
|
||||||
|
|
||||||
|
- handles the window manager selection from the ICCCM. Will exit if
|
||||||
|
another WM claims it, and can claim it from another WM if you pass
|
||||||
|
the --replace argument. So if you're running another
|
||||||
|
ICCCM-compliant WM, you can run "mutter --replace" to replace it
|
||||||
|
with Metacity.
|
||||||
|
|
||||||
|
- does basic colormap handling
|
||||||
|
|
||||||
|
- and much more! well, maybe not a lot more.
|
||||||
|
|
||||||
|
HOW TO ADD EXTERNAL FEATURES
|
||||||
|
===
|
||||||
|
|
||||||
|
You can write a mutter "plugin" such as a pager, window list, icon
|
||||||
|
box, task menu, or even things like "window matching" using the
|
||||||
|
Extended Window Manager Hints. See http://www.freedesktop.org for the
|
||||||
|
EWMH specification. An easy-to-use library called "libwnck" is
|
||||||
|
available that uses the EWMH and is specifically designed for writing
|
||||||
|
WM accessories.
|
||||||
|
|
||||||
|
You might be interested in existing accessories such as "Devil's Pie"
|
||||||
|
by Ross Burton, which add features to Mutter (or other
|
||||||
|
EWMH-compliant WMs).
|
||||||
|
|
||||||
|
MUTTER BUGS, NON-FEATURES, AND CAVEATS
|
||||||
|
===
|
||||||
|
|
||||||
|
See bugzilla: http://bugzilla.gnome.org/query.cgi
|
||||||
|
|
||||||
|
FAQ
|
||||||
|
===
|
||||||
|
|
||||||
|
Q: Will you add my feature?
|
||||||
|
|
||||||
|
A: If it makes sense to turn on unconditionally, or is genuinely a
|
||||||
|
harmless preference that I would not be embarrassed to put in a
|
||||||
|
simple, uncluttered, user-friendly configuration dialog.
|
||||||
|
|
||||||
|
If the only rationale for your feature is that other window
|
||||||
|
managers have it, or that you are personally used to it, or
|
||||||
|
something like that, then I will not be impressed. Metacity is
|
||||||
|
firmly in the "choose good defaults" camp rather than the "offer 6
|
||||||
|
equally broken ways to do it, and let the user pick one" camp.
|
||||||
|
|
||||||
|
This is part of a "no crackrock" policy, despite some exceptions
|
||||||
|
I'm mildly embarrassed about. For example, multiple workspaces
|
||||||
|
probably constitute crackrock, they confuse most users and really
|
||||||
|
are not that useful if you have a decent tasklist and so on. But I
|
||||||
|
am too used to them to turn them off. Or alternatively
|
||||||
|
iconification/tasklist is crack, and workspaces/pager are good. But
|
||||||
|
having both is certainly a bit wrong. Sloppy focus is probably
|
||||||
|
crackrock too.
|
||||||
|
|
||||||
|
But don't think unlimited crack is OK just because I slipped up a
|
||||||
|
little. No slippery slope here.
|
||||||
|
|
||||||
|
Don't let this discourage patches and fixes - I love those. ;-)
|
||||||
|
Just be prepared to hear the above objections if your patch adds
|
||||||
|
some crack-ridden configuration option.
|
||||||
|
|
||||||
|
http://pobox.com/~hp/free-software-ui.html
|
||||||
|
http://pobox.com/~hp/features.html
|
||||||
|
|
||||||
|
Q: Will Mutter be part of GNOME?
|
||||||
|
|
||||||
|
A: It is not officially part of GNOME as of GNOME 2.27. We are
|
||||||
|
hoping to have mutter officially included as of GNOME 2.28.
|
||||||
|
|
||||||
|
Q: Why does Mutter remember the workspace/position of some apps
|
||||||
|
but not others across logout/login?
|
||||||
|
|
||||||
|
A: Mutter only stores sizes/positions for apps that are session
|
||||||
|
managed. As far as I can determine, there is no way to attempt to
|
||||||
|
remember workspace/position for non-session-aware apps without
|
||||||
|
causing a lot of weird effects.
|
||||||
|
|
||||||
|
The reason is that you don't know which non-SM-aware apps were
|
||||||
|
launched by the session. When you initially log in, Metacity sees a
|
||||||
|
bunch of new windows appear. But it can't distinguish between
|
||||||
|
windows that were stored in your session, or windows you just
|
||||||
|
launched after logging in. If Metacity tried to guess that a window
|
||||||
|
was from the session, it could e.g. end up maximizing a dialog, or
|
||||||
|
put a window you just launched on another desktop or in a weird
|
||||||
|
place. And in fact I see a lot of bugs like this in window managers
|
||||||
|
that try to handle non-session-aware apps.
|
||||||
|
|
||||||
|
However, for session-aware apps, Mutter can tell that the
|
||||||
|
application instance is from the session and thus restore it
|
||||||
|
reliably, assuming the app properly restores the windows it had
|
||||||
|
open on session save.
|
||||||
|
|
||||||
|
So the correct way to fix the situation is to make apps
|
||||||
|
session-aware. libSM has come with X for years, it's very
|
||||||
|
standardized, it's shared by GNOME and KDE - even twm is
|
||||||
|
session-aware. So anyone who won't take a patch to add SM is more
|
||||||
|
archaic than twm - and you should flame them. ;-)
|
||||||
|
|
||||||
|
Docs on session management:
|
||||||
|
http://www.fifi.org/doc/xspecs/xsmp.txt.gz
|
||||||
|
http://www.fifi.org/doc/xspecs/SMlib.txt.gz
|
||||||
|
|
||||||
|
See also the ICCCM section on SM. For GNOME apps, use the
|
||||||
|
GnomeClient object. For a simple example of using libSM directly,
|
||||||
|
twm/session.c in the twm source code is pretty easy to understand.
|
||||||
|
|
||||||
|
Q: How about adding viewports in addition to workspaces?
|
||||||
|
|
||||||
|
A: I could conceivably be convinced to use viewports _instead_ of
|
||||||
|
workspaces, though currently I'm not thinking that. But I don't
|
||||||
|
think it makes any sense to have both; it's just confusing. They
|
||||||
|
are functionally equivalent.
|
||||||
|
|
||||||
|
You may think this means that you won't have certain keybindings,
|
||||||
|
or something like that. This is a misconception. The only
|
||||||
|
_fundamental_ difference between viewports and workspaces is that
|
||||||
|
with viewports, windows can "overlap" and appear partially on
|
||||||
|
one and partially on another. All other differences that
|
||||||
|
traditionally exist in other window managers are accidental -
|
||||||
|
the features commonly associated with viewports can be implemented
|
||||||
|
for workspaces, and vice versa.
|
||||||
|
|
||||||
|
So I don't want to have two kinds of
|
||||||
|
workspace/desktop/viewport/whatever, but I'm willing to add
|
||||||
|
features traditionally associated with either kind if those
|
||||||
|
features make sense.
|
||||||
|
|
||||||
|
Q: Why is the panel always on top?
|
||||||
|
|
||||||
|
A: Because it's a better user interface, and until we made this not
|
||||||
|
configurable a bunch of apps were not getting fixed (the app
|
||||||
|
authors were just saying "put your panel on the bottom" instead of
|
||||||
|
properly supporting fullscreen mode, and such).
|
||||||
|
|
||||||
|
rationales.txt has the bugzilla URL for some flamefesting on this,
|
||||||
|
if you want to go back and relive the glory.
|
||||||
|
Read these and the bugzilla stuff before asking/commenting:
|
||||||
|
http://pobox.com/~hp/free-software-ui.html
|
||||||
|
http://pobox.com/~hp/features.html
|
||||||
|
|
||||||
|
Q: Why is there no edge flipping?
|
||||||
|
|
||||||
|
A: This one is also in rationales.txt. Because "ouija board" UI, where
|
||||||
|
you just move the mouse around and the computer guesses what you
|
||||||
|
mean, has a lot of issues. This includes mouse focus, shade-hover
|
||||||
|
mode, edge flipping, autoraise, etc. Metacity has mouse focus and
|
||||||
|
autoraise as a compromise, but these features are all confusing for
|
||||||
|
many users, and cause problems with accessibility, fitt's law, and
|
||||||
|
so on.
|
||||||
|
|
||||||
|
Read these and the bugzilla stuff before asking/commenting:
|
||||||
|
http://pobox.com/~hp/free-software-ui.html
|
||||||
|
http://pobox.com/~hp/features.html
|
||||||
|
|
||||||
|
Q: Why does wireframe move/resize suck?
|
||||||
|
|
||||||
|
A: You can turn it on with the reduced_resources setting.
|
||||||
|
|
||||||
|
But: it has low usability, and is a pain
|
||||||
|
to implement, and there's no reason opaque move/resize should be a
|
||||||
|
problem on any setup that can run a modern desktop worth a darn to
|
||||||
|
begin with.
|
||||||
|
|
||||||
|
Read these and the bugzilla stuff before asking/commenting:
|
||||||
|
http://pobox.com/~hp/free-software-ui.html
|
||||||
|
http://pobox.com/~hp/features.html
|
||||||
|
|
||||||
|
The reason we had to add wireframe anyway was broken
|
||||||
|
proprietary apps that can't handle lots of resize events.
|
||||||
|
|
||||||
|
Q: Why no XYZ?
|
||||||
|
|
||||||
|
A: You are probably getting the idea by now - check rationales.txt,
|
||||||
|
query/search bugzilla, and read http://pobox.com/~hp/features.html
|
||||||
|
and http://pobox.com/~hp/free-software-ui.html
|
||||||
|
|
||||||
|
Then sit down and answer the question for yourself. Is the feature
|
||||||
|
good? What's the rationale for it? Answer "why" not just "why not."
|
||||||
|
Justify in terms of users as a whole, not just users like
|
||||||
|
yourself. How else can you solve the same problem? etc. If that
|
||||||
|
leads you to a strong opinion, then please, post the rationale for
|
||||||
|
discussion to an appropriate bugzilla bug, or to
|
||||||
|
usability@gnome.org.
|
||||||
|
|
||||||
|
Please don't just "me too!" on bugzilla bugs, please don't think
|
||||||
|
flames will get you anywhere, and please don't repeat rationale
|
||||||
|
that's already been offered.
|
||||||
|
|
||||||
|
Q: Your dumb web pages you made me read talk about solving problems in
|
||||||
|
fundamental ways instead of adding preferences or workarounds.
|
||||||
|
What are some examples where metacity has done this?
|
||||||
|
|
||||||
|
A: There are quite a few, though many opportunities remain. Sometimes
|
||||||
|
the real fix involves application changes. The metacity approach is
|
||||||
|
that it's OK to require apps to change, though there are also
|
||||||
|
plenty of workarounds in metacity for battles considered too hard
|
||||||
|
to fight.
|
||||||
|
|
||||||
|
Here are some examples:
|
||||||
|
|
||||||
|
- fullscreen mode was introduced to allow position constraints,
|
||||||
|
panel-on-top, and other such things to apply to normal windows
|
||||||
|
while still allowing video players etc. to "just work"
|
||||||
|
|
||||||
|
- "whether to include minimized windows in Alt+Tab" was solved
|
||||||
|
by putting minimized windows at the *end* of the tab order.
|
||||||
|
|
||||||
|
- Whether to pop up a feedback display during Alt+Tab was solved by
|
||||||
|
having both Alt+Tab and Alt+Esc
|
||||||
|
|
||||||
|
- Whether to have a "kill" feature was solved by automatically
|
||||||
|
detecting and offering to kill stuck apps. Better, metacity
|
||||||
|
actually does "kill -9" on the process, it doesn't just
|
||||||
|
disconnect the process from the X server. You'll appreciate this
|
||||||
|
if you ever did a "kill" on Netscape 4, and watched it keep
|
||||||
|
eating 100% CPU even though the X server had booted it.
|
||||||
|
|
||||||
|
- The workspaces vs. viewports mess was avoided by adding
|
||||||
|
directional navigation and such to workspaces, see discussion
|
||||||
|
earlier in this file.
|
||||||
|
|
||||||
|
- Instead of configurable placement algorithms, there's just one
|
||||||
|
that works fairly well most of the time.
|
||||||
|
|
||||||
|
- To avoid excess CPU use during opaque move/resize, we rate limit
|
||||||
|
the updates to the application window's size.
|
||||||
|
|
||||||
|
- Instead of configurable "show size of window while resizing,"
|
||||||
|
it's only shown for windows where it matters, such as terminals.
|
||||||
|
(Only use-case given for all windows is for web designers
|
||||||
|
choosing their web browser size, but there are web sites and
|
||||||
|
desktop backgrounds that do this for you.)
|
||||||
|
|
||||||
|
- Using startup notification, applications open on the workspace
|
||||||
|
where you launched them, not the active workspace when their
|
||||||
|
window is opened.
|
||||||
|
|
||||||
|
- and much more.
|
||||||
|
|
||||||
|
Q: I think mutter sucks.
|
||||||
|
|
||||||
|
A: Feel free to use any WM you like. The reason metacity follows the
|
||||||
|
ICCCM and EWMH specifications is that it makes metacity a modular,
|
||||||
|
interchangeable part in the desktop. libwnck-based apps such as the
|
||||||
|
GNOME window list will work just fine with any EWMH-compliant WM.
|
||||||
|
|
||||||
|
Q: Did you spend a lot of time on this?
|
||||||
|
|
||||||
|
A: Originally the answer was no. Sadly the answer is now yes.
|
||||||
|
|
||||||
|
Q: How can you claim that you are anti-crack, while still
|
||||||
|
writing a window manager?
|
||||||
|
|
||||||
|
A: I have no comment on that.
|
||||||
@@ -5,7 +5,7 @@ srcdir=`dirname $0`
|
|||||||
test -z "$srcdir" && srcdir=.
|
test -z "$srcdir" && srcdir=.
|
||||||
|
|
||||||
PKG_NAME="mutter"
|
PKG_NAME="mutter"
|
||||||
REQUIRED_AUTOMAKE_VERSION=1.10
|
REQUIRED_AUTOMAKE_VERSION=1.13
|
||||||
|
|
||||||
(test -f $srcdir/configure.ac \
|
(test -f $srcdir/configure.ac \
|
||||||
&& test -d $srcdir/src) || {
|
&& test -d $srcdir/src) || {
|
||||||
|
|||||||
17
configure.ac
17
configure.ac
@@ -2,8 +2,8 @@ AC_PREREQ(2.50)
|
|||||||
AC_CONFIG_MACRO_DIR([m4])
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
|
|
||||||
m4_define([mutter_major_version], [3])
|
m4_define([mutter_major_version], [3])
|
||||||
m4_define([mutter_minor_version], [12])
|
m4_define([mutter_minor_version], [11])
|
||||||
m4_define([mutter_micro_version], [0])
|
m4_define([mutter_micro_version], [90])
|
||||||
|
|
||||||
m4_define([mutter_version],
|
m4_define([mutter_version],
|
||||||
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
||||||
@@ -16,7 +16,7 @@ AC_INIT([mutter], [mutter_version],
|
|||||||
AC_CONFIG_SRCDIR(src/core/display.c)
|
AC_CONFIG_SRCDIR(src/core/display.c)
|
||||||
AC_CONFIG_HEADERS(config.h)
|
AC_CONFIG_HEADERS(config.h)
|
||||||
|
|
||||||
AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz tar-ustar subdir-objects])
|
AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz tar-ustar])
|
||||||
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],)
|
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],)
|
||||||
AM_MAINTAINER_MODE([enable])
|
AM_MAINTAINER_MODE([enable])
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@ MUTTER_PC_MODULES="
|
|||||||
cairo >= 1.10.0
|
cairo >= 1.10.0
|
||||||
gsettings-desktop-schemas >= 3.7.3
|
gsettings-desktop-schemas >= 3.7.3
|
||||||
xcomposite >= 0.2 xfixes xrender xdamage xi >= 1.6.0
|
xcomposite >= 0.2 xfixes xrender xdamage xi >= 1.6.0
|
||||||
$CLUTTER_PACKAGE >= 1.17.5
|
$CLUTTER_PACKAGE >= 1.17.1
|
||||||
cogl-1.0 >= 1.17.1
|
cogl-1.0 >= 1.17.1
|
||||||
upower-glib >= 0.99.0
|
upower-glib >= 0.99.0
|
||||||
gnome-desktop-3.0
|
gnome-desktop-3.0
|
||||||
@@ -133,7 +133,7 @@ AC_ARG_WITH([wayland-protocols],
|
|||||||
AC_ARG_WITH([xwayland-path],
|
AC_ARG_WITH([xwayland-path],
|
||||||
[AS_HELP_STRING([--with-xwayland-path], [Absolute path for an X Wayland server])],
|
[AS_HELP_STRING([--with-xwayland-path], [Absolute path for an X Wayland server])],
|
||||||
[XWAYLAND_PATH="$withval"],
|
[XWAYLAND_PATH="$withval"],
|
||||||
[XWAYLAND_PATH="$bindir/Xwayland"])
|
[XWAYLAND_PATH="$bindir/Xorg"])
|
||||||
|
|
||||||
AM_GLIB_GNU_GETTEXT
|
AM_GLIB_GNU_GETTEXT
|
||||||
|
|
||||||
@@ -142,6 +142,11 @@ AM_GLIB_GNU_GETTEXT
|
|||||||
PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.14.0)
|
PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.14.0)
|
||||||
PKG_CHECK_MODULES(MUTTER_LAUNCH, libdrm libsystemd-login)
|
PKG_CHECK_MODULES(MUTTER_LAUNCH, libdrm libsystemd-login)
|
||||||
|
|
||||||
|
saved_LIBS="$LIBS"
|
||||||
|
LIBS="$LIBS $MUTTER_LAUNCH"
|
||||||
|
AC_CHECK_FUNCS([sd_session_get_vt])
|
||||||
|
LIBS="$saved_LIBS"
|
||||||
|
|
||||||
# Unconditionally use this dir to avoid a circular dep with gnomecc
|
# Unconditionally use this dir to avoid a circular dep with gnomecc
|
||||||
GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings"
|
GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings"
|
||||||
AC_SUBST(GNOME_KEYBINDINGS_KEYSDIR)
|
AC_SUBST(GNOME_KEYBINDINGS_KEYSDIR)
|
||||||
@@ -453,6 +458,7 @@ doc/reference/meta-docs.sgml
|
|||||||
src/Makefile
|
src/Makefile
|
||||||
src/libmutter-wayland.pc
|
src/libmutter-wayland.pc
|
||||||
src/compositor/plugins/Makefile
|
src/compositor/plugins/Makefile
|
||||||
|
protocol/Makefile
|
||||||
po/Makefile.in
|
po/Makefile.in
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -480,6 +486,7 @@ mutter-wayland-$VERSION
|
|||||||
Session management: ${found_sm}
|
Session management: ${found_sm}
|
||||||
Shape extension: ${found_shape}
|
Shape extension: ${found_shape}
|
||||||
Xsync: ${found_xsync}
|
Xsync: ${found_xsync}
|
||||||
|
Xcursor: ${have_xcursor}
|
||||||
"
|
"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
SUBDIRS = man reference
|
SUBDIRS = man reference
|
||||||
|
|
||||||
EXTRA_DIST=theme-format.txt dialogs.txt code-overview.txt \
|
EXTRA_DIST=theme-format.txt dialogs.txt code-overview.txt \
|
||||||
how-to-get-focus-right.txt rationales.txt
|
how-to-get-focus-right.txt
|
||||||
|
|||||||
@@ -16,11 +16,11 @@ src/core/monitor.c
|
|||||||
src/core/mutter.c
|
src/core/mutter.c
|
||||||
src/core/prefs.c
|
src/core/prefs.c
|
||||||
src/core/screen.c
|
src/core/screen.c
|
||||||
src/x11/session.c
|
src/core/session.c
|
||||||
src/core/util.c
|
src/core/util.c
|
||||||
src/core/window.c
|
src/core/window.c
|
||||||
src/x11/window-props.c
|
src/core/window-props.c
|
||||||
src/x11/xprops.c
|
src/core/xprops.c
|
||||||
src/mutter-wayland.desktop.in
|
src/mutter-wayland.desktop.in
|
||||||
src/org.gnome.mutter.gschema.xml.in
|
src/org.gnome.mutter.gschema.xml.in
|
||||||
src/org.gnome.mutter.wayland.gschema.xml.in
|
src/org.gnome.mutter.wayland.gschema.xml.in
|
||||||
|
|||||||
7
protocol/Makefile.am
Normal file
7
protocol/Makefile.am
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
NULL =
|
||||||
|
|
||||||
|
EXTRA_DIST = \
|
||||||
|
gtk-shell.xml \
|
||||||
|
xdg-shell.xml \
|
||||||
|
xserver.xml \
|
||||||
|
$(NULL)
|
||||||
@@ -40,22 +40,19 @@
|
|||||||
|
|
||||||
<enum name="version">
|
<enum name="version">
|
||||||
<description summary="latest protocol version">
|
<description summary="latest protocol version">
|
||||||
The 'current' member of this enum gives the version of the
|
Use this enum to check the protocol version, and it will be updated
|
||||||
protocol. Implementations can compare this to the version
|
automatically.
|
||||||
they implement using static_assert to ensure the protocol and
|
|
||||||
implementation versions match.
|
|
||||||
</description>
|
</description>
|
||||||
<entry name="current" value="3" summary="Always the latest version"/>
|
<entry name="current" value="2" summary="Always the latest version"/>
|
||||||
</enum>
|
</enum>
|
||||||
|
|
||||||
|
|
||||||
<request name="use_unstable_version">
|
<request name="use_unstable_version">
|
||||||
<description summary="enable use of this unstable version">
|
<description summary="enable use of this unstable version">
|
||||||
Negotiate the unstable version of the interface. This
|
Use this request in order to enable use of this interface.
|
||||||
mechanism is in place to ensure client and server agree on the
|
|
||||||
unstable versions of the protocol that they speak or exit
|
Understand and agree that one is using an unstable interface,
|
||||||
cleanly if they don't agree. This request will go away once
|
that will likely change in the future, breaking the API.
|
||||||
the xdg-shell protocol is stable.
|
|
||||||
</description>
|
</description>
|
||||||
<arg name="version" type="int"/>
|
<arg name="version" type="int"/>
|
||||||
</request>
|
</request>
|
||||||
@@ -278,87 +275,113 @@
|
|||||||
<arg name="output" type="object" interface="wl_output" allow-null="true"/>
|
<arg name="output" type="object" interface="wl_output" allow-null="true"/>
|
||||||
</request>
|
</request>
|
||||||
|
|
||||||
<enum name="state">
|
<event name="request_set_fullscreen">
|
||||||
<description summary="types of state on the surface">
|
<description summary="server requests that the client set fullscreen">
|
||||||
The different state values used on the surface. This is designed for
|
Event sent from the compositor to the client requesting that the client
|
||||||
state values like maximized, fullscreen. It is paired with the
|
goes to a fullscreen state. It's the client job to call set_fullscreen
|
||||||
request_change_state event to ensure that both the client and the
|
and really trigger the fullscreen state.
|
||||||
compositor setting the state can be synchronized.
|
|
||||||
|
|
||||||
States set in this way are double-buffered. They will get applied on
|
|
||||||
the next commit.
|
|
||||||
|
|
||||||
Desktop environments may extend this enum by taking up a range of
|
|
||||||
values and documenting the range they chose in this description.
|
|
||||||
They are not required to document the values for the range that they
|
|
||||||
chose. Ideally, any good extensions from a desktop environment should
|
|
||||||
make its way into standardization into this enum.
|
|
||||||
|
|
||||||
The current reserved ranges are:
|
|
||||||
|
|
||||||
0x0000 - 0x0FFF: xdg-shell core values, documented below.
|
|
||||||
0x1000 - 0x1FFF: GNOME
|
|
||||||
</description>
|
</description>
|
||||||
<entry name="maximized" value="1" summary="the surface is maximized">
|
|
||||||
A non-zero value indicates the surface is maximized. Otherwise,
|
|
||||||
the surface is unmaximized.
|
|
||||||
</entry>
|
|
||||||
<entry name="fullscreen" value="2" summary="the surface is fullscreen">
|
|
||||||
A non-zero value indicates the surface is fullscreen. Otherwise,
|
|
||||||
the surface is not fullscreen.
|
|
||||||
</entry>
|
|
||||||
</enum>
|
|
||||||
|
|
||||||
<request name="request_change_state">
|
|
||||||
<description summary="client requests to change a surface's state">
|
|
||||||
This asks the compositor to change the state. If the compositor wants
|
|
||||||
to change the state, it will send a change_state event with the same
|
|
||||||
state_type, value, and serial, and the event flow continues as if it
|
|
||||||
it was initiated by the compositor.
|
|
||||||
|
|
||||||
If the compositor does not want to change the state, it will send a
|
|
||||||
change_state to the client with the old value of the state.
|
|
||||||
</description>
|
|
||||||
<arg name="state_type" type="uint" summary="the state to set"/>
|
|
||||||
<arg name="value" type="uint" summary="the value to change the state to"/>
|
|
||||||
<arg name="serial" type="uint" summary="an event serial">
|
|
||||||
This serial is so the client can know which change_state event corresponds
|
|
||||||
to which request_change_state request it sent out.
|
|
||||||
</arg>
|
|
||||||
</request>
|
|
||||||
|
|
||||||
<event name="change_state">
|
|
||||||
<description summary="compositor wants to change a surface's state">
|
|
||||||
This event tells the client to change a surface's state. The client
|
|
||||||
should respond with an ack_change_state request to the compositor to
|
|
||||||
guarantee that the compositor knows that the client has seen it.
|
|
||||||
</description>
|
|
||||||
|
|
||||||
<arg name="state_type" type="uint" summary="the state to set"/>
|
|
||||||
<arg name="value" type="uint" summary="the value to change the state to"/>
|
|
||||||
<arg name="serial" type="uint" summary="a serial for the compositor's own tracking"/>
|
|
||||||
</event>
|
</event>
|
||||||
|
|
||||||
<request name="ack_change_state">
|
<event name="request_unset_fullscreen">
|
||||||
<description summary="ack a change_state event">
|
<description summary="server requests that the client unset fullscreen">
|
||||||
When a change_state event is received, a client should then ack it
|
Event sent from the compositor to the client requesting that the client
|
||||||
using the ack_change_state request to ensure that the compositor
|
leaves the fullscreen state. It's the client job to call
|
||||||
knows the client has seen the event.
|
unset_fullscreen and really leave the fullscreen state.
|
||||||
|
</description>
|
||||||
By this point, the state is confirmed, and the next attach should
|
</event>
|
||||||
contain the buffer drawn for the new state value.
|
|
||||||
|
<request name="set_fullscreen">
|
||||||
The values here need to be the same as the values in the cooresponding
|
<description summary="set the surface state as fullscreen">
|
||||||
change_state event.
|
Set the surface as fullscreen.
|
||||||
|
|
||||||
|
After this request, the compositor should send a configure event
|
||||||
|
informing the output size.
|
||||||
|
|
||||||
|
This request informs the compositor that the next attached buffer
|
||||||
|
committed will be in a fullscreen state. The buffer size should be the
|
||||||
|
same size as the size informed in the configure event, if the client
|
||||||
|
doesn't want to leave any empty area.
|
||||||
|
|
||||||
|
In other words: the next attached buffer after set_maximized is the new
|
||||||
|
maximized buffer. And the surface will be positioned at the maximized
|
||||||
|
position on commit.
|
||||||
|
|
||||||
|
A simple way to synchronize and wait for the correct configure event is
|
||||||
|
to use a wl_display.sync request right after the set_fullscreen
|
||||||
|
request. When the sync callback returns, the last configure event
|
||||||
|
received just before it will be the correct one, and should contain the
|
||||||
|
right size for the surface to maximize.
|
||||||
|
|
||||||
|
Setting one state won't unset another state. Use
|
||||||
|
xdg_surface.unset_fullscreen for unsetting it.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="unset_fullscreen">
|
||||||
|
<description summary="unset the surface state as fullscreen">
|
||||||
|
Unset the surface fullscreen state.
|
||||||
|
|
||||||
|
Same negotiation as set_fullscreen must be used.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<event name="request_set_maximized">
|
||||||
|
<description summary="server requests that the client set maximized">
|
||||||
|
Event sent from the compositor to the client requesting that the client
|
||||||
|
goes to a maximized state. It's the client job to call set_maximized
|
||||||
|
and really trigger the maximized state.
|
||||||
|
</description>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="request_unset_maximized">
|
||||||
|
<description summary="server requests that the client unset maximized">
|
||||||
|
Event sent from the compositor to the client requesting that the client
|
||||||
|
leaves the maximized state. It's the client job to call unset_maximized
|
||||||
|
and really leave the maximized state.
|
||||||
|
</description>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<request name="set_maximized">
|
||||||
|
<description summary="set the surface state as maximized">
|
||||||
|
Set the surface as maximized.
|
||||||
|
|
||||||
|
After this request, the compositor will send a configure event
|
||||||
|
informing the output size minus panel and other MW decorations.
|
||||||
|
|
||||||
|
This request informs the compositor that the next attached buffer
|
||||||
|
committed will be in a maximized state. The buffer size should be the
|
||||||
|
same size as the size informed in the configure event, if the client
|
||||||
|
doesn't want to leave any empty area.
|
||||||
|
|
||||||
|
In other words: the next attached buffer after set_maximized is the new
|
||||||
|
maximized buffer. And the surface will be positioned at the maximized
|
||||||
|
position on commit.
|
||||||
|
|
||||||
|
A simple way to synchronize and wait for the correct configure event is
|
||||||
|
to use a wl_display.sync request right after the set_maximized request.
|
||||||
|
When the sync callback returns, the last configure event received just
|
||||||
|
before it will be the correct one, and should contain the right size
|
||||||
|
for the surface to maximize.
|
||||||
|
|
||||||
|
Setting one state won't unset another state. Use
|
||||||
|
xdg_surface.unset_maximized for unsetting it.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="unset_maximized">
|
||||||
|
<description summary="unset the surface state as maximized">
|
||||||
|
Unset the surface maximized state.
|
||||||
|
|
||||||
|
Same negotiation as set_maximized must be used.
|
||||||
</description>
|
</description>
|
||||||
<arg name="state_type" type="uint" summary="the state to set"/>
|
|
||||||
<arg name="value" type="uint" summary="the value to change the state to"/>
|
|
||||||
<arg name="serial" type="uint" summary="a serial to pass to change_state"/>
|
|
||||||
</request>
|
</request>
|
||||||
|
|
||||||
<request name="set_minimized">
|
<request name="set_minimized">
|
||||||
<description summary="minimize the surface">
|
<description summary="set the surface state as minimized">
|
||||||
Minimize the surface.
|
Set the surface minimized state.
|
||||||
|
|
||||||
|
Setting one state won't unset another state.
|
||||||
</description>
|
</description>
|
||||||
</request>
|
</request>
|
||||||
|
|
||||||
18
protocol/xserver.xml
Normal file
18
protocol/xserver.xml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<protocol name="xserver">
|
||||||
|
|
||||||
|
<interface name="xserver" version="1">
|
||||||
|
<request name="set_window_id">
|
||||||
|
<arg name="surface" type="object" interface="wl_surface"/>
|
||||||
|
<arg name="id" type="uint"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<event name="client">
|
||||||
|
<arg name="fd" type="fd"/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="listen_socket">
|
||||||
|
<arg name="fd" type="fd"/>
|
||||||
|
</event>
|
||||||
|
</interface>
|
||||||
|
|
||||||
|
</protocol>
|
||||||
@@ -29,18 +29,6 @@
|
|||||||
<KeyListEntry name="move-to-workspace-down"
|
<KeyListEntry name="move-to-workspace-down"
|
||||||
_description="Move window one 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"
|
<KeyListEntry name="switch-applications"
|
||||||
_description="Switch applications"/>
|
_description="Switch applications"/>
|
||||||
|
|
||||||
|
|||||||
148
src/Makefile.am
148
src/Makefile.am
@@ -6,14 +6,12 @@ lib_LTLIBRARIES = libmutter-wayland.la
|
|||||||
SUBDIRS=compositor/plugins
|
SUBDIRS=compositor/plugins
|
||||||
|
|
||||||
INCLUDES= \
|
INCLUDES= \
|
||||||
-DCLUTTER_ENABLE_COMPOSITOR_API \
|
|
||||||
-DCLUTTER_ENABLE_EXPERIMENTAL_API \
|
-DCLUTTER_ENABLE_EXPERIMENTAL_API \
|
||||||
-DCOGL_ENABLE_EXPERIMENTAL_API \
|
-DCOGL_ENABLE_EXPERIMENTAL_API \
|
||||||
-DCOGL_ENABLE_EXPERIMENTAL_2_0_API \
|
-DCOGL_ENABLE_EXPERIMENTAL_2_0_API \
|
||||||
$(MUTTER_CFLAGS) \
|
$(MUTTER_CFLAGS) \
|
||||||
-I$(top_builddir) \
|
-I$(top_builddir) \
|
||||||
-I$(srcdir) \
|
-I$(srcdir) \
|
||||||
-I$(srcdir)/backends \
|
|
||||||
-I$(srcdir)/core \
|
-I$(srcdir)/core \
|
||||||
-I$(srcdir)/ui \
|
-I$(srcdir)/ui \
|
||||||
-I$(srcdir)/compositor \
|
-I$(srcdir)/compositor \
|
||||||
@@ -30,55 +28,28 @@ INCLUDES= \
|
|||||||
-DMUTTER_PLUGIN_API_VERSION=$(MUTTER_PLUGIN_API_VERSION) \
|
-DMUTTER_PLUGIN_API_VERSION=$(MUTTER_PLUGIN_API_VERSION) \
|
||||||
-DMUTTER_PKGLIBDIR=\"$(pkglibdir)\" \
|
-DMUTTER_PKGLIBDIR=\"$(pkglibdir)\" \
|
||||||
-DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\" \
|
-DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\" \
|
||||||
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \
|
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\"
|
||||||
|
|
||||||
|
INCLUDES += \
|
||||||
|
-I$(srcdir)/wayland \
|
||||||
|
-I$(builddir)/wayland \
|
||||||
-DXWAYLAND_PATH='"@XWAYLAND_PATH@"'
|
-DXWAYLAND_PATH='"@XWAYLAND_PATH@"'
|
||||||
|
|
||||||
mutter_built_sources = \
|
mutter_built_sources = \
|
||||||
$(dbus_idle_built_sources) \
|
$(dbus_idle_built_sources) \
|
||||||
$(dbus_display_config_built_sources) \
|
$(dbus_xrandr_built_sources) \
|
||||||
mutter-enum-types.h \
|
mutter-enum-types.h \
|
||||||
mutter-enum-types.c \
|
mutter-enum-types.c \
|
||||||
gtk-shell-protocol.c \
|
wayland/gtk-shell-protocol.c \
|
||||||
gtk-shell-server-protocol.h \
|
wayland/gtk-shell-server-protocol.h \
|
||||||
xdg-shell-protocol.c \
|
wayland/xdg-shell-protocol.c \
|
||||||
xdg-shell-server-protocol.h
|
wayland/xdg-shell-server-protocol.h \
|
||||||
|
wayland/xserver-protocol.c \
|
||||||
wayland_protocols = \
|
wayland/xserver-server-protocol.h
|
||||||
wayland/protocol/gtk-shell.xml \
|
|
||||||
wayland/protocol/xdg-shell.xml
|
|
||||||
|
|
||||||
libmutter_wayland_la_SOURCES = \
|
libmutter_wayland_la_SOURCES = \
|
||||||
backends/meta-backend.c \
|
core/async-getprop.c \
|
||||||
backends/meta-backend.h \
|
core/async-getprop.h \
|
||||||
backends/meta-cursor.c \
|
|
||||||
backends/meta-cursor.h \
|
|
||||||
backends/meta-cursor-private.h \
|
|
||||||
backends/meta-cursor-tracker.c \
|
|
||||||
backends/meta-cursor-tracker-private.h \
|
|
||||||
backends/meta-idle-monitor.c \
|
|
||||||
backends/meta-idle-monitor-private.h \
|
|
||||||
backends/meta-idle-monitor-dbus.c \
|
|
||||||
backends/meta-idle-monitor-dbus.h \
|
|
||||||
backends/meta-monitor-config.c \
|
|
||||||
backends/meta-monitor-config.h \
|
|
||||||
backends/meta-monitor-manager.c \
|
|
||||||
backends/meta-monitor-manager.h \
|
|
||||||
backends/meta-monitor-manager-dummy.c \
|
|
||||||
backends/meta-monitor-manager-dummy.h \
|
|
||||||
backends/edid-parse.c \
|
|
||||||
backends/edid.h \
|
|
||||||
backends/native/meta-idle-monitor-native.c \
|
|
||||||
backends/native/meta-idle-monitor-native.h \
|
|
||||||
backends/native/meta-monitor-manager-kms.c \
|
|
||||||
backends/native/meta-monitor-manager-kms.h \
|
|
||||||
backends/native/meta-weston-launch.c \
|
|
||||||
backends/native/meta-weston-launch.h \
|
|
||||||
backends/x11/meta-idle-monitor-xsync.c \
|
|
||||||
backends/x11/meta-idle-monitor-xsync.h \
|
|
||||||
backends/x11/meta-monitor-manager-xrandr.c \
|
|
||||||
backends/x11/meta-monitor-manager-xrandr.h \
|
|
||||||
backends/x11/meta-xrandr-shared.h \
|
|
||||||
core/above-tab-keycode.c \
|
|
||||||
core/barrier.c \
|
core/barrier.c \
|
||||||
meta/barrier.h \
|
meta/barrier.h \
|
||||||
core/bell.c \
|
core/bell.c \
|
||||||
@@ -133,6 +104,7 @@ libmutter_wayland_la_SOURCES = \
|
|||||||
meta/meta-shadow-factory.h \
|
meta/meta-shadow-factory.h \
|
||||||
meta/meta-window-actor.h \
|
meta/meta-window-actor.h \
|
||||||
meta/compositor-mutter.h \
|
meta/compositor-mutter.h \
|
||||||
|
core/above-tab-keycode.c \
|
||||||
core/constraints.c \
|
core/constraints.c \
|
||||||
core/constraints.h \
|
core/constraints.h \
|
||||||
core/core.c \
|
core/core.c \
|
||||||
@@ -140,19 +112,39 @@ libmutter_wayland_la_SOURCES = \
|
|||||||
core/display.c \
|
core/display.c \
|
||||||
core/display-private.h \
|
core/display-private.h \
|
||||||
meta/display.h \
|
meta/display.h \
|
||||||
|
ui/draw-workspace.c \
|
||||||
|
ui/draw-workspace.h \
|
||||||
core/edge-resistance.c \
|
core/edge-resistance.c \
|
||||||
core/edge-resistance.h \
|
core/edge-resistance.h \
|
||||||
core/events.c \
|
core/edid-parse.c \
|
||||||
core/events.h \
|
core/edid.h \
|
||||||
core/errors.c \
|
core/errors.c \
|
||||||
meta/errors.h \
|
meta/errors.h \
|
||||||
core/frame.c \
|
core/frame.c \
|
||||||
core/frame.h \
|
core/frame.h \
|
||||||
ui/gradient.c \
|
ui/gradient.c \
|
||||||
meta/gradient.h \
|
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.c \
|
||||||
core/keybindings-private.h \
|
core/keybindings-private.h \
|
||||||
core/main.c \
|
core/main.c \
|
||||||
|
core/meta-cursor-tracker.c \
|
||||||
|
core/meta-cursor-tracker-private.h \
|
||||||
|
core/meta-idle-monitor.c \
|
||||||
|
core/meta-idle-monitor-private.h \
|
||||||
|
core/meta-xrandr-shared.h \
|
||||||
|
core/monitor.c \
|
||||||
|
core/monitor-config.c \
|
||||||
|
core/monitor-kms.c \
|
||||||
|
core/monitor-private.h \
|
||||||
|
core/monitor-xrandr.c \
|
||||||
|
core/mutter-Xatomtype.h \
|
||||||
core/place.c \
|
core/place.c \
|
||||||
core/place.h \
|
core/place.h \
|
||||||
core/prefs.c \
|
core/prefs.c \
|
||||||
@@ -161,6 +153,8 @@ libmutter_wayland_la_SOURCES = \
|
|||||||
core/screen-private.h \
|
core/screen-private.h \
|
||||||
meta/screen.h \
|
meta/screen.h \
|
||||||
meta/types.h \
|
meta/types.h \
|
||||||
|
core/session.c \
|
||||||
|
core/session.h \
|
||||||
core/stack.c \
|
core/stack.c \
|
||||||
core/stack.h \
|
core/stack.h \
|
||||||
core/stack-tracker.c \
|
core/stack-tracker.c \
|
||||||
@@ -168,11 +162,17 @@ libmutter_wayland_la_SOURCES = \
|
|||||||
core/util.c \
|
core/util.c \
|
||||||
meta/util.h \
|
meta/util.h \
|
||||||
core/util-private.h \
|
core/util-private.h \
|
||||||
|
core/window-props.c \
|
||||||
|
core/window-props.h \
|
||||||
|
core/window-x11.c \
|
||||||
|
core/window-x11.h \
|
||||||
core/window.c \
|
core/window.c \
|
||||||
core/window-private.h \
|
core/window-private.h \
|
||||||
meta/window.h \
|
meta/window.h \
|
||||||
core/workspace.c \
|
core/workspace.c \
|
||||||
core/workspace-private.h \
|
core/workspace-private.h \
|
||||||
|
core/xprops.c \
|
||||||
|
core/xprops.h \
|
||||||
meta/common.h \
|
meta/common.h \
|
||||||
core/core.h \
|
core/core.h \
|
||||||
ui/ui.h \
|
ui/ui.h \
|
||||||
@@ -184,36 +184,17 @@ libmutter_wayland_la_SOURCES = \
|
|||||||
ui/metaaccellabel.h \
|
ui/metaaccellabel.h \
|
||||||
ui/resizepopup.c \
|
ui/resizepopup.c \
|
||||||
ui/resizepopup.h \
|
ui/resizepopup.h \
|
||||||
|
ui/tabpopup.c \
|
||||||
|
ui/tabpopup.h \
|
||||||
ui/theme-parser.c \
|
ui/theme-parser.c \
|
||||||
ui/theme.c \
|
ui/theme.c \
|
||||||
meta/theme.h \
|
meta/theme.h \
|
||||||
ui/theme-private.h \
|
ui/theme-private.h \
|
||||||
ui/ui.c \
|
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.c \
|
||||||
wayland/meta-wayland.h \
|
|
||||||
wayland/meta-wayland-private.h \
|
wayland/meta-wayland-private.h \
|
||||||
wayland/meta-xwayland.c \
|
|
||||||
wayland/meta-xwayland.h \
|
|
||||||
wayland/meta-xwayland-private.h \
|
wayland/meta-xwayland-private.h \
|
||||||
|
wayland/meta-xwayland.c \
|
||||||
wayland/meta-wayland-data-device.c \
|
wayland/meta-wayland-data-device.c \
|
||||||
wayland/meta-wayland-data-device.h \
|
wayland/meta-wayland-data-device.h \
|
||||||
wayland/meta-wayland-keyboard.c \
|
wayland/meta-wayland-keyboard.c \
|
||||||
@@ -228,8 +209,8 @@ libmutter_wayland_la_SOURCES = \
|
|||||||
wayland/meta-wayland-surface.h \
|
wayland/meta-wayland-surface.h \
|
||||||
wayland/meta-wayland-types.h \
|
wayland/meta-wayland-types.h \
|
||||||
wayland/meta-wayland-versions.h \
|
wayland/meta-wayland-versions.h \
|
||||||
wayland/window-wayland.c \
|
wayland/meta-weston-launch.c \
|
||||||
wayland/window-wayland.h
|
wayland/meta-weston-launch.h
|
||||||
|
|
||||||
nodist_libmutter_wayland_la_SOURCES = \
|
nodist_libmutter_wayland_la_SOURCES = \
|
||||||
$(mutter_built_sources)
|
$(mutter_built_sources)
|
||||||
@@ -286,9 +267,7 @@ mutter_wayland_LDADD = $(MUTTER_LIBS) libmutter-wayland.la
|
|||||||
|
|
||||||
bin_PROGRAMS+=mutter-launch
|
bin_PROGRAMS+=mutter-launch
|
||||||
|
|
||||||
mutter_launch_SOURCES = \
|
mutter_launch_SOURCES = wayland/weston-launch.c wayland/weston-launch.h
|
||||||
backends/native/weston-launch.c \
|
|
||||||
backends/native/weston-launch.h
|
|
||||||
|
|
||||||
mutter_launch_CFLAGS = $(MUTTER_LAUNCH_CFLAGS) -DLIBDIR=\"$(libdir)\"
|
mutter_launch_CFLAGS = $(MUTTER_LAUNCH_CFLAGS) -DLIBDIR=\"$(libdir)\"
|
||||||
mutter_launch_LDFLAGS = $(MUTTER_LAUNCH_LIBS) -lpam
|
mutter_launch_LDFLAGS = $(MUTTER_LAUNCH_LIBS) -lpam
|
||||||
@@ -332,7 +311,7 @@ endif
|
|||||||
|
|
||||||
testboxes_SOURCES = core/testboxes.c
|
testboxes_SOURCES = core/testboxes.c
|
||||||
testgradient_SOURCES = ui/testgradient.c
|
testgradient_SOURCES = ui/testgradient.c
|
||||||
testasyncgetprop_SOURCES = x11/testasyncgetprop.c
|
testasyncgetprop_SOURCES = core/testasyncgetprop.c
|
||||||
|
|
||||||
noinst_PROGRAMS=testboxes testgradient testasyncgetprop
|
noinst_PROGRAMS=testboxes testgradient testasyncgetprop
|
||||||
|
|
||||||
@@ -383,15 +362,13 @@ EXTRA_DIST=$(desktopfiles_files) \
|
|||||||
$(desktopfiles_in_files) \
|
$(desktopfiles_in_files) \
|
||||||
$(wmproperties_in_files) \
|
$(wmproperties_in_files) \
|
||||||
$(xml_in_files) \
|
$(xml_in_files) \
|
||||||
$(wayland_protocols) \
|
|
||||||
org.gnome.mutter.gschema.xml.in \
|
org.gnome.mutter.gschema.xml.in \
|
||||||
org.gnome.mutter.wayland.gschema.xml.in \
|
org.gnome.mutter.wayland.gschema.xml.in \
|
||||||
mutter-schemas.convert \
|
mutter-schemas.convert \
|
||||||
libmutter-wayland.pc.in \
|
libmutter-wayland.pc.in \
|
||||||
mutter-enum-types.h.in \
|
mutter-enum-types.h.in \
|
||||||
mutter-enum-types.c.in \
|
mutter-enum-types.c.in \
|
||||||
org.gnome.Mutter.DisplayConfig.xml \
|
xrandr.xml idle-monitor.xml
|
||||||
org.gnome.Mutter.IdleMonitor.xml
|
|
||||||
|
|
||||||
BUILT_SOURCES = $(mutter_built_sources)
|
BUILT_SOURCES = $(mutter_built_sources)
|
||||||
MUTTER_STAMP_FILES = stamp-mutter-enum-types.h
|
MUTTER_STAMP_FILES = stamp-mutter-enum-types.h
|
||||||
@@ -416,24 +393,27 @@ mutter-enum-types.c: stamp-mutter-enum-types.h mutter-enum-types.c.in
|
|||||||
cp xgen-tetc mutter-enum-types.c && \
|
cp xgen-tetc mutter-enum-types.c && \
|
||||||
rm -f xgen-tetc
|
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 \
|
$(AM_V_GEN)gdbus-codegen \
|
||||||
--interface-prefix org.gnome.Mutter \
|
--interface-prefix org.gnome.Mutter \
|
||||||
--c-namespace MetaDBus \
|
--c-namespace MetaDBus \
|
||||||
--generate-c-code meta-dbus-display-config \
|
--generate-c-code meta-dbus-xrandr \
|
||||||
$(srcdir)/org.gnome.Mutter.DisplayConfig.xml
|
$(srcdir)/xrandr.xml
|
||||||
|
|
||||||
$(dbus_idle_built_sources) : Makefile.am org.gnome.Mutter.IdleMonitor.xml
|
|
||||||
|
$(dbus_idle_built_sources) : Makefile.am idle-monitor.xml
|
||||||
$(AM_V_GEN)gdbus-codegen \
|
$(AM_V_GEN)gdbus-codegen \
|
||||||
--interface-prefix org.gnome.Mutter \
|
--interface-prefix org.gnome.Mutter \
|
||||||
--c-namespace MetaDBus \
|
--c-namespace MetaDBus \
|
||||||
--generate-c-code meta-dbus-idle-monitor \
|
--generate-c-code meta-dbus-idle-monitor \
|
||||||
--c-generate-object-manager \
|
--c-generate-object-manager \
|
||||||
$(srcdir)/org.gnome.Mutter.IdleMonitor.xml
|
$(srcdir)/idle-monitor.xml
|
||||||
|
|
||||||
%-protocol.c : $(srcdir)/wayland/protocol/%.xml
|
wayland/%-protocol.c : $(top_builddir)/protocol/%.xml
|
||||||
|
mkdir -p wayland
|
||||||
$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
|
$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
|
||||||
%-server-protocol.h : $(srcdir)/wayland/protocol/%.xml
|
wayland/%-server-protocol.h : $(top_builddir)/protocol/%.xml
|
||||||
|
mkdir -p wayland
|
||||||
$(AM_V_GEN)$(WAYLAND_SCANNER) server-header < $< > $@
|
$(AM_V_GEN)$(WAYLAND_SCANNER) server-header < $< > $@
|
||||||
|
|||||||
@@ -1,157 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2014 Red Hat
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
||||||
* 02111-1307, USA.
|
|
||||||
*
|
|
||||||
* Written by:
|
|
||||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include "meta-backend.h"
|
|
||||||
#include <meta/main.h>
|
|
||||||
|
|
||||||
#include <gdk/gdkx.h>
|
|
||||||
#include <clutter/clutter.h>
|
|
||||||
#include <clutter/x11/clutter-x11.h>
|
|
||||||
|
|
||||||
#include "backends/native/meta-weston-launch.h"
|
|
||||||
#include <meta/util.h>
|
|
||||||
|
|
||||||
/* Mutter is responsible for pulling events off the X queue, so Clutter
|
|
||||||
* doesn't need (and shouldn't) run its normal event source which polls
|
|
||||||
* the X fd, but we do have to deal with dispatching events that accumulate
|
|
||||||
* in the clutter queue. This happens, for example, when clutter generate
|
|
||||||
* enter/leave events on mouse motion - several events are queued in the
|
|
||||||
* clutter queue but only one dispatched. It could also happen because of
|
|
||||||
* explicit calls to clutter_event_put(). We add a very simple custom
|
|
||||||
* event loop source which is simply responsible for pulling events off
|
|
||||||
* of the queue and dispatching them before we block for new events.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
event_prepare (GSource *source,
|
|
||||||
gint *timeout_)
|
|
||||||
{
|
|
||||||
*timeout_ = -1;
|
|
||||||
|
|
||||||
return clutter_events_pending ();
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
event_check (GSource *source)
|
|
||||||
{
|
|
||||||
return clutter_events_pending ();
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
event_dispatch (GSource *source,
|
|
||||||
GSourceFunc callback,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
ClutterEvent *event = clutter_event_get ();
|
|
||||||
|
|
||||||
if (event)
|
|
||||||
{
|
|
||||||
clutter_do_event (event);
|
|
||||||
clutter_event_free (event);
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GSourceFuncs event_funcs = {
|
|
||||||
event_prepare,
|
|
||||||
event_check,
|
|
||||||
event_dispatch
|
|
||||||
};
|
|
||||||
|
|
||||||
static MetaLauncher *launcher;
|
|
||||||
|
|
||||||
void
|
|
||||||
meta_clutter_init (void)
|
|
||||||
{
|
|
||||||
GSource *source;
|
|
||||||
|
|
||||||
/* When running as an X11 compositor, we install our own event filter and
|
|
||||||
* pass events to Clutter explicitly, so we need to prevent Clutter from
|
|
||||||
* handling our events.
|
|
||||||
*
|
|
||||||
* However, when running as a Wayland compostior under X11 nested, Clutter
|
|
||||||
* Clutter needs to see events related to its own window. We need to
|
|
||||||
* eventually replace this with a proper frontend / backend split: Clutter
|
|
||||||
* under nested is connecting to the "host X server" to get its events it
|
|
||||||
* needs to put up a window, and GTK+ is connecting to the "inner X server".
|
|
||||||
* The two would the same in the X11 compositor case, but not when running
|
|
||||||
* XWayland as a Wayland compositor.
|
|
||||||
*/
|
|
||||||
if (!meta_is_wayland_compositor ())
|
|
||||||
{
|
|
||||||
clutter_x11_set_display (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
|
|
||||||
clutter_x11_disable_event_retrieval ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we're running on bare metal, we're a display server,
|
|
||||||
* so start talking to weston-launch. */
|
|
||||||
#if defined(CLUTTER_WINDOWING_EGL)
|
|
||||||
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
|
|
||||||
launcher = meta_launcher_new ();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
|
|
||||||
g_error ("Unable to initialize Clutter.\n");
|
|
||||||
|
|
||||||
source = g_source_new (&event_funcs, sizeof (GSource));
|
|
||||||
g_source_attach (source, NULL);
|
|
||||||
g_source_unref (source);
|
|
||||||
}
|
|
||||||
|
|
||||||
gboolean
|
|
||||||
meta_activate_vt (int vt, GError **error)
|
|
||||||
{
|
|
||||||
if (launcher)
|
|
||||||
return meta_launcher_activate_vt (launcher, vt, error);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_debug ("Ignoring VT switch keybinding, not running as display server");
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* meta_activate_session:
|
|
||||||
*
|
|
||||||
* Tells mutter to activate the session. When mutter is a
|
|
||||||
* Wayland compositor, this tells logind to switch over to
|
|
||||||
* the new session.
|
|
||||||
*/
|
|
||||||
gboolean
|
|
||||||
meta_activate_session (void)
|
|
||||||
{
|
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
if (!meta_launcher_activate_vt (launcher, -1, &error))
|
|
||||||
{
|
|
||||||
g_warning ("Could not activate session: %s\n", error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2014 Red Hat
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
||||||
* 02111-1307, USA.
|
|
||||||
*
|
|
||||||
* Written by:
|
|
||||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef META_BACKEND_H
|
|
||||||
#define META_BACKEND_H
|
|
||||||
|
|
||||||
#include <glib-object.h>
|
|
||||||
|
|
||||||
void meta_clutter_init (void);
|
|
||||||
|
|
||||||
gboolean meta_activate_vt (int vt, GError **error);
|
|
||||||
|
|
||||||
#endif /* META_BACKEND_H */
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright 2013 Red Hat, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Author: Giovanni Campagna <gcampagn@redhat.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef META_CURSOR_PRIVATE_H
|
|
||||||
#define META_CURSOR_PRIVATE_H
|
|
||||||
|
|
||||||
#include "meta-cursor.h"
|
|
||||||
|
|
||||||
#include <cogl/cogl.h>
|
|
||||||
#include <gbm.h>
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
CoglTexture2D *texture;
|
|
||||||
struct gbm_bo *bo;
|
|
||||||
int hot_x, hot_y;
|
|
||||||
} MetaCursorImage;
|
|
||||||
|
|
||||||
struct _MetaCursorReference {
|
|
||||||
int ref_count;
|
|
||||||
|
|
||||||
MetaCursorImage image;
|
|
||||||
};
|
|
||||||
|
|
||||||
CoglTexture *meta_cursor_reference_get_cogl_texture (MetaCursorReference *cursor,
|
|
||||||
int *hot_x,
|
|
||||||
int *hot_y);
|
|
||||||
|
|
||||||
struct gbm_bo *meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
|
|
||||||
int *hot_x,
|
|
||||||
int *hot_y);
|
|
||||||
|
|
||||||
#endif /* META_CURSOR_PRIVATE_H */
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright 2013 Red Hat, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Author: Giovanni Campagna <gcampagn@redhat.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef META_CURSOR_TRACKER_PRIVATE_H
|
|
||||||
#define META_CURSOR_TRACKER_PRIVATE_H
|
|
||||||
|
|
||||||
#include <meta/meta-cursor-tracker.h>
|
|
||||||
#include <wayland-server.h>
|
|
||||||
|
|
||||||
#include "meta-cursor.h"
|
|
||||||
|
|
||||||
struct _MetaCursorTracker {
|
|
||||||
GObject parent_instance;
|
|
||||||
|
|
||||||
MetaScreen *screen;
|
|
||||||
|
|
||||||
gboolean is_showing;
|
|
||||||
gboolean has_hw_cursor;
|
|
||||||
|
|
||||||
/* The cursor tracker stores the cursor for the current grab
|
|
||||||
* operation, the cursor for the window with pointer focus, and
|
|
||||||
* the cursor for the root window, which contains either the
|
|
||||||
* default arrow cursor or the 'busy' hourglass if we're launching
|
|
||||||
* an app.
|
|
||||||
*
|
|
||||||
* We choose the first one available -- if there's a grab cursor,
|
|
||||||
* we choose that cursor, if there's window cursor, we choose that,
|
|
||||||
* otherwise we choose the root cursor.
|
|
||||||
*
|
|
||||||
* The displayed_cursor contains the chosen cursor.
|
|
||||||
*/
|
|
||||||
MetaCursorReference *displayed_cursor;
|
|
||||||
|
|
||||||
MetaCursorReference *grab_cursor;
|
|
||||||
|
|
||||||
/* Wayland clients can set a NULL buffer as their cursor
|
|
||||||
* explicitly, which means that we shouldn't display anything.
|
|
||||||
* So, we can't simply store a NULL in window_cursor to
|
|
||||||
* determine an unset window cursor; we need an extra boolean.
|
|
||||||
*/
|
|
||||||
gboolean has_window_cursor;
|
|
||||||
MetaCursorReference *window_cursor;
|
|
||||||
|
|
||||||
MetaCursorReference *root_cursor;
|
|
||||||
|
|
||||||
MetaCursorReference *theme_cursors[META_CURSOR_LAST];
|
|
||||||
|
|
||||||
int current_x, current_y;
|
|
||||||
MetaRectangle current_rect;
|
|
||||||
MetaRectangle previous_rect;
|
|
||||||
gboolean previous_is_valid;
|
|
||||||
|
|
||||||
CoglPipeline *pipeline;
|
|
||||||
int drm_fd;
|
|
||||||
struct gbm_device *gbm;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _MetaCursorTrackerClass {
|
|
||||||
GObjectClass parent_class;
|
|
||||||
};
|
|
||||||
|
|
||||||
gboolean meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
|
|
||||||
XEvent *xevent);
|
|
||||||
|
|
||||||
void meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker,
|
|
||||||
MetaCursorReference *cursor);
|
|
||||||
void meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
|
|
||||||
MetaCursorReference *cursor);
|
|
||||||
void meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker);
|
|
||||||
void meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
|
|
||||||
MetaCursorReference *cursor);
|
|
||||||
|
|
||||||
void meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
|
|
||||||
int new_x,
|
|
||||||
int new_y);
|
|
||||||
void meta_cursor_tracker_paint (MetaCursorTracker *tracker);
|
|
||||||
|
|
||||||
void meta_cursor_tracker_force_update (MetaCursorTracker *tracker);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,412 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright 2013 Red Hat, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Author: Giovanni Campagna <gcampagn@redhat.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include "meta-cursor-private.h"
|
|
||||||
|
|
||||||
#include <meta/errors.h>
|
|
||||||
|
|
||||||
#include "display-private.h"
|
|
||||||
#include "screen-private.h"
|
|
||||||
#include "meta-cursor-tracker-private.h" /* for tracker->gbm */
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <X11/cursorfont.h>
|
|
||||||
#include <X11/extensions/Xfixes.h>
|
|
||||||
#include <X11/Xcursor/Xcursor.h>
|
|
||||||
|
|
||||||
#include <cogl/cogl-wayland-server.h>
|
|
||||||
|
|
||||||
MetaCursorReference *
|
|
||||||
meta_cursor_reference_ref (MetaCursorReference *self)
|
|
||||||
{
|
|
||||||
g_assert (self->ref_count > 0);
|
|
||||||
self->ref_count++;
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_cursor_image_free (MetaCursorImage *image)
|
|
||||||
{
|
|
||||||
cogl_object_unref (image->texture);
|
|
||||||
if (image->bo)
|
|
||||||
gbm_bo_destroy (image->bo);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_cursor_reference_free (MetaCursorReference *self)
|
|
||||||
{
|
|
||||||
meta_cursor_image_free (&self->image);
|
|
||||||
g_slice_free (MetaCursorReference, self);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
meta_cursor_reference_unref (MetaCursorReference *self)
|
|
||||||
{
|
|
||||||
self->ref_count--;
|
|
||||||
|
|
||||||
if (self->ref_count == 0)
|
|
||||||
meta_cursor_reference_free (self);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
translate_meta_cursor (MetaCursor cursor,
|
|
||||||
guint *glyph_out,
|
|
||||||
const char **name_out)
|
|
||||||
{
|
|
||||||
guint glyph = XC_num_glyphs;
|
|
||||||
const char *name = NULL;
|
|
||||||
|
|
||||||
switch (cursor)
|
|
||||||
{
|
|
||||||
case META_CURSOR_DEFAULT:
|
|
||||||
glyph = XC_left_ptr;
|
|
||||||
break;
|
|
||||||
case META_CURSOR_NORTH_RESIZE:
|
|
||||||
glyph = XC_top_side;
|
|
||||||
break;
|
|
||||||
case META_CURSOR_SOUTH_RESIZE:
|
|
||||||
glyph = XC_bottom_side;
|
|
||||||
break;
|
|
||||||
case META_CURSOR_WEST_RESIZE:
|
|
||||||
glyph = XC_left_side;
|
|
||||||
break;
|
|
||||||
case META_CURSOR_EAST_RESIZE:
|
|
||||||
glyph = XC_right_side;
|
|
||||||
break;
|
|
||||||
case META_CURSOR_SE_RESIZE:
|
|
||||||
glyph = XC_bottom_right_corner;
|
|
||||||
break;
|
|
||||||
case META_CURSOR_SW_RESIZE:
|
|
||||||
glyph = XC_bottom_left_corner;
|
|
||||||
break;
|
|
||||||
case META_CURSOR_NE_RESIZE:
|
|
||||||
glyph = XC_top_right_corner;
|
|
||||||
break;
|
|
||||||
case META_CURSOR_NW_RESIZE:
|
|
||||||
glyph = XC_top_left_corner;
|
|
||||||
break;
|
|
||||||
case META_CURSOR_MOVE_OR_RESIZE_WINDOW:
|
|
||||||
glyph = XC_fleur;
|
|
||||||
break;
|
|
||||||
case META_CURSOR_BUSY:
|
|
||||||
glyph = XC_watch;
|
|
||||||
break;
|
|
||||||
case META_CURSOR_DND_IN_DRAG:
|
|
||||||
name = "dnd-none";
|
|
||||||
break;
|
|
||||||
case META_CURSOR_DND_MOVE:
|
|
||||||
name = "dnd-move";
|
|
||||||
break;
|
|
||||||
case META_CURSOR_DND_COPY:
|
|
||||||
name = "dnd-copy";
|
|
||||||
break;
|
|
||||||
case META_CURSOR_DND_UNSUPPORTED_TARGET:
|
|
||||||
name = "dnd-none";
|
|
||||||
break;
|
|
||||||
case META_CURSOR_POINTING_HAND:
|
|
||||||
glyph = XC_hand2;
|
|
||||||
break;
|
|
||||||
case META_CURSOR_CROSSHAIR:
|
|
||||||
glyph = XC_crosshair;
|
|
||||||
break;
|
|
||||||
case META_CURSOR_IBEAM:
|
|
||||||
glyph = XC_xterm;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
g_assert_not_reached ();
|
|
||||||
glyph = 0; /* silence compiler */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
*glyph_out = glyph;
|
|
||||||
*name_out = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Cursor
|
|
||||||
load_cursor_on_server (MetaDisplay *display,
|
|
||||||
MetaCursor cursor)
|
|
||||||
{
|
|
||||||
Cursor xcursor;
|
|
||||||
guint glyph;
|
|
||||||
const char *name;
|
|
||||||
|
|
||||||
translate_meta_cursor (cursor, &glyph, &name);
|
|
||||||
|
|
||||||
if (name != NULL)
|
|
||||||
xcursor = XcursorLibraryLoadCursor (display->xdisplay, name);
|
|
||||||
else
|
|
||||||
xcursor = XCreateFontCursor (display->xdisplay, glyph);
|
|
||||||
|
|
||||||
return xcursor;
|
|
||||||
}
|
|
||||||
|
|
||||||
Cursor
|
|
||||||
meta_display_create_x_cursor (MetaDisplay *display,
|
|
||||||
MetaCursor cursor)
|
|
||||||
{
|
|
||||||
return load_cursor_on_server (display, cursor);
|
|
||||||
}
|
|
||||||
|
|
||||||
static XcursorImage *
|
|
||||||
load_cursor_on_client (MetaDisplay *display,
|
|
||||||
MetaCursor cursor)
|
|
||||||
{
|
|
||||||
XcursorImage *image;
|
|
||||||
guint glyph;
|
|
||||||
const char *name;
|
|
||||||
const char *theme = XcursorGetTheme (display->xdisplay);
|
|
||||||
int size = XcursorGetDefaultSize (display->xdisplay);
|
|
||||||
|
|
||||||
translate_meta_cursor (cursor, &glyph, &name);
|
|
||||||
|
|
||||||
if (name != NULL)
|
|
||||||
image = XcursorLibraryLoadImage (name, theme, size);
|
|
||||||
else
|
|
||||||
image = XcursorShapeLoadImage (glyph, theme, size);
|
|
||||||
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_cursor_image_load_gbm_buffer (struct gbm_device *gbm,
|
|
||||||
MetaCursorImage *image,
|
|
||||||
uint8_t *pixels,
|
|
||||||
int width,
|
|
||||||
int height,
|
|
||||||
int rowstride,
|
|
||||||
uint32_t gbm_format)
|
|
||||||
{
|
|
||||||
if (width > 64 || height > 64)
|
|
||||||
{
|
|
||||||
meta_warning ("Invalid theme cursor size (must be at most 64x64)\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gbm_device_is_format_supported (gbm, gbm_format,
|
|
||||||
GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE))
|
|
||||||
{
|
|
||||||
uint8_t buf[4 * 64 * 64];
|
|
||||||
int i;
|
|
||||||
|
|
||||||
image->bo = gbm_bo_create (gbm, 64, 64,
|
|
||||||
gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
|
|
||||||
|
|
||||||
memset (buf, 0, sizeof(buf));
|
|
||||||
for (i = 0; i < height; i++)
|
|
||||||
memcpy (buf + i * 4 * 64, pixels + i * rowstride, width * 4);
|
|
||||||
|
|
||||||
gbm_bo_write (image->bo, buf, 64 * 64 * 4);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
meta_warning ("HW cursor for format %d not supported\n", gbm_format);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_cursor_image_load_from_xcursor_image (MetaCursorTracker *tracker,
|
|
||||||
MetaCursorImage *image,
|
|
||||||
XcursorImage *xc_image)
|
|
||||||
{
|
|
||||||
int width, height, rowstride;
|
|
||||||
CoglPixelFormat cogl_format;
|
|
||||||
uint32_t gbm_format;
|
|
||||||
ClutterBackend *clutter_backend;
|
|
||||||
CoglContext *cogl_context;
|
|
||||||
|
|
||||||
width = xc_image->width;
|
|
||||||
height = xc_image->height;
|
|
||||||
rowstride = width * 4;
|
|
||||||
|
|
||||||
gbm_format = GBM_FORMAT_ARGB8888;
|
|
||||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
|
||||||
cogl_format = COGL_PIXEL_FORMAT_BGRA_8888;
|
|
||||||
#else
|
|
||||||
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
image->hot_x = xc_image->xhot;
|
|
||||||
image->hot_y = xc_image->yhot;
|
|
||||||
|
|
||||||
clutter_backend = clutter_get_default_backend ();
|
|
||||||
cogl_context = clutter_backend_get_cogl_context (clutter_backend);
|
|
||||||
image->texture = cogl_texture_2d_new_from_data (cogl_context,
|
|
||||||
width, height,
|
|
||||||
cogl_format,
|
|
||||||
rowstride,
|
|
||||||
(uint8_t *) xc_image->pixels,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (tracker->gbm)
|
|
||||||
meta_cursor_image_load_gbm_buffer (tracker->gbm,
|
|
||||||
image,
|
|
||||||
(uint8_t *) xc_image->pixels,
|
|
||||||
width, height, rowstride,
|
|
||||||
gbm_format);
|
|
||||||
}
|
|
||||||
|
|
||||||
MetaCursorReference *
|
|
||||||
meta_cursor_reference_from_theme (MetaCursorTracker *tracker,
|
|
||||||
MetaCursor cursor)
|
|
||||||
{
|
|
||||||
MetaCursorReference *self;
|
|
||||||
XcursorImage *image;
|
|
||||||
|
|
||||||
if (tracker->theme_cursors[cursor])
|
|
||||||
return meta_cursor_reference_ref (tracker->theme_cursors[cursor]);
|
|
||||||
|
|
||||||
image = load_cursor_on_client (tracker->screen->display, cursor);
|
|
||||||
if (!image)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
self = g_slice_new0 (MetaCursorReference);
|
|
||||||
self->ref_count = 1;
|
|
||||||
meta_cursor_image_load_from_xcursor_image (tracker, &self->image, image);
|
|
||||||
|
|
||||||
XcursorImageDestroy (image);
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_cursor_image_load_from_buffer (MetaCursorTracker *tracker,
|
|
||||||
MetaCursorImage *image,
|
|
||||||
struct wl_resource *buffer,
|
|
||||||
int hot_x,
|
|
||||||
int hot_y)
|
|
||||||
{
|
|
||||||
ClutterBackend *backend;
|
|
||||||
CoglContext *cogl_context;
|
|
||||||
struct wl_shm_buffer *shm_buffer;
|
|
||||||
uint32_t gbm_format;
|
|
||||||
int width, height;
|
|
||||||
|
|
||||||
image->hot_x = hot_x;
|
|
||||||
image->hot_y = hot_y;
|
|
||||||
|
|
||||||
backend = clutter_get_default_backend ();
|
|
||||||
cogl_context = clutter_backend_get_cogl_context (backend);
|
|
||||||
|
|
||||||
image->texture = cogl_wayland_texture_2d_new_from_buffer (cogl_context, buffer, NULL);
|
|
||||||
|
|
||||||
width = cogl_texture_get_width (COGL_TEXTURE (image->texture));
|
|
||||||
height = cogl_texture_get_height (COGL_TEXTURE (image->texture));
|
|
||||||
|
|
||||||
shm_buffer = wl_shm_buffer_get (buffer);
|
|
||||||
if (shm_buffer)
|
|
||||||
{
|
|
||||||
if (tracker->gbm)
|
|
||||||
{
|
|
||||||
int rowstride = wl_shm_buffer_get_stride (shm_buffer);
|
|
||||||
|
|
||||||
switch (wl_shm_buffer_get_format (shm_buffer))
|
|
||||||
{
|
|
||||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
|
||||||
case WL_SHM_FORMAT_ARGB8888:
|
|
||||||
gbm_format = GBM_FORMAT_ARGB8888;
|
|
||||||
break;
|
|
||||||
case WL_SHM_FORMAT_XRGB8888:
|
|
||||||
gbm_format = GBM_FORMAT_XRGB8888;
|
|
||||||
break;
|
|
||||||
#else
|
|
||||||
case WL_SHM_FORMAT_ARGB8888:
|
|
||||||
gbm_format = GBM_FORMAT_ARGB8888;
|
|
||||||
break;
|
|
||||||
case WL_SHM_FORMAT_XRGB8888:
|
|
||||||
gbm_format = GBM_FORMAT_XRGB8888;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
g_warn_if_reached ();
|
|
||||||
gbm_format = GBM_FORMAT_ARGB8888;
|
|
||||||
}
|
|
||||||
|
|
||||||
meta_cursor_image_load_gbm_buffer (tracker->gbm,
|
|
||||||
image,
|
|
||||||
(uint8_t *) wl_shm_buffer_get_data (shm_buffer),
|
|
||||||
width, height, rowstride,
|
|
||||||
gbm_format);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* HW cursors must be 64x64, but 64x64 is huge, and no cursor theme actually uses
|
|
||||||
that, so themed cursors must be padded with transparent pixels to fill the
|
|
||||||
overlay. This is trivial if we have CPU access to the data, but it's not
|
|
||||||
possible if the buffer is in GPU memory (and possibly tiled too), so if we
|
|
||||||
don't get the right size, we fallback to GL.
|
|
||||||
*/
|
|
||||||
if (width != 64 || height != 64)
|
|
||||||
{
|
|
||||||
meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tracker->gbm)
|
|
||||||
{
|
|
||||||
image->bo = gbm_bo_import (tracker->gbm, GBM_BO_IMPORT_WL_BUFFER,
|
|
||||||
buffer, GBM_BO_USE_CURSOR_64X64);
|
|
||||||
if (!image->bo)
|
|
||||||
meta_warning ("Importing HW cursor from wl_buffer failed\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MetaCursorReference *
|
|
||||||
meta_cursor_reference_from_buffer (MetaCursorTracker *tracker,
|
|
||||||
struct wl_resource *buffer,
|
|
||||||
int hot_x,
|
|
||||||
int hot_y)
|
|
||||||
{
|
|
||||||
MetaCursorReference *self;
|
|
||||||
|
|
||||||
self = g_slice_new0 (MetaCursorReference);
|
|
||||||
self->ref_count = 1;
|
|
||||||
meta_cursor_image_load_from_buffer (tracker, &self->image, buffer, hot_x, hot_y);
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoglTexture *
|
|
||||||
meta_cursor_reference_get_cogl_texture (MetaCursorReference *cursor,
|
|
||||||
int *hot_x,
|
|
||||||
int *hot_y)
|
|
||||||
{
|
|
||||||
if (hot_x)
|
|
||||||
*hot_x = cursor->image.hot_x;
|
|
||||||
if (hot_y)
|
|
||||||
*hot_y = cursor->image.hot_y;
|
|
||||||
return COGL_TEXTURE (cursor->image.texture);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct gbm_bo *
|
|
||||||
meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
|
|
||||||
int *hot_x,
|
|
||||||
int *hot_y)
|
|
||||||
{
|
|
||||||
if (hot_x)
|
|
||||||
*hot_x = cursor->image.hot_x;
|
|
||||||
if (hot_y)
|
|
||||||
*hot_y = cursor->image.hot_y;
|
|
||||||
return cursor->image.bo;
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright 2013 Red Hat, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Author: Giovanni Campagna <gcampagn@redhat.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef META_CURSOR_H
|
|
||||||
#define META_CURSOR_H
|
|
||||||
|
|
||||||
typedef struct _MetaCursorReference MetaCursorReference;
|
|
||||||
|
|
||||||
MetaCursorReference * meta_cursor_reference_ref (MetaCursorReference *cursor);
|
|
||||||
void meta_cursor_reference_unref (MetaCursorReference *cursor);
|
|
||||||
|
|
||||||
#include <meta/meta-cursor-tracker.h>
|
|
||||||
#include <meta/common.h>
|
|
||||||
#include <wayland-server.h>
|
|
||||||
|
|
||||||
MetaCursorReference * meta_cursor_reference_from_theme (MetaCursorTracker *tracker,
|
|
||||||
MetaCursor cursor);
|
|
||||||
|
|
||||||
MetaCursorReference * meta_cursor_reference_from_buffer (MetaCursorTracker *tracker,
|
|
||||||
struct wl_resource *buffer,
|
|
||||||
int hot_x,
|
|
||||||
int hot_y);
|
|
||||||
|
|
||||||
#endif /* META_CURSOR_H */
|
|
||||||
@@ -1,286 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright 2013 Red Hat, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
|
|
||||||
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include "meta-idle-monitor-dbus.h"
|
|
||||||
#include <meta/meta-idle-monitor.h>
|
|
||||||
#include "meta-dbus-idle-monitor.h"
|
|
||||||
|
|
||||||
#include <clutter/clutter.h>
|
|
||||||
#include <meta/util.h>
|
|
||||||
#include <meta/main.h> /* for meta_get_replace_current_wm () */
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
handle_get_idletime (MetaDBusIdleMonitor *skeleton,
|
|
||||||
GDBusMethodInvocation *invocation,
|
|
||||||
MetaIdleMonitor *monitor)
|
|
||||||
{
|
|
||||||
guint64 idletime;
|
|
||||||
|
|
||||||
idletime = meta_idle_monitor_get_idletime (monitor);
|
|
||||||
meta_dbus_idle_monitor_complete_get_idletime (skeleton, invocation, idletime);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
MetaDBusIdleMonitor *dbus_monitor;
|
|
||||||
MetaIdleMonitor *monitor;
|
|
||||||
char *dbus_name;
|
|
||||||
guint watch_id;
|
|
||||||
guint name_watcher_id;
|
|
||||||
} DBusWatch;
|
|
||||||
|
|
||||||
static void
|
|
||||||
destroy_dbus_watch (gpointer data)
|
|
||||||
{
|
|
||||||
DBusWatch *watch = data;
|
|
||||||
|
|
||||||
g_object_unref (watch->dbus_monitor);
|
|
||||||
g_object_unref (watch->monitor);
|
|
||||||
g_free (watch->dbus_name);
|
|
||||||
g_bus_unwatch_name (watch->name_watcher_id);
|
|
||||||
|
|
||||||
g_slice_free (DBusWatch, watch);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
dbus_idle_callback (MetaIdleMonitor *monitor,
|
|
||||||
guint watch_id,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
DBusWatch *watch = user_data;
|
|
||||||
GDBusInterfaceSkeleton *skeleton = G_DBUS_INTERFACE_SKELETON (watch->dbus_monitor);
|
|
||||||
|
|
||||||
g_dbus_connection_emit_signal (g_dbus_interface_skeleton_get_connection (skeleton),
|
|
||||||
watch->dbus_name,
|
|
||||||
g_dbus_interface_skeleton_get_object_path (skeleton),
|
|
||||||
"org.gnome.Mutter.IdleMonitor",
|
|
||||||
"WatchFired",
|
|
||||||
g_variant_new ("(u)", watch_id),
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
name_vanished_callback (GDBusConnection *connection,
|
|
||||||
const char *name,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
DBusWatch *watch = user_data;
|
|
||||||
|
|
||||||
meta_idle_monitor_remove_watch (watch->monitor, watch->watch_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
static DBusWatch *
|
|
||||||
make_dbus_watch (MetaDBusIdleMonitor *skeleton,
|
|
||||||
GDBusMethodInvocation *invocation,
|
|
||||||
MetaIdleMonitor *monitor)
|
|
||||||
{
|
|
||||||
DBusWatch *watch;
|
|
||||||
|
|
||||||
watch = g_slice_new (DBusWatch);
|
|
||||||
watch->dbus_monitor = g_object_ref (skeleton);
|
|
||||||
watch->monitor = g_object_ref (monitor);
|
|
||||||
watch->dbus_name = g_strdup (g_dbus_method_invocation_get_sender (invocation));
|
|
||||||
watch->name_watcher_id = g_bus_watch_name_on_connection (g_dbus_method_invocation_get_connection (invocation),
|
|
||||||
watch->dbus_name,
|
|
||||||
G_BUS_NAME_WATCHER_FLAGS_NONE,
|
|
||||||
NULL, /* appeared */
|
|
||||||
name_vanished_callback,
|
|
||||||
watch, NULL);
|
|
||||||
|
|
||||||
return watch;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
handle_add_idle_watch (MetaDBusIdleMonitor *skeleton,
|
|
||||||
GDBusMethodInvocation *invocation,
|
|
||||||
guint64 interval,
|
|
||||||
MetaIdleMonitor *monitor)
|
|
||||||
{
|
|
||||||
DBusWatch *watch;
|
|
||||||
|
|
||||||
watch = make_dbus_watch (skeleton, invocation, monitor);
|
|
||||||
watch->watch_id = meta_idle_monitor_add_idle_watch (monitor, interval,
|
|
||||||
dbus_idle_callback, watch, destroy_dbus_watch);
|
|
||||||
|
|
||||||
meta_dbus_idle_monitor_complete_add_idle_watch (skeleton, invocation, watch->watch_id);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
handle_add_user_active_watch (MetaDBusIdleMonitor *skeleton,
|
|
||||||
GDBusMethodInvocation *invocation,
|
|
||||||
MetaIdleMonitor *monitor)
|
|
||||||
{
|
|
||||||
DBusWatch *watch;
|
|
||||||
|
|
||||||
watch = make_dbus_watch (skeleton, invocation, monitor);
|
|
||||||
watch->watch_id = meta_idle_monitor_add_user_active_watch (monitor,
|
|
||||||
dbus_idle_callback, watch,
|
|
||||||
destroy_dbus_watch);
|
|
||||||
|
|
||||||
meta_dbus_idle_monitor_complete_add_user_active_watch (skeleton, invocation, watch->watch_id);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
handle_remove_watch (MetaDBusIdleMonitor *skeleton,
|
|
||||||
GDBusMethodInvocation *invocation,
|
|
||||||
guint id,
|
|
||||||
MetaIdleMonitor *monitor)
|
|
||||||
{
|
|
||||||
meta_idle_monitor_remove_watch (monitor, id);
|
|
||||||
meta_dbus_idle_monitor_complete_remove_watch (skeleton, invocation);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
create_monitor_skeleton (GDBusObjectManagerServer *manager,
|
|
||||||
MetaIdleMonitor *monitor,
|
|
||||||
const char *path)
|
|
||||||
{
|
|
||||||
MetaDBusIdleMonitor *skeleton;
|
|
||||||
MetaDBusObjectSkeleton *object;
|
|
||||||
|
|
||||||
skeleton = meta_dbus_idle_monitor_skeleton_new ();
|
|
||||||
g_signal_connect_object (skeleton, "handle-add-idle-watch",
|
|
||||||
G_CALLBACK (handle_add_idle_watch), monitor, 0);
|
|
||||||
g_signal_connect_object (skeleton, "handle-add-user-active-watch",
|
|
||||||
G_CALLBACK (handle_add_user_active_watch), monitor, 0);
|
|
||||||
g_signal_connect_object (skeleton, "handle-remove-watch",
|
|
||||||
G_CALLBACK (handle_remove_watch), monitor, 0);
|
|
||||||
g_signal_connect_object (skeleton, "handle-get-idletime",
|
|
||||||
G_CALLBACK (handle_get_idletime), monitor, 0);
|
|
||||||
|
|
||||||
object = meta_dbus_object_skeleton_new (path);
|
|
||||||
meta_dbus_object_skeleton_set_idle_monitor (object, skeleton);
|
|
||||||
|
|
||||||
g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (object));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
on_device_added (ClutterDeviceManager *device_manager,
|
|
||||||
ClutterInputDevice *device,
|
|
||||||
GDBusObjectManagerServer *manager)
|
|
||||||
{
|
|
||||||
|
|
||||||
MetaIdleMonitor *monitor;
|
|
||||||
int device_id;
|
|
||||||
char *path;
|
|
||||||
|
|
||||||
device_id = clutter_input_device_get_device_id (device);
|
|
||||||
monitor = meta_idle_monitor_get_for_device (device_id);
|
|
||||||
path = g_strdup_printf ("/org/gnome/Mutter/IdleMonitor/Device%d", device_id);
|
|
||||||
|
|
||||||
create_monitor_skeleton (manager, monitor, path);
|
|
||||||
g_free (path);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
on_device_removed (ClutterDeviceManager *device_manager,
|
|
||||||
ClutterInputDevice *device,
|
|
||||||
GDBusObjectManagerServer *manager)
|
|
||||||
{
|
|
||||||
int device_id;
|
|
||||||
char *path;
|
|
||||||
|
|
||||||
device_id = clutter_input_device_get_device_id (device);
|
|
||||||
path = g_strdup_printf ("/org/gnome/Mutter/IdleMonitor/Device%d", device_id);
|
|
||||||
g_dbus_object_manager_server_unexport (manager, path);
|
|
||||||
g_free (path);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
on_bus_acquired (GDBusConnection *connection,
|
|
||||||
const char *name,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
GDBusObjectManagerServer *manager;
|
|
||||||
ClutterDeviceManager *device_manager;
|
|
||||||
MetaIdleMonitor *monitor;
|
|
||||||
GSList *devices, *iter;
|
|
||||||
char *path;
|
|
||||||
|
|
||||||
manager = g_dbus_object_manager_server_new ("/org/gnome/Mutter/IdleMonitor");
|
|
||||||
|
|
||||||
/* We never clear the core monitor, as that's supposed to cumulate idle times from
|
|
||||||
all devices */
|
|
||||||
monitor = meta_idle_monitor_get_core ();
|
|
||||||
path = g_strdup ("/org/gnome/Mutter/IdleMonitor/Core");
|
|
||||||
create_monitor_skeleton (manager, monitor, path);
|
|
||||||
g_free (path);
|
|
||||||
|
|
||||||
device_manager = clutter_device_manager_get_default ();
|
|
||||||
devices = clutter_device_manager_list_devices (device_manager);
|
|
||||||
|
|
||||||
for (iter = devices; iter; iter = iter->next)
|
|
||||||
on_device_added (device_manager, iter->data, manager);
|
|
||||||
|
|
||||||
g_slist_free (devices);
|
|
||||||
|
|
||||||
g_signal_connect_object (device_manager, "device-added",
|
|
||||||
G_CALLBACK (on_device_added), manager, 0);
|
|
||||||
g_signal_connect_object (device_manager, "device-removed",
|
|
||||||
G_CALLBACK (on_device_removed), manager, 0);
|
|
||||||
|
|
||||||
g_dbus_object_manager_server_set_connection (manager, connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
on_name_acquired (GDBusConnection *connection,
|
|
||||||
const char *name,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
meta_verbose ("Acquired name %s\n", name);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
on_name_lost (GDBusConnection *connection,
|
|
||||||
const char *name,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
meta_verbose ("Lost or failed to acquire name %s\n", name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
meta_idle_monitor_init_dbus (void)
|
|
||||||
{
|
|
||||||
static int dbus_name_id;
|
|
||||||
|
|
||||||
if (dbus_name_id > 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dbus_name_id = g_bus_own_name (G_BUS_TYPE_SESSION,
|
|
||||||
"org.gnome.Mutter.IdleMonitor",
|
|
||||||
G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
|
|
||||||
(meta_get_replace_current_wm () ?
|
|
||||||
G_BUS_NAME_OWNER_FLAGS_REPLACE : 0),
|
|
||||||
on_bus_acquired,
|
|
||||||
on_name_acquired,
|
|
||||||
on_name_lost,
|
|
||||||
NULL, NULL);
|
|
||||||
}
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright 2013 Red Hat, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
|
|
||||||
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef META_IDLE_MONITOR_PRIVATE_H
|
|
||||||
#define META_IDLE_MONITOR_PRIVATE_H
|
|
||||||
|
|
||||||
#include <meta/meta-idle-monitor.h>
|
|
||||||
#include "display-private.h"
|
|
||||||
|
|
||||||
#include <X11/Xlib.h>
|
|
||||||
#include <X11/extensions/sync.h>
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
MetaIdleMonitor *monitor;
|
|
||||||
guint id;
|
|
||||||
MetaIdleMonitorWatchFunc callback;
|
|
||||||
gpointer user_data;
|
|
||||||
GDestroyNotify notify;
|
|
||||||
guint64 timeout_msec;
|
|
||||||
int idle_source_id;
|
|
||||||
} MetaIdleMonitorWatch;
|
|
||||||
|
|
||||||
struct _MetaIdleMonitor
|
|
||||||
{
|
|
||||||
GObject parent_instance;
|
|
||||||
|
|
||||||
GHashTable *watches;
|
|
||||||
int device_id;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _MetaIdleMonitorClass
|
|
||||||
{
|
|
||||||
GObjectClass parent_class;
|
|
||||||
|
|
||||||
gint64 (*get_idletime) (MetaIdleMonitor *monitor);
|
|
||||||
MetaIdleMonitorWatch * (*make_watch) (MetaIdleMonitor *monitor,
|
|
||||||
guint64 timeout_msec,
|
|
||||||
MetaIdleMonitorWatchFunc callback,
|
|
||||||
gpointer user_data,
|
|
||||||
GDestroyNotify notify);
|
|
||||||
};
|
|
||||||
|
|
||||||
void _meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch);
|
|
||||||
|
|
||||||
#endif /* META_IDLE_MONITOR_PRIVATE_H */
|
|
||||||
@@ -1,367 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright 2013 Red Hat, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
|
|
||||||
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SECTION:idle-monitor
|
|
||||||
* @title: MetaIdleMonitor
|
|
||||||
* @short_description: Mutter idle counter (similar to X's IDLETIME)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <clutter/clutter.h>
|
|
||||||
#include <X11/Xlib.h>
|
|
||||||
#include <X11/extensions/sync.h>
|
|
||||||
|
|
||||||
#include <meta/util.h>
|
|
||||||
#include <meta/main.h>
|
|
||||||
#include <meta/meta-idle-monitor.h>
|
|
||||||
#include "meta-idle-monitor-private.h"
|
|
||||||
#include "meta-idle-monitor-dbus.h"
|
|
||||||
#include "backends/x11/meta-idle-monitor-xsync.h"
|
|
||||||
#include "backends/native/meta-idle-monitor-native.h"
|
|
||||||
|
|
||||||
G_STATIC_ASSERT(sizeof(unsigned long) == sizeof(gpointer));
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
PROP_0,
|
|
||||||
PROP_DEVICE_ID,
|
|
||||||
PROP_LAST,
|
|
||||||
};
|
|
||||||
|
|
||||||
static GParamSpec *obj_props[PROP_LAST];
|
|
||||||
|
|
||||||
G_DEFINE_TYPE (MetaIdleMonitor, meta_idle_monitor, G_TYPE_OBJECT)
|
|
||||||
|
|
||||||
static MetaIdleMonitor *device_monitors[256];
|
|
||||||
static int device_id_max;
|
|
||||||
|
|
||||||
void
|
|
||||||
_meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch)
|
|
||||||
{
|
|
||||||
MetaIdleMonitor *monitor;
|
|
||||||
guint id;
|
|
||||||
gboolean is_user_active_watch;
|
|
||||||
|
|
||||||
monitor = watch->monitor;
|
|
||||||
g_object_ref (monitor);
|
|
||||||
|
|
||||||
if (watch->idle_source_id)
|
|
||||||
{
|
|
||||||
g_source_remove (watch->idle_source_id);
|
|
||||||
watch->idle_source_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
id = watch->id;
|
|
||||||
is_user_active_watch = (watch->timeout_msec == 0);
|
|
||||||
|
|
||||||
if (watch->callback)
|
|
||||||
watch->callback (monitor, id, watch->user_data);
|
|
||||||
|
|
||||||
if (is_user_active_watch)
|
|
||||||
meta_idle_monitor_remove_watch (monitor, id);
|
|
||||||
|
|
||||||
g_object_unref (monitor);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_idle_monitor_dispose (GObject *object)
|
|
||||||
{
|
|
||||||
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
|
|
||||||
|
|
||||||
g_clear_pointer (&monitor->watches, g_hash_table_destroy);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (meta_idle_monitor_parent_class)->dispose (object);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_idle_monitor_get_property (GObject *object,
|
|
||||||
guint prop_id,
|
|
||||||
GValue *value,
|
|
||||||
GParamSpec *pspec)
|
|
||||||
{
|
|
||||||
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
|
|
||||||
|
|
||||||
switch (prop_id)
|
|
||||||
{
|
|
||||||
case PROP_DEVICE_ID:
|
|
||||||
g_value_set_int (value, monitor->device_id);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_idle_monitor_set_property (GObject *object,
|
|
||||||
guint prop_id,
|
|
||||||
const GValue *value,
|
|
||||||
GParamSpec *pspec)
|
|
||||||
{
|
|
||||||
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
|
|
||||||
switch (prop_id)
|
|
||||||
{
|
|
||||||
case PROP_DEVICE_ID:
|
|
||||||
monitor->device_id = g_value_get_int (value);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_idle_monitor_class_init (MetaIdleMonitorClass *klass)
|
|
||||||
{
|
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
||||||
|
|
||||||
object_class->dispose = meta_idle_monitor_dispose;
|
|
||||||
object_class->get_property = meta_idle_monitor_get_property;
|
|
||||||
object_class->set_property = meta_idle_monitor_set_property;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MetaIdleMonitor:device_id:
|
|
||||||
*
|
|
||||||
* The device to listen to idletime on.
|
|
||||||
*/
|
|
||||||
obj_props[PROP_DEVICE_ID] =
|
|
||||||
g_param_spec_int ("device-id",
|
|
||||||
"Device ID",
|
|
||||||
"The device to listen to idletime on",
|
|
||||||
0, 255, 0,
|
|
||||||
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
|
||||||
g_object_class_install_property (object_class, PROP_DEVICE_ID, obj_props[PROP_DEVICE_ID]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_idle_monitor_init (MetaIdleMonitor *monitor)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static GType
|
|
||||||
get_idle_monitor_type (void)
|
|
||||||
{
|
|
||||||
if (meta_is_wayland_compositor ())
|
|
||||||
return META_TYPE_IDLE_MONITOR_NATIVE;
|
|
||||||
else
|
|
||||||
return META_TYPE_IDLE_MONITOR_XSYNC;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
ensure_device_monitor (int device_id)
|
|
||||||
{
|
|
||||||
if (device_monitors[device_id])
|
|
||||||
return;
|
|
||||||
|
|
||||||
device_monitors[device_id] = g_object_new (get_idle_monitor_type (),
|
|
||||||
"device-id", device_id,
|
|
||||||
NULL);
|
|
||||||
device_id_max = MAX (device_id_max, device_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME -- destroy device monitors at some point */
|
|
||||||
G_GNUC_UNUSED static void
|
|
||||||
destroy_device_monitor (int device_id)
|
|
||||||
{
|
|
||||||
g_clear_object (&device_monitors[device_id]);
|
|
||||||
if (device_id == device_id_max)
|
|
||||||
device_id_max--;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* meta_idle_monitor_get_core:
|
|
||||||
*
|
|
||||||
* Returns: (transfer none): the #MetaIdleMonitor that tracks the server-global
|
|
||||||
* idletime for all devices. To track device-specific idletime,
|
|
||||||
* use meta_idle_monitor_get_for_device().
|
|
||||||
*/
|
|
||||||
MetaIdleMonitor *
|
|
||||||
meta_idle_monitor_get_core (void)
|
|
||||||
{
|
|
||||||
ensure_device_monitor (0);
|
|
||||||
return device_monitors[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* meta_idle_monitor_get_for_device:
|
|
||||||
* @device_id: the device to get the idle time for.
|
|
||||||
*
|
|
||||||
* Returns: (transfer none): a new #MetaIdleMonitor that tracks the
|
|
||||||
* device-specific idletime for @device. To track server-global idletime
|
|
||||||
* for all devices, use meta_idle_monitor_get_core().
|
|
||||||
*/
|
|
||||||
MetaIdleMonitor *
|
|
||||||
meta_idle_monitor_get_for_device (int device_id)
|
|
||||||
{
|
|
||||||
g_return_val_if_fail (device_id > 0 && device_id < 256, NULL);
|
|
||||||
|
|
||||||
ensure_device_monitor (device_id);
|
|
||||||
return device_monitors[device_id];
|
|
||||||
}
|
|
||||||
|
|
||||||
static MetaIdleMonitorWatch *
|
|
||||||
make_watch (MetaIdleMonitor *monitor,
|
|
||||||
guint64 timeout_msec,
|
|
||||||
MetaIdleMonitorWatchFunc callback,
|
|
||||||
gpointer user_data,
|
|
||||||
GDestroyNotify notify)
|
|
||||||
{
|
|
||||||
MetaIdleMonitorWatch *watch;
|
|
||||||
|
|
||||||
watch = META_IDLE_MONITOR_GET_CLASS (monitor)->make_watch (monitor,
|
|
||||||
timeout_msec,
|
|
||||||
callback,
|
|
||||||
user_data,
|
|
||||||
notify);
|
|
||||||
|
|
||||||
g_hash_table_insert (monitor->watches,
|
|
||||||
GUINT_TO_POINTER (watch->id),
|
|
||||||
watch);
|
|
||||||
return watch;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* meta_idle_monitor_add_idle_watch:
|
|
||||||
* @monitor: A #MetaIdleMonitor
|
|
||||||
* @interval_msec: The idletime interval, in milliseconds
|
|
||||||
* @callback: (allow-none): The callback to call when the user has
|
|
||||||
* accumulated @interval_msec milliseconds of idle time.
|
|
||||||
* @user_data: (allow-none): The user data to pass to the callback
|
|
||||||
* @notify: A #GDestroyNotify
|
|
||||||
*
|
|
||||||
* Returns: a watch id
|
|
||||||
*
|
|
||||||
* Adds a watch for a specific idle time. The callback will be called
|
|
||||||
* when the user has accumulated @interval_msec milliseconds of idle time.
|
|
||||||
* This function will return an ID that can either be passed to
|
|
||||||
* meta_idle_monitor_remove_watch(), or can be used to tell idle time
|
|
||||||
* watches apart if you have more than one.
|
|
||||||
*
|
|
||||||
* Also note that this function will only care about positive transitions
|
|
||||||
* (user's idle time exceeding a certain time). If you want to know about
|
|
||||||
* when the user has become active, use
|
|
||||||
* meta_idle_monitor_add_user_active_watch().
|
|
||||||
*/
|
|
||||||
guint
|
|
||||||
meta_idle_monitor_add_idle_watch (MetaIdleMonitor *monitor,
|
|
||||||
guint64 interval_msec,
|
|
||||||
MetaIdleMonitorWatchFunc callback,
|
|
||||||
gpointer user_data,
|
|
||||||
GDestroyNotify notify)
|
|
||||||
{
|
|
||||||
MetaIdleMonitorWatch *watch;
|
|
||||||
|
|
||||||
g_return_val_if_fail (META_IS_IDLE_MONITOR (monitor), 0);
|
|
||||||
g_return_val_if_fail (interval_msec > 0, 0);
|
|
||||||
|
|
||||||
watch = make_watch (monitor,
|
|
||||||
interval_msec,
|
|
||||||
callback,
|
|
||||||
user_data,
|
|
||||||
notify);
|
|
||||||
|
|
||||||
return watch->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* meta_idle_monitor_add_user_active_watch:
|
|
||||||
* @monitor: A #MetaIdleMonitor
|
|
||||||
* @callback: (allow-none): The callback to call when the user is
|
|
||||||
* active again.
|
|
||||||
* @user_data: (allow-none): The user data to pass to the callback
|
|
||||||
* @notify: A #GDestroyNotify
|
|
||||||
*
|
|
||||||
* Returns: a watch id
|
|
||||||
*
|
|
||||||
* Add a one-time watch to know when the user is active again.
|
|
||||||
* Note that this watch is one-time and will de-activate after the
|
|
||||||
* function is called, for efficiency purposes. It's most convenient
|
|
||||||
* to call this when an idle watch, as added by
|
|
||||||
* meta_idle_monitor_add_idle_watch(), has triggered.
|
|
||||||
*/
|
|
||||||
guint
|
|
||||||
meta_idle_monitor_add_user_active_watch (MetaIdleMonitor *monitor,
|
|
||||||
MetaIdleMonitorWatchFunc callback,
|
|
||||||
gpointer user_data,
|
|
||||||
GDestroyNotify notify)
|
|
||||||
{
|
|
||||||
MetaIdleMonitorWatch *watch;
|
|
||||||
|
|
||||||
g_return_val_if_fail (META_IS_IDLE_MONITOR (monitor), 0);
|
|
||||||
|
|
||||||
watch = make_watch (monitor,
|
|
||||||
0,
|
|
||||||
callback,
|
|
||||||
user_data,
|
|
||||||
notify);
|
|
||||||
|
|
||||||
return watch->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* meta_idle_monitor_remove_watch:
|
|
||||||
* @monitor: A #MetaIdleMonitor
|
|
||||||
* @id: A watch ID
|
|
||||||
*
|
|
||||||
* Removes an idle time watcher, previously added by
|
|
||||||
* meta_idle_monitor_add_idle_watch() or
|
|
||||||
* meta_idle_monitor_add_user_active_watch().
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
meta_idle_monitor_remove_watch (MetaIdleMonitor *monitor,
|
|
||||||
guint id)
|
|
||||||
{
|
|
||||||
g_return_if_fail (META_IS_IDLE_MONITOR (monitor));
|
|
||||||
|
|
||||||
g_object_ref (monitor);
|
|
||||||
g_hash_table_remove (monitor->watches,
|
|
||||||
GUINT_TO_POINTER (id));
|
|
||||||
g_object_unref (monitor);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* meta_idle_monitor_get_idletime:
|
|
||||||
* @monitor: A #MetaIdleMonitor
|
|
||||||
*
|
|
||||||
* Returns: The current idle time, in milliseconds, or -1 for not supported
|
|
||||||
*/
|
|
||||||
gint64
|
|
||||||
meta_idle_monitor_get_idletime (MetaIdleMonitor *monitor)
|
|
||||||
{
|
|
||||||
return META_IDLE_MONITOR_GET_CLASS (monitor)->get_idletime (monitor);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
meta_idle_monitor_xsync_handle_xevent_all (XEvent *xevent)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (meta_is_wayland_compositor ())
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (i = 0; i <= device_id_max; i++)
|
|
||||||
if (device_monitors[i])
|
|
||||||
meta_idle_monitor_xsync_handle_xevent (device_monitors[i], (XSyncAlarmNotifyEvent*)xevent);
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2001 Havoc Pennington
|
|
||||||
* Copyright (C) 2003 Rob Adams
|
|
||||||
* Copyright (C) 2004-2006 Elijah Newren
|
|
||||||
* Copyright (C) 2013 Red Hat Inc.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef META_MONITOR_CONFIG_H
|
|
||||||
#define META_MONITOR_CONFIG_H
|
|
||||||
|
|
||||||
#include "meta-monitor-manager.h"
|
|
||||||
|
|
||||||
#define META_TYPE_MONITOR_CONFIG (meta_monitor_config_get_type ())
|
|
||||||
#define META_MONITOR_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_CONFIG, MetaMonitorConfig))
|
|
||||||
#define META_MONITOR_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_CONFIG, MetaMonitorConfigClass))
|
|
||||||
#define META_IS_MONITOR_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_CONFIG))
|
|
||||||
#define META_IS_MONITOR_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MONITOR_CONFIG))
|
|
||||||
#define META_MONITOR_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MONITOR_CONFIG, MetaMonitorConfigClass))
|
|
||||||
|
|
||||||
GType meta_monitor_config_get_type (void) G_GNUC_CONST;
|
|
||||||
|
|
||||||
MetaMonitorConfig *meta_monitor_config_new (void);
|
|
||||||
|
|
||||||
gboolean meta_monitor_config_match_current (MetaMonitorConfig *config,
|
|
||||||
MetaMonitorManager *manager);
|
|
||||||
|
|
||||||
gboolean meta_monitor_config_apply_stored (MetaMonitorConfig *config,
|
|
||||||
MetaMonitorManager *manager);
|
|
||||||
|
|
||||||
void meta_monitor_config_make_default (MetaMonitorConfig *config,
|
|
||||||
MetaMonitorManager *manager);
|
|
||||||
|
|
||||||
void meta_monitor_config_update_current (MetaMonitorConfig *config,
|
|
||||||
MetaMonitorManager *manager);
|
|
||||||
void meta_monitor_config_make_persistent (MetaMonitorConfig *config);
|
|
||||||
|
|
||||||
void meta_monitor_config_restore_previous (MetaMonitorConfig *config,
|
|
||||||
MetaMonitorManager *manager);
|
|
||||||
|
|
||||||
#endif /* META_MONITOR_CONFIG_H */
|
|
||||||
@@ -1,227 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2001, 2002 Havoc Pennington
|
|
||||||
* Copyright (C) 2002, 2003 Red Hat Inc.
|
|
||||||
* Some ICCCM manager selection code derived from fvwm2,
|
|
||||||
* Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team
|
|
||||||
* Copyright (C) 2003 Rob Adams
|
|
||||||
* Copyright (C) 2004-2006 Elijah Newren
|
|
||||||
* Copyright (C) 2013 Red Hat Inc.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include "meta-monitor-manager-dummy.h"
|
|
||||||
|
|
||||||
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
|
|
||||||
|
|
||||||
struct _MetaMonitorManagerDummy
|
|
||||||
{
|
|
||||||
MetaMonitorManager parent_instance;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _MetaMonitorManagerDummyClass
|
|
||||||
{
|
|
||||||
MetaMonitorManagerClass parent_class;
|
|
||||||
};
|
|
||||||
|
|
||||||
G_DEFINE_TYPE (MetaMonitorManagerDummy, meta_monitor_manager_dummy, META_TYPE_MONITOR_MANAGER);
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
|
|
||||||
{
|
|
||||||
manager->max_screen_width = 65535;
|
|
||||||
manager->max_screen_height = 65535;
|
|
||||||
manager->screen_width = 1024;
|
|
||||||
manager->screen_height = 768;
|
|
||||||
|
|
||||||
manager->modes = g_new0 (MetaMonitorMode, 1);
|
|
||||||
manager->n_modes = 1;
|
|
||||||
|
|
||||||
manager->modes[0].mode_id = 0;
|
|
||||||
manager->modes[0].width = 1024;
|
|
||||||
manager->modes[0].height = 768;
|
|
||||||
manager->modes[0].refresh_rate = 60.0;
|
|
||||||
|
|
||||||
manager->crtcs = g_new0 (MetaCRTC, 1);
|
|
||||||
manager->n_crtcs = 1;
|
|
||||||
|
|
||||||
manager->crtcs[0].crtc_id = 1;
|
|
||||||
manager->crtcs[0].rect.x = 0;
|
|
||||||
manager->crtcs[0].rect.y = 0;
|
|
||||||
manager->crtcs[0].rect.width = manager->modes[0].width;
|
|
||||||
manager->crtcs[0].rect.height = manager->modes[0].height;
|
|
||||||
manager->crtcs[0].current_mode = &manager->modes[0];
|
|
||||||
manager->crtcs[0].transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
|
||||||
manager->crtcs[0].all_transforms = ALL_WL_TRANSFORMS;
|
|
||||||
manager->crtcs[0].is_dirty = FALSE;
|
|
||||||
manager->crtcs[0].logical_monitor = NULL;
|
|
||||||
|
|
||||||
manager->outputs = g_new0 (MetaOutput, 1);
|
|
||||||
manager->n_outputs = 1;
|
|
||||||
|
|
||||||
manager->outputs[0].crtc = &manager->crtcs[0];
|
|
||||||
manager->outputs[0].output_id = 1;
|
|
||||||
manager->outputs[0].name = g_strdup ("LVDS");
|
|
||||||
manager->outputs[0].vendor = g_strdup ("MetaProducts Inc.");
|
|
||||||
manager->outputs[0].product = g_strdup ("unknown");
|
|
||||||
manager->outputs[0].serial = g_strdup ("0xC0FFEE");
|
|
||||||
manager->outputs[0].width_mm = 222;
|
|
||||||
manager->outputs[0].height_mm = 125;
|
|
||||||
manager->outputs[0].subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
|
|
||||||
manager->outputs[0].preferred_mode = &manager->modes[0];
|
|
||||||
manager->outputs[0].n_modes = 1;
|
|
||||||
manager->outputs[0].modes = g_new0 (MetaMonitorMode *, 1);
|
|
||||||
manager->outputs[0].modes[0] = &manager->modes[0];
|
|
||||||
manager->outputs[0].n_possible_crtcs = 1;
|
|
||||||
manager->outputs[0].possible_crtcs = g_new0 (MetaCRTC *, 1);
|
|
||||||
manager->outputs[0].possible_crtcs[0] = &manager->crtcs[0];
|
|
||||||
manager->outputs[0].n_possible_clones = 0;
|
|
||||||
manager->outputs[0].possible_clones = g_new0 (MetaOutput *, 0);
|
|
||||||
manager->outputs[0].backlight = -1;
|
|
||||||
manager->outputs[0].backlight_min = 0;
|
|
||||||
manager->outputs[0].backlight_max = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_monitor_manager_dummy_apply_config (MetaMonitorManager *manager,
|
|
||||||
MetaCRTCInfo **crtcs,
|
|
||||||
unsigned int n_crtcs,
|
|
||||||
MetaOutputInfo **outputs,
|
|
||||||
unsigned int n_outputs)
|
|
||||||
{
|
|
||||||
unsigned i;
|
|
||||||
int screen_width = 0, screen_height = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < n_crtcs; i++)
|
|
||||||
{
|
|
||||||
MetaCRTCInfo *crtc_info = crtcs[i];
|
|
||||||
MetaCRTC *crtc = crtc_info->crtc;
|
|
||||||
crtc->is_dirty = TRUE;
|
|
||||||
|
|
||||||
if (crtc_info->mode == NULL)
|
|
||||||
{
|
|
||||||
crtc->rect.x = 0;
|
|
||||||
crtc->rect.y = 0;
|
|
||||||
crtc->rect.width = 0;
|
|
||||||
crtc->rect.height = 0;
|
|
||||||
crtc->current_mode = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MetaMonitorMode *mode;
|
|
||||||
MetaOutput *output;
|
|
||||||
int i, n_outputs;
|
|
||||||
int width, height;
|
|
||||||
|
|
||||||
mode = crtc_info->mode;
|
|
||||||
|
|
||||||
if (meta_monitor_transform_is_rotated (crtc_info->transform))
|
|
||||||
{
|
|
||||||
width = mode->height;
|
|
||||||
height = mode->width;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
width = mode->width;
|
|
||||||
height = mode->height;
|
|
||||||
}
|
|
||||||
|
|
||||||
crtc->rect.x = crtc_info->x;
|
|
||||||
crtc->rect.y = crtc_info->y;
|
|
||||||
crtc->rect.width = width;
|
|
||||||
crtc->rect.height = height;
|
|
||||||
crtc->current_mode = mode;
|
|
||||||
crtc->transform = crtc_info->transform;
|
|
||||||
|
|
||||||
screen_width = MAX (screen_width, crtc_info->x + width);
|
|
||||||
screen_height = MAX (screen_height, crtc_info->y + height);
|
|
||||||
|
|
||||||
n_outputs = crtc_info->outputs->len;
|
|
||||||
for (i = 0; i < n_outputs; i++)
|
|
||||||
{
|
|
||||||
output = ((MetaOutput**)crtc_info->outputs->pdata)[i];
|
|
||||||
|
|
||||||
output->is_dirty = TRUE;
|
|
||||||
output->crtc = crtc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < n_outputs; i++)
|
|
||||||
{
|
|
||||||
MetaOutputInfo *output_info = outputs[i];
|
|
||||||
MetaOutput *output = output_info->output;
|
|
||||||
|
|
||||||
output->is_primary = output_info->is_primary;
|
|
||||||
output->is_presentation = output_info->is_presentation;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Disable CRTCs not mentioned in the list */
|
|
||||||
for (i = 0; i < manager->n_crtcs; i++)
|
|
||||||
{
|
|
||||||
MetaCRTC *crtc = &manager->crtcs[i];
|
|
||||||
|
|
||||||
crtc->logical_monitor = NULL;
|
|
||||||
|
|
||||||
if (crtc->is_dirty)
|
|
||||||
{
|
|
||||||
crtc->is_dirty = FALSE;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
crtc->rect.x = 0;
|
|
||||||
crtc->rect.y = 0;
|
|
||||||
crtc->rect.width = 0;
|
|
||||||
crtc->rect.height = 0;
|
|
||||||
crtc->current_mode = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Disable outputs not mentioned in the list */
|
|
||||||
for (i = 0; i < manager->n_outputs; i++)
|
|
||||||
{
|
|
||||||
MetaOutput *output = &manager->outputs[i];
|
|
||||||
|
|
||||||
if (output->is_dirty)
|
|
||||||
{
|
|
||||||
output->is_dirty = FALSE;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
output->crtc = NULL;
|
|
||||||
output->is_primary = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
manager->screen_width = screen_width;
|
|
||||||
manager->screen_height = screen_height;
|
|
||||||
|
|
||||||
meta_monitor_manager_rebuild_derived (manager);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_monitor_manager_dummy_class_init (MetaMonitorManagerDummyClass *klass)
|
|
||||||
{
|
|
||||||
MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass);
|
|
||||||
|
|
||||||
manager_class->read_current = meta_monitor_manager_dummy_read_current;
|
|
||||||
manager_class->apply_configuration = meta_monitor_manager_dummy_apply_config;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_monitor_manager_dummy_init (MetaMonitorManagerDummy *manager)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2001 Havoc Pennington
|
|
||||||
* Copyright (C) 2003 Rob Adams
|
|
||||||
* Copyright (C) 2004-2006 Elijah Newren
|
|
||||||
* Copyright (C) 2013 Red Hat Inc.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef META_MONITOR_MANAGER_DUMMY_H
|
|
||||||
#define META_MONITOR_MANAGER_DUMMY_H
|
|
||||||
|
|
||||||
#include "meta-monitor-manager.h"
|
|
||||||
|
|
||||||
#define META_TYPE_MONITOR_MANAGER_DUMMY (meta_monitor_manager_dummy_get_type ())
|
|
||||||
#define META_MONITOR_MANAGER_DUMMY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_DUMMY, MetaMonitorManagerDummy))
|
|
||||||
#define META_MONITOR_MANAGER_DUMMY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_MANAGER_DUMMY, MetaMonitorManagerDummyClass))
|
|
||||||
#define META_IS_MONITOR_MANAGER_DUMMY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_MANAGER_DUMMY))
|
|
||||||
#define META_IS_MONITOR_MANAGER_DUMMY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MONITOR_MANAGER_DUMMY))
|
|
||||||
#define META_MONITOR_MANAGER_DUMMY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MONITOR_MANAGER_DUMMY, MetaMonitorManagerDummyClass))
|
|
||||||
|
|
||||||
typedef struct _MetaMonitorManagerDummyClass MetaMonitorManagerDummyClass;
|
|
||||||
typedef struct _MetaMonitorManagerDummy MetaMonitorManagerDummy;
|
|
||||||
|
|
||||||
GType meta_monitor_manager_dummy_get_type (void);
|
|
||||||
|
|
||||||
#endif /* META_MONITOR_MANAGER_DUMMY_H */
|
|
||||||
@@ -1,219 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright 2013 Red Hat, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
|
|
||||||
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include "meta-idle-monitor-native.h"
|
|
||||||
#include "meta-idle-monitor-private.h"
|
|
||||||
|
|
||||||
#include <meta/util.h>
|
|
||||||
#include "display-private.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
struct _MetaIdleMonitorNative
|
|
||||||
{
|
|
||||||
MetaIdleMonitor parent;
|
|
||||||
|
|
||||||
guint64 last_event_time;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _MetaIdleMonitorNativeClass
|
|
||||||
{
|
|
||||||
MetaIdleMonitorClass parent_class;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
MetaIdleMonitorWatch base;
|
|
||||||
|
|
||||||
GSource *timeout_source;
|
|
||||||
} MetaIdleMonitorWatchNative;
|
|
||||||
|
|
||||||
G_DEFINE_TYPE (MetaIdleMonitorNative, meta_idle_monitor_native, META_TYPE_IDLE_MONITOR)
|
|
||||||
|
|
||||||
static gint64
|
|
||||||
meta_idle_monitor_native_get_idletime (MetaIdleMonitor *monitor)
|
|
||||||
{
|
|
||||||
MetaIdleMonitorNative *monitor_native = META_IDLE_MONITOR_NATIVE (monitor);
|
|
||||||
|
|
||||||
return (g_get_monotonic_time () - monitor_native->last_event_time) / 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
static guint32
|
|
||||||
get_next_watch_serial (void)
|
|
||||||
{
|
|
||||||
static guint32 serial = 0;
|
|
||||||
g_atomic_int_inc (&serial);
|
|
||||||
return serial;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
native_dispatch_timeout (GSource *source,
|
|
||||||
GSourceFunc callback,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
MetaIdleMonitorWatchNative *watch_native = user_data;
|
|
||||||
MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_native;
|
|
||||||
|
|
||||||
_meta_idle_monitor_watch_fire (watch);
|
|
||||||
g_source_set_ready_time (watch_native->timeout_source, -1);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GSourceFuncs native_source_funcs = {
|
|
||||||
NULL, /* prepare */
|
|
||||||
NULL, /* check */
|
|
||||||
native_dispatch_timeout,
|
|
||||||
NULL, /* finalize */
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
free_watch (gpointer data)
|
|
||||||
{
|
|
||||||
MetaIdleMonitorWatchNative *watch_native = data;
|
|
||||||
MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_native;
|
|
||||||
MetaIdleMonitor *monitor = watch->monitor;
|
|
||||||
|
|
||||||
g_object_ref (monitor);
|
|
||||||
|
|
||||||
if (watch->idle_source_id)
|
|
||||||
{
|
|
||||||
g_source_remove (watch->idle_source_id);
|
|
||||||
watch->idle_source_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (watch->notify != NULL)
|
|
||||||
watch->notify (watch->user_data);
|
|
||||||
|
|
||||||
if (watch_native->timeout_source != NULL)
|
|
||||||
g_source_destroy (watch_native->timeout_source);
|
|
||||||
|
|
||||||
g_object_unref (monitor);
|
|
||||||
g_slice_free (MetaIdleMonitorWatchNative, watch_native);
|
|
||||||
}
|
|
||||||
|
|
||||||
static MetaIdleMonitorWatch *
|
|
||||||
meta_idle_monitor_native_make_watch (MetaIdleMonitor *monitor,
|
|
||||||
guint64 timeout_msec,
|
|
||||||
MetaIdleMonitorWatchFunc callback,
|
|
||||||
gpointer user_data,
|
|
||||||
GDestroyNotify notify)
|
|
||||||
{
|
|
||||||
MetaIdleMonitorWatchNative *watch_native;
|
|
||||||
MetaIdleMonitorWatch *watch;
|
|
||||||
MetaIdleMonitorNative *monitor_native = META_IDLE_MONITOR_NATIVE (monitor);
|
|
||||||
|
|
||||||
watch_native = g_slice_new0 (MetaIdleMonitorWatchNative);
|
|
||||||
watch = (MetaIdleMonitorWatch *) watch_native;
|
|
||||||
|
|
||||||
watch->monitor = monitor;
|
|
||||||
watch->id = get_next_watch_serial ();
|
|
||||||
watch->callback = callback;
|
|
||||||
watch->user_data = user_data;
|
|
||||||
watch->notify = notify;
|
|
||||||
watch->timeout_msec = timeout_msec;
|
|
||||||
|
|
||||||
if (timeout_msec != 0)
|
|
||||||
{
|
|
||||||
GSource *source = g_source_new (&native_source_funcs, sizeof (GSource));
|
|
||||||
|
|
||||||
g_source_set_callback (source, NULL, watch, NULL);
|
|
||||||
g_source_set_ready_time (source, monitor_native->last_event_time + timeout_msec * 1000);
|
|
||||||
g_source_attach (source, NULL);
|
|
||||||
g_source_unref (source);
|
|
||||||
|
|
||||||
watch_native->timeout_source = source;
|
|
||||||
}
|
|
||||||
|
|
||||||
return watch;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_idle_monitor_native_class_init (MetaIdleMonitorNativeClass *klass)
|
|
||||||
{
|
|
||||||
MetaIdleMonitorClass *idle_monitor_class = META_IDLE_MONITOR_CLASS (klass);
|
|
||||||
|
|
||||||
idle_monitor_class->get_idletime = meta_idle_monitor_native_get_idletime;
|
|
||||||
idle_monitor_class->make_watch = meta_idle_monitor_native_make_watch;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_idle_monitor_native_init (MetaIdleMonitorNative *monitor_native)
|
|
||||||
{
|
|
||||||
MetaIdleMonitor *monitor = META_IDLE_MONITOR (monitor_native);
|
|
||||||
|
|
||||||
monitor->watches = g_hash_table_new_full (NULL, NULL, NULL, free_watch);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
MetaIdleMonitorNative *monitor_native;
|
|
||||||
GList *fired_watches;
|
|
||||||
} CheckNativeClosure;
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
check_native_watch (gpointer key,
|
|
||||||
gpointer value,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
MetaIdleMonitorWatchNative *watch_native = value;
|
|
||||||
MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_native;
|
|
||||||
CheckNativeClosure *closure = user_data;
|
|
||||||
gboolean steal;
|
|
||||||
|
|
||||||
if (watch->timeout_msec == 0)
|
|
||||||
{
|
|
||||||
closure->fired_watches = g_list_prepend (closure->fired_watches, watch);
|
|
||||||
steal = TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_source_set_ready_time (watch_native->timeout_source,
|
|
||||||
closure->monitor_native->last_event_time +
|
|
||||||
watch->timeout_msec * 1000);
|
|
||||||
steal = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return steal;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
fire_native_watch (gpointer watch,
|
|
||||||
gpointer data)
|
|
||||||
{
|
|
||||||
_meta_idle_monitor_watch_fire (watch);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
meta_idle_monitor_native_reset_idletime (MetaIdleMonitor *monitor)
|
|
||||||
{
|
|
||||||
MetaIdleMonitorNative *monitor_native = META_IDLE_MONITOR_NATIVE (monitor);
|
|
||||||
CheckNativeClosure closure;
|
|
||||||
|
|
||||||
monitor_native->last_event_time = g_get_monotonic_time ();
|
|
||||||
|
|
||||||
closure.monitor_native = monitor_native;
|
|
||||||
closure.fired_watches = NULL;
|
|
||||||
g_hash_table_foreach_steal (monitor->watches, check_native_watch, &closure);
|
|
||||||
|
|
||||||
g_list_foreach (closure.fired_watches, fire_native_watch, NULL);
|
|
||||||
g_list_free (closure.fired_watches);
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright 2013 Red Hat, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
|
|
||||||
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef META_IDLE_MONITOR_NATIVE_H
|
|
||||||
#define META_IDLE_MONITOR_NATIVE_H
|
|
||||||
|
|
||||||
#include <glib-object.h>
|
|
||||||
#include <meta/meta-idle-monitor.h>
|
|
||||||
|
|
||||||
#define META_TYPE_IDLE_MONITOR_NATIVE (meta_idle_monitor_native_get_type ())
|
|
||||||
#define META_IDLE_MONITOR_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_IDLE_MONITOR_NATIVE, MetaIdleMonitorNative))
|
|
||||||
#define META_IDLE_MONITOR_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_IDLE_MONITOR_NATIVE, MetaIdleMonitorNativeClass))
|
|
||||||
#define META_IS_IDLE_MONITOR_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_IDLE_MONITOR_NATIVE))
|
|
||||||
#define META_IS_IDLE_MONITOR_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_IDLE_MONITOR_NATIVE))
|
|
||||||
#define META_IDLE_MONITOR_NATIVE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_IDLE_MONITOR_NATIVE, MetaIdleMonitorNativeClass))
|
|
||||||
|
|
||||||
typedef struct _MetaIdleMonitorNative MetaIdleMonitorNative;
|
|
||||||
typedef struct _MetaIdleMonitorNativeClass MetaIdleMonitorNativeClass;
|
|
||||||
|
|
||||||
GType meta_idle_monitor_native_get_type (void);
|
|
||||||
|
|
||||||
void meta_idle_monitor_native_reset_idletime (MetaIdleMonitor *monitor);
|
|
||||||
|
|
||||||
#endif /* META_IDLE_MONITOR_NATIVE_H */
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2001 Havoc Pennington
|
|
||||||
* Copyright (C) 2003 Rob Adams
|
|
||||||
* Copyright (C) 2004-2006 Elijah Newren
|
|
||||||
* Copyright (C) 2013 Red Hat Inc.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef META_MONITOR_MANAGER_KMS_H
|
|
||||||
#define META_MONITOR_MANAGER_KMS_H
|
|
||||||
|
|
||||||
#include "meta-monitor-manager.h"
|
|
||||||
|
|
||||||
#define META_TYPE_MONITOR_MANAGER_KMS (meta_monitor_manager_kms_get_type ())
|
|
||||||
#define META_MONITOR_MANAGER_KMS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKms))
|
|
||||||
#define META_MONITOR_MANAGER_KMS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKmsClass))
|
|
||||||
#define META_IS_MONITOR_MANAGER_KMS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_MANAGER_KMS))
|
|
||||||
#define META_IS_MONITOR_MANAGER_KMS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MONITOR_MANAGER_KMS))
|
|
||||||
#define META_MONITOR_MANAGER_KMS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKmsClass))
|
|
||||||
|
|
||||||
typedef struct _MetaMonitorManagerKmsClass MetaMonitorManagerKmsClass;
|
|
||||||
typedef struct _MetaMonitorManagerKms MetaMonitorManagerKms;
|
|
||||||
|
|
||||||
GType meta_monitor_manager_kms_get_type (void);
|
|
||||||
|
|
||||||
#endif /* META_MONITOR_MANAGER_KMS_H */
|
|
||||||
@@ -1,366 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright 2013 Red Hat, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
|
|
||||||
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include "meta-idle-monitor-xsync.h"
|
|
||||||
#include "meta-idle-monitor-private.h"
|
|
||||||
|
|
||||||
#include <meta/util.h>
|
|
||||||
#include "display-private.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
struct _MetaIdleMonitorXSync
|
|
||||||
{
|
|
||||||
MetaIdleMonitor parent;
|
|
||||||
|
|
||||||
GHashTable *alarms;
|
|
||||||
Display *display;
|
|
||||||
XSyncCounter counter;
|
|
||||||
XSyncAlarm user_active_alarm;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _MetaIdleMonitorXSyncClass
|
|
||||||
{
|
|
||||||
MetaIdleMonitorClass parent_class;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
MetaIdleMonitorWatch base;
|
|
||||||
|
|
||||||
XSyncAlarm xalarm;
|
|
||||||
} MetaIdleMonitorWatchXSync;
|
|
||||||
|
|
||||||
G_DEFINE_TYPE (MetaIdleMonitorXSync, meta_idle_monitor_xsync, META_TYPE_IDLE_MONITOR)
|
|
||||||
|
|
||||||
static gint64
|
|
||||||
_xsyncvalue_to_int64 (XSyncValue value)
|
|
||||||
{
|
|
||||||
return ((guint64) XSyncValueHigh32 (value)) << 32
|
|
||||||
| (guint64) XSyncValueLow32 (value);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define GUINT64_TO_XSYNCVALUE(value, ret) XSyncIntsToValue (ret, (value) & 0xFFFFFFFF, ((guint64)(value)) >> 32)
|
|
||||||
|
|
||||||
static XSyncAlarm
|
|
||||||
_xsync_alarm_set (MetaIdleMonitorXSync *monitor_xsync,
|
|
||||||
XSyncTestType test_type,
|
|
||||||
guint64 interval,
|
|
||||||
gboolean want_events)
|
|
||||||
{
|
|
||||||
XSyncAlarmAttributes attr;
|
|
||||||
XSyncValue delta;
|
|
||||||
guint flags;
|
|
||||||
|
|
||||||
flags = XSyncCACounter | XSyncCAValueType | XSyncCATestType |
|
|
||||||
XSyncCAValue | XSyncCADelta | XSyncCAEvents;
|
|
||||||
|
|
||||||
XSyncIntToValue (&delta, 0);
|
|
||||||
attr.trigger.counter = monitor_xsync->counter;
|
|
||||||
attr.trigger.value_type = XSyncAbsolute;
|
|
||||||
attr.delta = delta;
|
|
||||||
attr.events = want_events;
|
|
||||||
|
|
||||||
GUINT64_TO_XSYNCVALUE (interval, &attr.trigger.wait_value);
|
|
||||||
attr.trigger.test_type = test_type;
|
|
||||||
return XSyncCreateAlarm (monitor_xsync->display, flags, &attr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
ensure_alarm_rescheduled (Display *dpy,
|
|
||||||
XSyncAlarm alarm)
|
|
||||||
{
|
|
||||||
XSyncAlarmAttributes attr;
|
|
||||||
|
|
||||||
/* Some versions of Xorg have an issue where alarms aren't
|
|
||||||
* always rescheduled. Calling XSyncChangeAlarm, even
|
|
||||||
* without any attributes, will reschedule the alarm. */
|
|
||||||
XSyncChangeAlarm (dpy, alarm, 0, &attr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
set_alarm_enabled (Display *dpy,
|
|
||||||
XSyncAlarm alarm,
|
|
||||||
gboolean enabled)
|
|
||||||
{
|
|
||||||
XSyncAlarmAttributes attr;
|
|
||||||
attr.events = enabled;
|
|
||||||
XSyncChangeAlarm (dpy, alarm, XSyncCAEvents, &attr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
check_x11_watch (gpointer data,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
MetaIdleMonitorWatchXSync *watch_xsync = data;
|
|
||||||
MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_xsync;
|
|
||||||
XSyncAlarm alarm = (XSyncAlarm) user_data;
|
|
||||||
|
|
||||||
if (watch_xsync->xalarm != alarm)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_meta_idle_monitor_watch_fire (watch);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *
|
|
||||||
counter_name_for_device (int device_id)
|
|
||||||
{
|
|
||||||
if (device_id > 0)
|
|
||||||
return g_strdup_printf ("DEVICEIDLETIME %d", device_id);
|
|
||||||
|
|
||||||
return g_strdup ("IDLETIME");
|
|
||||||
}
|
|
||||||
|
|
||||||
static XSyncCounter
|
|
||||||
find_idletime_counter (MetaIdleMonitorXSync *monitor_xsync)
|
|
||||||
{
|
|
||||||
MetaIdleMonitor *monitor = META_IDLE_MONITOR (monitor_xsync);
|
|
||||||
int i;
|
|
||||||
int ncounters;
|
|
||||||
XSyncSystemCounter *counters;
|
|
||||||
XSyncCounter counter = None;
|
|
||||||
char *counter_name;
|
|
||||||
|
|
||||||
counter_name = counter_name_for_device (monitor->device_id);
|
|
||||||
counters = XSyncListSystemCounters (monitor_xsync->display, &ncounters);
|
|
||||||
for (i = 0; i < ncounters; i++)
|
|
||||||
{
|
|
||||||
if (counters[i].name != NULL && strcmp (counters[i].name, counter_name) == 0)
|
|
||||||
{
|
|
||||||
counter = counters[i].counter;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
XSyncFreeSystemCounterList (counters);
|
|
||||||
g_free (counter_name);
|
|
||||||
|
|
||||||
return counter;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
init_xsync (MetaIdleMonitorXSync *monitor_xsync)
|
|
||||||
{
|
|
||||||
monitor_xsync->counter = find_idletime_counter (monitor_xsync);
|
|
||||||
/* IDLETIME counter not found? */
|
|
||||||
if (monitor_xsync->counter == None)
|
|
||||||
{
|
|
||||||
g_warning ("IDLETIME counter not found\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
monitor_xsync->user_active_alarm = _xsync_alarm_set (monitor_xsync, XSyncNegativeTransition, 1, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_idle_monitor_xsync_dispose (GObject *object)
|
|
||||||
{
|
|
||||||
MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (object);
|
|
||||||
|
|
||||||
if (monitor_xsync->user_active_alarm != None)
|
|
||||||
{
|
|
||||||
XSyncDestroyAlarm (monitor_xsync->display, monitor_xsync->user_active_alarm);
|
|
||||||
monitor_xsync->user_active_alarm = None;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_clear_pointer (&monitor_xsync->alarms, g_hash_table_destroy);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (meta_idle_monitor_xsync_parent_class)->dispose (object);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_idle_monitor_xsync_constructed (GObject *object)
|
|
||||||
{
|
|
||||||
MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (object);
|
|
||||||
|
|
||||||
g_assert (!meta_is_wayland_compositor ());
|
|
||||||
|
|
||||||
monitor_xsync->display = meta_get_display ()->xdisplay;
|
|
||||||
init_xsync (monitor_xsync);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (meta_idle_monitor_xsync_parent_class)->constructed (object);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gint64
|
|
||||||
meta_idle_monitor_xsync_get_idletime (MetaIdleMonitor *monitor)
|
|
||||||
{
|
|
||||||
MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (monitor);
|
|
||||||
XSyncValue value;
|
|
||||||
|
|
||||||
if (!XSyncQueryCounter (monitor_xsync->display, monitor_xsync->counter, &value))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return _xsyncvalue_to_int64 (value);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
fire_watch_idle (gpointer data)
|
|
||||||
{
|
|
||||||
MetaIdleMonitorWatch *watch = data;
|
|
||||||
|
|
||||||
watch->idle_source_id = 0;
|
|
||||||
_meta_idle_monitor_watch_fire (watch);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static guint32
|
|
||||||
get_next_watch_serial (void)
|
|
||||||
{
|
|
||||||
static guint32 serial = 0;
|
|
||||||
g_atomic_int_inc (&serial);
|
|
||||||
return serial;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
free_watch (gpointer data)
|
|
||||||
{
|
|
||||||
MetaIdleMonitorWatchXSync *watch_xsync = data;
|
|
||||||
MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_xsync;
|
|
||||||
MetaIdleMonitor *monitor = watch->monitor;
|
|
||||||
MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (monitor);
|
|
||||||
|
|
||||||
g_object_ref (monitor);
|
|
||||||
|
|
||||||
if (watch->idle_source_id)
|
|
||||||
{
|
|
||||||
g_source_remove (watch->idle_source_id);
|
|
||||||
watch->idle_source_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (watch->notify != NULL)
|
|
||||||
watch->notify (watch->user_data);
|
|
||||||
|
|
||||||
if (watch_xsync->xalarm != monitor_xsync->user_active_alarm &&
|
|
||||||
watch_xsync->xalarm != None)
|
|
||||||
{
|
|
||||||
XSyncDestroyAlarm (monitor_xsync->display, watch_xsync->xalarm);
|
|
||||||
g_hash_table_remove (monitor_xsync->alarms, (gpointer) watch_xsync->xalarm);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_object_unref (monitor);
|
|
||||||
g_slice_free (MetaIdleMonitorWatchXSync, watch_xsync);
|
|
||||||
}
|
|
||||||
|
|
||||||
static MetaIdleMonitorWatch *
|
|
||||||
meta_idle_monitor_xsync_make_watch (MetaIdleMonitor *monitor,
|
|
||||||
guint64 timeout_msec,
|
|
||||||
MetaIdleMonitorWatchFunc callback,
|
|
||||||
gpointer user_data,
|
|
||||||
GDestroyNotify notify)
|
|
||||||
{
|
|
||||||
MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (monitor);
|
|
||||||
MetaIdleMonitorWatchXSync *watch_xsync;
|
|
||||||
MetaIdleMonitorWatch *watch;
|
|
||||||
|
|
||||||
watch_xsync = g_slice_new0 (MetaIdleMonitorWatchXSync);
|
|
||||||
watch = (MetaIdleMonitorWatch *) watch_xsync;
|
|
||||||
|
|
||||||
watch->monitor = monitor;
|
|
||||||
watch->id = get_next_watch_serial ();
|
|
||||||
watch->callback = callback;
|
|
||||||
watch->user_data = user_data;
|
|
||||||
watch->notify = notify;
|
|
||||||
watch->timeout_msec = timeout_msec;
|
|
||||||
|
|
||||||
if (monitor_xsync->user_active_alarm != None)
|
|
||||||
{
|
|
||||||
if (timeout_msec != 0)
|
|
||||||
{
|
|
||||||
watch_xsync->xalarm = _xsync_alarm_set (monitor_xsync, XSyncPositiveTransition, timeout_msec, TRUE);
|
|
||||||
|
|
||||||
g_hash_table_add (monitor_xsync->alarms, (gpointer) watch_xsync->xalarm);
|
|
||||||
|
|
||||||
if (meta_idle_monitor_get_idletime (monitor) > (gint64)timeout_msec)
|
|
||||||
watch->idle_source_id = g_idle_add (fire_watch_idle, watch);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
watch_xsync->xalarm = monitor_xsync->user_active_alarm;
|
|
||||||
|
|
||||||
set_alarm_enabled (monitor_xsync->display, monitor_xsync->user_active_alarm, TRUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return watch;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_idle_monitor_xsync_class_init (MetaIdleMonitorXSyncClass *klass)
|
|
||||||
{
|
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
||||||
MetaIdleMonitorClass *idle_monitor_class = META_IDLE_MONITOR_CLASS (klass);
|
|
||||||
|
|
||||||
object_class->dispose = meta_idle_monitor_xsync_dispose;
|
|
||||||
object_class->constructed = meta_idle_monitor_xsync_constructed;
|
|
||||||
|
|
||||||
idle_monitor_class->get_idletime = meta_idle_monitor_xsync_get_idletime;
|
|
||||||
idle_monitor_class->make_watch = meta_idle_monitor_xsync_make_watch;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_idle_monitor_xsync_init (MetaIdleMonitorXSync *monitor_xsync)
|
|
||||||
{
|
|
||||||
MetaIdleMonitor *monitor = META_IDLE_MONITOR (monitor_xsync);
|
|
||||||
|
|
||||||
monitor->watches = g_hash_table_new_full (NULL, NULL, NULL, free_watch);
|
|
||||||
monitor_xsync->alarms = g_hash_table_new (NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
meta_idle_monitor_xsync_handle_xevent (MetaIdleMonitor *monitor,
|
|
||||||
XSyncAlarmNotifyEvent *alarm_event)
|
|
||||||
{
|
|
||||||
MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (monitor);
|
|
||||||
XSyncAlarm alarm;
|
|
||||||
GList *watches;
|
|
||||||
gboolean has_alarm;
|
|
||||||
|
|
||||||
if (alarm_event->state != XSyncAlarmActive)
|
|
||||||
return;
|
|
||||||
|
|
||||||
alarm = alarm_event->alarm;
|
|
||||||
|
|
||||||
has_alarm = FALSE;
|
|
||||||
|
|
||||||
if (alarm == monitor_xsync->user_active_alarm)
|
|
||||||
{
|
|
||||||
set_alarm_enabled (monitor_xsync->display,
|
|
||||||
alarm,
|
|
||||||
FALSE);
|
|
||||||
has_alarm = TRUE;
|
|
||||||
}
|
|
||||||
else if (g_hash_table_contains (monitor_xsync->alarms, (gpointer) alarm))
|
|
||||||
{
|
|
||||||
ensure_alarm_rescheduled (monitor_xsync->display,
|
|
||||||
alarm);
|
|
||||||
has_alarm = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_alarm)
|
|
||||||
{
|
|
||||||
watches = g_hash_table_get_values (monitor->watches);
|
|
||||||
|
|
||||||
g_list_foreach (watches, check_x11_watch, (gpointer) alarm);
|
|
||||||
g_list_free (watches);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright 2013 Red Hat, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
|
|
||||||
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef META_IDLE_MONITOR_XSYNC_H
|
|
||||||
#define META_IDLE_MONITOR_XSYNC_H
|
|
||||||
|
|
||||||
#include <glib-object.h>
|
|
||||||
#include <meta/meta-idle-monitor.h>
|
|
||||||
|
|
||||||
#include <X11/Xlib.h>
|
|
||||||
#include <X11/extensions/sync.h>
|
|
||||||
|
|
||||||
#define META_TYPE_IDLE_MONITOR_XSYNC (meta_idle_monitor_xsync_get_type ())
|
|
||||||
#define META_IDLE_MONITOR_XSYNC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_IDLE_MONITOR_XSYNC, MetaIdleMonitorXSync))
|
|
||||||
#define META_IDLE_MONITOR_XSYNC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_IDLE_MONITOR_XSYNC, MetaIdleMonitorXSyncClass))
|
|
||||||
#define META_IS_IDLE_MONITOR_XSYNC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_IDLE_MONITOR_XSYNC))
|
|
||||||
#define META_IS_IDLE_MONITOR_XSYNC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_IDLE_MONITOR_XSYNC))
|
|
||||||
#define META_IDLE_MONITOR_XSYNC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_IDLE_MONITOR_XSYNC, MetaIdleMonitorXSyncClass))
|
|
||||||
|
|
||||||
typedef struct _MetaIdleMonitorXSync MetaIdleMonitorXSync;
|
|
||||||
typedef struct _MetaIdleMonitorXSyncClass MetaIdleMonitorXSyncClass;
|
|
||||||
|
|
||||||
GType meta_idle_monitor_xsync_get_type (void);
|
|
||||||
|
|
||||||
void meta_idle_monitor_xsync_handle_xevent (MetaIdleMonitor *monitor,
|
|
||||||
XSyncAlarmNotifyEvent *xevent);
|
|
||||||
|
|
||||||
void meta_idle_monitor_xsync_handle_xevent_all (XEvent *xevent);
|
|
||||||
|
|
||||||
#endif /* META_IDLE_MONITOR_XSYNC_H */
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2001 Havoc Pennington
|
|
||||||
* Copyright (C) 2003 Rob Adams
|
|
||||||
* Copyright (C) 2004-2006 Elijah Newren
|
|
||||||
* Copyright (C) 2013 Red Hat Inc.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef META_MONITOR_MANAGER_XRANDR_H
|
|
||||||
#define META_MONITOR_MANAGER_XRANDR_H
|
|
||||||
|
|
||||||
#include "meta-monitor-manager.h"
|
|
||||||
|
|
||||||
#define META_TYPE_MONITOR_MANAGER_XRANDR (meta_monitor_manager_xrandr_get_type ())
|
|
||||||
#define META_MONITOR_MANAGER_XRANDR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandr))
|
|
||||||
#define META_MONITOR_MANAGER_XRANDR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandrClass))
|
|
||||||
#define META_IS_MONITOR_MANAGER_XRANDR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_MANAGER_XRANDR))
|
|
||||||
#define META_IS_MONITOR_MANAGER_XRANDR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MONITOR_MANAGER_XRANDR))
|
|
||||||
#define META_MONITOR_MANAGER_XRANDR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandrClass))
|
|
||||||
|
|
||||||
typedef struct _MetaMonitorManagerXrandrClass MetaMonitorManagerXrandrClass;
|
|
||||||
typedef struct _MetaMonitorManagerXrandr MetaMonitorManagerXrandr;
|
|
||||||
|
|
||||||
GType meta_monitor_manager_xrandr_get_type (void);
|
|
||||||
|
|
||||||
#endif /* META_MONITOR_MANAGER_XRANDR_H */
|
|
||||||
@@ -11,21 +11,35 @@
|
|||||||
#include "meta-window-actor-private.h"
|
#include "meta-window-actor-private.h"
|
||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
|
|
||||||
|
typedef struct _MetaCompScreen MetaCompScreen;
|
||||||
|
|
||||||
struct _MetaCompositor
|
struct _MetaCompositor
|
||||||
{
|
{
|
||||||
MetaDisplay *display;
|
MetaDisplay *display;
|
||||||
|
|
||||||
guint repaint_func_id;
|
guint repaint_func_id;
|
||||||
|
|
||||||
|
ClutterActor *shadow_src;
|
||||||
|
|
||||||
|
MetaPlugin *modal_plugin;
|
||||||
|
|
||||||
gint64 server_time_query_time;
|
gint64 server_time_query_time;
|
||||||
gint64 server_time_offset;
|
gint64 server_time_offset;
|
||||||
|
|
||||||
guint server_time_is_monotonic_time : 1;
|
guint server_time_is_monotonic_time : 1;
|
||||||
|
guint show_redraw : 1;
|
||||||
|
guint debug : 1;
|
||||||
guint no_mipmaps : 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;
|
ClutterActor *background_actor;
|
||||||
GList *windows;
|
GList *windows;
|
||||||
|
GHashTable *windows_by_xid;
|
||||||
Window output;
|
Window output;
|
||||||
|
|
||||||
CoglOnscreen *onscreen;
|
CoglOnscreen *onscreen;
|
||||||
@@ -43,17 +57,19 @@ struct _MetaCompositor
|
|||||||
/* Wait 2ms after vblank before starting to draw next frame */
|
/* Wait 2ms after vblank before starting to draw next frame */
|
||||||
#define META_SYNC_DELAY 2
|
#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,
|
MetaPlugin *plugin,
|
||||||
MetaModalOptions options,
|
MetaModalOptions options,
|
||||||
guint32 timestamp);
|
guint32 timestamp);
|
||||||
void meta_end_modal_for_plugin (MetaCompositor *compositor,
|
void meta_end_modal_for_plugin (MetaScreen *screen,
|
||||||
MetaPlugin *plugin,
|
MetaPlugin *plugin,
|
||||||
guint32 timestamp);
|
guint32 timestamp);
|
||||||
|
|
||||||
gint64 meta_compositor_monotonic_time_to_server_time (MetaDisplay *display,
|
gint64 meta_compositor_monotonic_time_to_server_time (MetaDisplay *display,
|
||||||
gint64 monotonic_time);
|
gint64 monotonic_time);
|
||||||
|
|
||||||
|
void meta_check_end_modal (MetaScreen *screen);
|
||||||
|
|
||||||
#endif /* META_COMPOSITOR_PRIVATE_H */
|
#endif /* META_COMPOSITOR_PRIVATE_H */
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -26,6 +26,8 @@
|
|||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <cogl/cogl-texture-pixmap-x11.h>
|
||||||
|
|
||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
|
|
||||||
#include "cogl-utils.h"
|
#include "cogl-utils.h"
|
||||||
@@ -753,6 +755,88 @@ set_filename (MetaBackground *self,
|
|||||||
priv->filename = g_strdup (filename);
|
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:
|
* meta_background_load_gradient:
|
||||||
* @self: the #MetaBackground
|
* @self: the #MetaBackground
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ static GType plugin_type = G_TYPE_NONE;
|
|||||||
|
|
||||||
struct MetaPluginManager
|
struct MetaPluginManager
|
||||||
{
|
{
|
||||||
MetaCompositor *compositor;
|
MetaScreen *screen;
|
||||||
MetaPlugin *plugin;
|
MetaPlugin *plugin;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -91,7 +91,7 @@ on_confirm_display_change (MetaMonitorManager *monitors,
|
|||||||
}
|
}
|
||||||
|
|
||||||
MetaPluginManager *
|
MetaPluginManager *
|
||||||
meta_plugin_manager_new (MetaCompositor *compositor)
|
meta_plugin_manager_new (MetaScreen *screen)
|
||||||
{
|
{
|
||||||
MetaPluginManager *plugin_mgr;
|
MetaPluginManager *plugin_mgr;
|
||||||
MetaPluginClass *klass;
|
MetaPluginClass *klass;
|
||||||
@@ -99,10 +99,8 @@ meta_plugin_manager_new (MetaCompositor *compositor)
|
|||||||
MetaMonitorManager *monitors;
|
MetaMonitorManager *monitors;
|
||||||
|
|
||||||
plugin_mgr = g_new0 (MetaPluginManager, 1);
|
plugin_mgr = g_new0 (MetaPluginManager, 1);
|
||||||
plugin_mgr->compositor = compositor;
|
plugin_mgr->screen = screen;
|
||||||
plugin_mgr->plugin = plugin = g_object_new (plugin_type, NULL);
|
plugin_mgr->plugin = plugin = g_object_new (plugin_type, "screen", screen, NULL);
|
||||||
|
|
||||||
_meta_plugin_set_compositor (plugin, compositor);
|
|
||||||
|
|
||||||
klass = META_PLUGIN_GET_CLASS (plugin);
|
klass = META_PLUGIN_GET_CLASS (plugin);
|
||||||
|
|
||||||
@@ -153,7 +151,7 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
|
|||||||
{
|
{
|
||||||
MetaPlugin *plugin = plugin_mgr->plugin;
|
MetaPlugin *plugin = plugin_mgr->plugin;
|
||||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||||
MetaDisplay *display = plugin_mgr->compositor->display;
|
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
|
||||||
gboolean retval = FALSE;
|
gboolean retval = FALSE;
|
||||||
|
|
||||||
if (display->display_opening)
|
if (display->display_opening)
|
||||||
@@ -167,6 +165,8 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
|
|||||||
retval = TRUE;
|
retval = TRUE;
|
||||||
meta_plugin_manager_kill_window_effects (plugin_mgr,
|
meta_plugin_manager_kill_window_effects (plugin_mgr,
|
||||||
actor);
|
actor);
|
||||||
|
|
||||||
|
_meta_plugin_effect_started (plugin);
|
||||||
klass->minimize (plugin, actor);
|
klass->minimize (plugin, actor);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -176,6 +176,8 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
|
|||||||
retval = TRUE;
|
retval = TRUE;
|
||||||
meta_plugin_manager_kill_window_effects (plugin_mgr,
|
meta_plugin_manager_kill_window_effects (plugin_mgr,
|
||||||
actor);
|
actor);
|
||||||
|
|
||||||
|
_meta_plugin_effect_started (plugin);
|
||||||
klass->map (plugin, actor);
|
klass->map (plugin, actor);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -183,6 +185,7 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
|
|||||||
if (klass->destroy)
|
if (klass->destroy)
|
||||||
{
|
{
|
||||||
retval = TRUE;
|
retval = TRUE;
|
||||||
|
_meta_plugin_effect_started (plugin);
|
||||||
klass->destroy (plugin, actor);
|
klass->destroy (plugin, actor);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -213,7 +216,7 @@ meta_plugin_manager_event_maximize (MetaPluginManager *plugin_mgr,
|
|||||||
{
|
{
|
||||||
MetaPlugin *plugin = plugin_mgr->plugin;
|
MetaPlugin *plugin = plugin_mgr->plugin;
|
||||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||||
MetaDisplay *display = plugin_mgr->compositor->display;
|
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
|
||||||
gboolean retval = FALSE;
|
gboolean retval = FALSE;
|
||||||
|
|
||||||
if (display->display_opening)
|
if (display->display_opening)
|
||||||
@@ -227,6 +230,8 @@ meta_plugin_manager_event_maximize (MetaPluginManager *plugin_mgr,
|
|||||||
retval = TRUE;
|
retval = TRUE;
|
||||||
meta_plugin_manager_kill_window_effects (plugin_mgr,
|
meta_plugin_manager_kill_window_effects (plugin_mgr,
|
||||||
actor);
|
actor);
|
||||||
|
|
||||||
|
_meta_plugin_effect_started (plugin);
|
||||||
klass->maximize (plugin, actor,
|
klass->maximize (plugin, actor,
|
||||||
target_x, target_y,
|
target_x, target_y,
|
||||||
target_width, target_height);
|
target_width, target_height);
|
||||||
@@ -238,6 +243,8 @@ meta_plugin_manager_event_maximize (MetaPluginManager *plugin_mgr,
|
|||||||
retval = TRUE;
|
retval = TRUE;
|
||||||
meta_plugin_manager_kill_window_effects (plugin_mgr,
|
meta_plugin_manager_kill_window_effects (plugin_mgr,
|
||||||
actor);
|
actor);
|
||||||
|
|
||||||
|
_meta_plugin_effect_started (plugin);
|
||||||
klass->unmaximize (plugin, actor,
|
klass->unmaximize (plugin, actor,
|
||||||
target_x, target_y,
|
target_x, target_y,
|
||||||
target_width, target_height);
|
target_width, target_height);
|
||||||
@@ -266,7 +273,7 @@ meta_plugin_manager_switch_workspace (MetaPluginManager *plugin_mgr,
|
|||||||
{
|
{
|
||||||
MetaPlugin *plugin = plugin_mgr->plugin;
|
MetaPlugin *plugin = plugin_mgr->plugin;
|
||||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||||
MetaDisplay *display = plugin_mgr->compositor->display;
|
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
|
||||||
gboolean retval = FALSE;
|
gboolean retval = FALSE;
|
||||||
|
|
||||||
if (display->display_opening)
|
if (display->display_opening)
|
||||||
@@ -276,6 +283,8 @@ meta_plugin_manager_switch_workspace (MetaPluginManager *plugin_mgr,
|
|||||||
{
|
{
|
||||||
retval = TRUE;
|
retval = TRUE;
|
||||||
meta_plugin_manager_kill_switch_workspace (plugin_mgr);
|
meta_plugin_manager_kill_switch_workspace (plugin_mgr);
|
||||||
|
|
||||||
|
_meta_plugin_effect_started (plugin);
|
||||||
klass->switch_workspace (plugin, from, to, direction);
|
klass->switch_workspace (plugin, from, to, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,7 +333,7 @@ meta_plugin_manager_show_tile_preview (MetaPluginManager *plugin_mgr,
|
|||||||
{
|
{
|
||||||
MetaPlugin *plugin = plugin_mgr->plugin;
|
MetaPlugin *plugin = plugin_mgr->plugin;
|
||||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||||
MetaDisplay *display = plugin_mgr->compositor->display;
|
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
|
||||||
|
|
||||||
if (display->display_opening)
|
if (display->display_opening)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@@ -343,7 +352,7 @@ meta_plugin_manager_hide_tile_preview (MetaPluginManager *plugin_mgr)
|
|||||||
{
|
{
|
||||||
MetaPlugin *plugin = plugin_mgr->plugin;
|
MetaPlugin *plugin = plugin_mgr->plugin;
|
||||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||||
MetaDisplay *display = plugin_mgr->compositor->display;
|
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
|
||||||
|
|
||||||
if (display->display_opening)
|
if (display->display_opening)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
*/
|
*/
|
||||||
typedef struct MetaPluginManager MetaPluginManager;
|
typedef struct MetaPluginManager MetaPluginManager;
|
||||||
|
|
||||||
MetaPluginManager * meta_plugin_manager_new (MetaCompositor *compositor);
|
MetaPluginManager * meta_plugin_manager_new (MetaScreen *screen);
|
||||||
|
|
||||||
void meta_plugin_manager_load (const gchar *plugin_name);
|
void meta_plugin_manager_load (const gchar *plugin_name);
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,6 @@
|
|||||||
#include "meta-plugin-manager.h"
|
#include "meta-plugin-manager.h"
|
||||||
#include <meta/screen.h>
|
#include <meta/screen.h>
|
||||||
#include <meta/display.h>
|
#include <meta/display.h>
|
||||||
#include <meta/util.h>
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
@@ -40,22 +39,98 @@
|
|||||||
|
|
||||||
#include "compositor-private.h"
|
#include "compositor-private.h"
|
||||||
#include "meta-window-actor-private.h"
|
#include "meta-window-actor-private.h"
|
||||||
#include "meta-monitor-manager.h"
|
#include "monitor-private.h"
|
||||||
|
|
||||||
G_DEFINE_ABSTRACT_TYPE (MetaPlugin, meta_plugin, G_TYPE_OBJECT);
|
G_DEFINE_ABSTRACT_TYPE (MetaPlugin, meta_plugin, G_TYPE_OBJECT);
|
||||||
|
|
||||||
#define META_PLUGIN_GET_PRIVATE(obj) \
|
#define META_PLUGIN_GET_PRIVATE(obj) \
|
||||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_PLUGIN, MetaPluginPrivate))
|
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_PLUGIN, MetaPluginPrivate))
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
PROP_SCREEN,
|
||||||
|
PROP_DEBUG_MODE,
|
||||||
|
};
|
||||||
|
|
||||||
struct _MetaPluginPrivate
|
struct _MetaPluginPrivate
|
||||||
{
|
{
|
||||||
MetaCompositor *compositor;
|
MetaScreen *screen;
|
||||||
|
|
||||||
|
gint running;
|
||||||
|
gboolean debug : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_plugin_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
MetaPluginPrivate *priv = META_PLUGIN (object)->priv;
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_SCREEN:
|
||||||
|
priv->screen = g_value_get_object (value);
|
||||||
|
break;
|
||||||
|
case PROP_DEBUG_MODE:
|
||||||
|
priv->debug = g_value_get_boolean (value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_plugin_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
MetaPluginPrivate *priv = META_PLUGIN (object)->priv;
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_SCREEN:
|
||||||
|
g_value_set_object (value, priv->screen);
|
||||||
|
break;
|
||||||
|
case PROP_DEBUG_MODE:
|
||||||
|
g_value_set_boolean (value, priv->debug);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_plugin_class_init (MetaPluginClass *klass)
|
meta_plugin_class_init (MetaPluginClass *klass)
|
||||||
{
|
{
|
||||||
g_type_class_add_private (klass, sizeof (MetaPluginPrivate));
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
gobject_class->set_property = meta_plugin_set_property;
|
||||||
|
gobject_class->get_property = meta_plugin_get_property;
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_SCREEN,
|
||||||
|
g_param_spec_object ("screen",
|
||||||
|
"MetaScreen",
|
||||||
|
"MetaScreen",
|
||||||
|
META_TYPE_SCREEN,
|
||||||
|
G_PARAM_READWRITE));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_DEBUG_MODE,
|
||||||
|
g_param_spec_boolean ("debug-mode",
|
||||||
|
"Debug Mode",
|
||||||
|
"Debug Mode",
|
||||||
|
FALSE,
|
||||||
|
G_PARAM_READABLE));
|
||||||
|
|
||||||
|
g_type_class_add_private (gobject_class, sizeof (MetaPluginPrivate));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -64,6 +139,22 @@ meta_plugin_init (MetaPlugin *self)
|
|||||||
self->priv = META_PLUGIN_GET_PRIVATE (self);
|
self->priv = META_PLUGIN_GET_PRIVATE (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
meta_plugin_running (MetaPlugin *plugin)
|
||||||
|
{
|
||||||
|
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||||
|
|
||||||
|
return (priv->running > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
meta_plugin_debug_mode (MetaPlugin *plugin)
|
||||||
|
{
|
||||||
|
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||||
|
|
||||||
|
return priv->debug;
|
||||||
|
}
|
||||||
|
|
||||||
const MetaPluginInfo *
|
const MetaPluginInfo *
|
||||||
meta_plugin_get_info (MetaPlugin *plugin)
|
meta_plugin_get_info (MetaPlugin *plugin)
|
||||||
{
|
{
|
||||||
@@ -75,6 +166,21 @@ meta_plugin_get_info (MetaPlugin *plugin)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _meta_plugin_effect_started:
|
||||||
|
* @plugin: the plugin
|
||||||
|
*
|
||||||
|
* Mark that an effect has started for the plugin. This is called
|
||||||
|
* internally by MetaPluginManager.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_meta_plugin_effect_started (MetaPlugin *plugin)
|
||||||
|
{
|
||||||
|
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||||
|
|
||||||
|
priv->running++;
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
_meta_plugin_xevent_filter (MetaPlugin *plugin,
|
_meta_plugin_xevent_filter (MetaPlugin *plugin,
|
||||||
XEvent *xev)
|
XEvent *xev)
|
||||||
@@ -102,7 +208,15 @@ meta_plugin_switch_workspace_completed (MetaPlugin *plugin)
|
|||||||
{
|
{
|
||||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||||
|
|
||||||
meta_switch_workspace_completed (priv->compositor);
|
MetaScreen *screen = priv->screen;
|
||||||
|
|
||||||
|
if (priv->running-- < 0)
|
||||||
|
{
|
||||||
|
g_warning ("Error in running effect accounting, adjusting.");
|
||||||
|
priv->running = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
meta_switch_workspace_completed (screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -110,6 +224,26 @@ meta_plugin_window_effect_completed (MetaPlugin *plugin,
|
|||||||
MetaWindowActor *actor,
|
MetaWindowActor *actor,
|
||||||
unsigned long event)
|
unsigned long event)
|
||||||
{
|
{
|
||||||
|
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||||
|
|
||||||
|
if (priv->running-- < 0)
|
||||||
|
{
|
||||||
|
g_warning ("Error in running effect accounting, adjusting.");
|
||||||
|
priv->running = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!actor)
|
||||||
|
{
|
||||||
|
const MetaPluginInfo *info;
|
||||||
|
const gchar *name = NULL;
|
||||||
|
|
||||||
|
if (plugin && (info = meta_plugin_get_info (plugin)))
|
||||||
|
name = info->name;
|
||||||
|
|
||||||
|
g_warning ("Plugin [%s] passed NULL for actor!",
|
||||||
|
name ? name : "unknown");
|
||||||
|
}
|
||||||
|
|
||||||
meta_window_actor_effect_completed (actor, event);
|
meta_window_actor_effect_completed (actor, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,7 +310,7 @@ meta_plugin_begin_modal (MetaPlugin *plugin,
|
|||||||
{
|
{
|
||||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||||
|
|
||||||
return meta_begin_modal_for_plugin (priv->compositor, plugin,
|
return meta_begin_modal_for_plugin (priv->screen, plugin,
|
||||||
options, timestamp);
|
options, timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,14 +331,16 @@ meta_plugin_end_modal (MetaPlugin *plugin,
|
|||||||
{
|
{
|
||||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||||
|
|
||||||
meta_end_modal_for_plugin (priv->compositor, plugin, timestamp);
|
meta_end_modal_for_plugin (priv->screen, plugin, timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* meta_plugin_get_screen:
|
* meta_plugin_get_screen:
|
||||||
* @plugin: a #MetaPlugin
|
* @plugin: a #MetaPlugin
|
||||||
*
|
*
|
||||||
* Gets the #MetaScreen corresponding to a plugin.
|
* Gets the #MetaScreen corresponding to a plugin. Each plugin instance
|
||||||
|
* is associated with exactly one screen; if Metacity is managing
|
||||||
|
* multiple screens, multiple plugin instances will be created.
|
||||||
*
|
*
|
||||||
* Return value: (transfer none): the #MetaScreen for the plugin
|
* Return value: (transfer none): the #MetaScreen for the plugin
|
||||||
*/
|
*/
|
||||||
@@ -213,15 +349,7 @@ meta_plugin_get_screen (MetaPlugin *plugin)
|
|||||||
{
|
{
|
||||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
||||||
|
|
||||||
return priv->compositor->display->screen;
|
return priv->screen;
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
_meta_plugin_set_compositor (MetaPlugin *plugin, MetaCompositor *compositor)
|
|
||||||
{
|
|
||||||
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
|
|
||||||
|
|
||||||
priv->compositor = compositor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -33,7 +33,6 @@
|
|||||||
#include "meta-texture-tower.h"
|
#include "meta-texture-tower.h"
|
||||||
|
|
||||||
#include "meta-shaped-texture-private.h"
|
#include "meta-shaped-texture-private.h"
|
||||||
#include "meta-window-actor-private.h"
|
|
||||||
|
|
||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
#include <cogl/cogl.h>
|
#include <cogl/cogl.h>
|
||||||
@@ -577,18 +576,8 @@ static cairo_region_t *
|
|||||||
effective_unobscured_region (MetaShapedTexture *self)
|
effective_unobscured_region (MetaShapedTexture *self)
|
||||||
{
|
{
|
||||||
MetaShapedTexturePrivate *priv = self->priv;
|
MetaShapedTexturePrivate *priv = self->priv;
|
||||||
ClutterActor *parent = clutter_actor_get_parent (CLUTTER_ACTOR (self));
|
|
||||||
|
|
||||||
if (clutter_actor_has_mapped_clones (CLUTTER_ACTOR (self)))
|
return clutter_actor_has_mapped_clones (CLUTTER_ACTOR (self)) ? NULL : priv->unobscured_region;
|
||||||
return NULL;
|
|
||||||
|
|
||||||
while (parent && !META_IS_WINDOW_ACTOR (parent))
|
|
||||||
parent = clutter_actor_get_parent (parent);
|
|
||||||
|
|
||||||
if (parent && clutter_actor_has_mapped_clones (parent))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return priv->unobscured_region;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
|
|||||||
@@ -29,30 +29,15 @@
|
|||||||
#include <cogl/cogl-wayland-server.h>
|
#include <cogl/cogl-wayland-server.h>
|
||||||
#include "meta-shaped-texture-private.h"
|
#include "meta-shaped-texture-private.h"
|
||||||
|
|
||||||
#include "wayland/meta-wayland-private.h"
|
|
||||||
|
|
||||||
struct _MetaSurfaceActorWaylandPrivate
|
struct _MetaSurfaceActorWaylandPrivate
|
||||||
{
|
{
|
||||||
MetaWaylandSurface *surface;
|
MetaWaylandSurface *surface;
|
||||||
MetaWaylandBuffer *buffer;
|
MetaWaylandBuffer *buffer;
|
||||||
struct wl_listener buffer_destroy_listener;
|
|
||||||
};
|
};
|
||||||
typedef struct _MetaSurfaceActorWaylandPrivate MetaSurfaceActorWaylandPrivate;
|
typedef struct _MetaSurfaceActorWaylandPrivate MetaSurfaceActorWaylandPrivate;
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaSurfaceActorWayland, meta_surface_actor_wayland, META_TYPE_SURFACE_ACTOR)
|
G_DEFINE_TYPE_WITH_PRIVATE (MetaSurfaceActorWayland, meta_surface_actor_wayland, META_TYPE_SURFACE_ACTOR)
|
||||||
|
|
||||||
static void
|
|
||||||
meta_surface_actor_handle_buffer_destroy (struct wl_listener *listener, void *data)
|
|
||||||
{
|
|
||||||
MetaSurfaceActorWaylandPrivate *priv = wl_container_of (listener, priv, buffer_destroy_listener);
|
|
||||||
|
|
||||||
/* If the buffer is destroyed while we're attached to it,
|
|
||||||
* we want to unset priv->buffer so we don't access freed
|
|
||||||
* memory. Keep the texture set however so the user doesn't
|
|
||||||
* see the window disappear. */
|
|
||||||
priv->buffer = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_surface_actor_wayland_process_damage (MetaSurfaceActor *actor,
|
meta_surface_actor_wayland_process_damage (MetaSurfaceActor *actor,
|
||||||
int x, int y, int width, int height)
|
int x, int y, int width, int height)
|
||||||
@@ -60,19 +45,16 @@ meta_surface_actor_wayland_process_damage (MetaSurfaceActor *actor,
|
|||||||
MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor);
|
MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor);
|
||||||
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
|
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
|
||||||
|
|
||||||
if (priv->buffer)
|
struct wl_resource *resource = priv->buffer->resource;
|
||||||
|
struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (resource);
|
||||||
|
|
||||||
|
if (shm_buffer)
|
||||||
{
|
{
|
||||||
struct wl_resource *resource = priv->buffer->resource;
|
CoglTexture2D *texture = COGL_TEXTURE_2D (priv->buffer->texture);
|
||||||
struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (resource);
|
cogl_wayland_texture_set_region_from_shm_buffer (texture, x, y, width, height, shm_buffer, x, y, 0, NULL);
|
||||||
|
|
||||||
if (shm_buffer)
|
|
||||||
{
|
|
||||||
CoglTexture2D *texture = COGL_TEXTURE_2D (priv->buffer->texture);
|
|
||||||
cogl_wayland_texture_set_region_from_shm_buffer (texture, x, y, width, height, shm_buffer, x, y, 0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
meta_surface_actor_update_area (META_SURFACE_ACTOR (self), x, y, width, height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
meta_surface_actor_update_area (META_SURFACE_ACTOR (self), x, y, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -80,6 +62,13 @@ meta_surface_actor_wayland_pre_paint (MetaSurfaceActor *actor)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
meta_surface_actor_wayland_is_argb32 (MetaSurfaceActor *actor)
|
||||||
|
{
|
||||||
|
/* XXX -- look at the SHM buffer format. */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
meta_surface_actor_wayland_is_visible (MetaSurfaceActor *actor)
|
meta_surface_actor_wayland_is_visible (MetaSurfaceActor *actor)
|
||||||
{
|
{
|
||||||
@@ -108,49 +97,24 @@ meta_surface_actor_wayland_is_unredirected (MetaSurfaceActor *actor)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static MetaWindow *
|
|
||||||
meta_surface_actor_wayland_get_window (MetaSurfaceActor *actor)
|
|
||||||
{
|
|
||||||
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (META_SURFACE_ACTOR_WAYLAND (actor));
|
|
||||||
|
|
||||||
return priv->surface->window;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_surface_actor_wayland_dispose (GObject *object)
|
|
||||||
{
|
|
||||||
MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (object);
|
|
||||||
|
|
||||||
meta_surface_actor_wayland_set_buffer (self, NULL);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (meta_surface_actor_wayland_parent_class)->dispose (object);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass)
|
meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass)
|
||||||
{
|
{
|
||||||
MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass);
|
MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass);
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
||||||
|
|
||||||
surface_actor_class->process_damage = meta_surface_actor_wayland_process_damage;
|
surface_actor_class->process_damage = meta_surface_actor_wayland_process_damage;
|
||||||
surface_actor_class->pre_paint = meta_surface_actor_wayland_pre_paint;
|
surface_actor_class->pre_paint = meta_surface_actor_wayland_pre_paint;
|
||||||
|
surface_actor_class->is_argb32 = meta_surface_actor_wayland_is_argb32;
|
||||||
surface_actor_class->is_visible = meta_surface_actor_wayland_is_visible;
|
surface_actor_class->is_visible = meta_surface_actor_wayland_is_visible;
|
||||||
|
|
||||||
surface_actor_class->should_unredirect = meta_surface_actor_wayland_should_unredirect;
|
surface_actor_class->should_unredirect = meta_surface_actor_wayland_should_unredirect;
|
||||||
surface_actor_class->set_unredirected = meta_surface_actor_wayland_set_unredirected;
|
surface_actor_class->set_unredirected = meta_surface_actor_wayland_set_unredirected;
|
||||||
surface_actor_class->is_unredirected = meta_surface_actor_wayland_is_unredirected;
|
surface_actor_class->is_unredirected = meta_surface_actor_wayland_is_unredirected;
|
||||||
|
|
||||||
surface_actor_class->get_window = meta_surface_actor_wayland_get_window;
|
|
||||||
|
|
||||||
object_class->dispose = meta_surface_actor_wayland_dispose;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_surface_actor_wayland_init (MetaSurfaceActorWayland *self)
|
meta_surface_actor_wayland_init (MetaSurfaceActorWayland *self)
|
||||||
{
|
{
|
||||||
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
|
|
||||||
|
|
||||||
priv->buffer_destroy_listener.notify = meta_surface_actor_handle_buffer_destroy;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MetaSurfaceActor *
|
MetaSurfaceActor *
|
||||||
@@ -173,16 +137,10 @@ meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self,
|
|||||||
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
|
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
|
||||||
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
|
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
|
||||||
|
|
||||||
if (priv->buffer)
|
|
||||||
wl_list_remove (&priv->buffer_destroy_listener.link);
|
|
||||||
|
|
||||||
priv->buffer = buffer;
|
priv->buffer = buffer;
|
||||||
|
|
||||||
if (priv->buffer)
|
if (buffer)
|
||||||
{
|
meta_shaped_texture_set_texture (stex, buffer->texture);
|
||||||
wl_signal_add (&priv->buffer->destroy_signal, &priv->buffer_destroy_listener);
|
|
||||||
meta_shaped_texture_set_texture (stex, priv->buffer->texture);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
meta_shaped_texture_set_texture (stex, NULL);
|
meta_shaped_texture_set_texture (stex, NULL);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
#include "meta-surface-actor.h"
|
#include "meta-surface-actor.h"
|
||||||
|
|
||||||
#include "wayland/meta-wayland.h"
|
#include "meta-wayland-private.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
#include "meta-surface-actor-x11.h"
|
#include "meta-surface-actor-x11.h"
|
||||||
|
|
||||||
#include <X11/extensions/Xcomposite.h>
|
#include <X11/extensions/Xcomposite.h>
|
||||||
|
#include <X11/extensions/Xrender.h>
|
||||||
#include <cogl/cogl-texture-pixmap-x11.h>
|
#include <cogl/cogl-texture-pixmap-x11.h>
|
||||||
|
|
||||||
#include <meta/errors.h>
|
#include <meta/errors.h>
|
||||||
@@ -53,6 +54,7 @@ struct _MetaSurfaceActorX11Private
|
|||||||
guint does_full_damage : 1;
|
guint does_full_damage : 1;
|
||||||
|
|
||||||
/* Other state... */
|
/* Other state... */
|
||||||
|
guint argb32 : 1;
|
||||||
guint received_damage : 1;
|
guint received_damage : 1;
|
||||||
guint size_changed : 1;
|
guint size_changed : 1;
|
||||||
|
|
||||||
@@ -264,6 +266,28 @@ meta_surface_actor_x11_pre_paint (MetaSurfaceActor *actor)
|
|||||||
update_pixmap (self);
|
update_pixmap (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_is_argb32 (MetaSurfaceActorX11 *self)
|
||||||
|
{
|
||||||
|
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||||
|
MetaDisplay *display = priv->display;
|
||||||
|
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||||
|
|
||||||
|
XRenderPictFormat *format;
|
||||||
|
format = XRenderFindVisualFormat (xdisplay, priv->window->xvisual);
|
||||||
|
|
||||||
|
priv->argb32 = (format && format->type == PictTypeDirect && format->direct.alphaMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
meta_surface_actor_x11_is_argb32 (MetaSurfaceActor *actor)
|
||||||
|
{
|
||||||
|
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
|
||||||
|
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||||
|
|
||||||
|
return priv->argb32;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
meta_surface_actor_x11_is_visible (MetaSurfaceActor *actor)
|
meta_surface_actor_x11_is_visible (MetaSurfaceActor *actor)
|
||||||
{
|
{
|
||||||
@@ -288,7 +312,7 @@ meta_surface_actor_x11_should_unredirect (MetaSurfaceActor *actor)
|
|||||||
if (window->shape_region != NULL)
|
if (window->shape_region != NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (meta_surface_actor_is_argb32 (actor) && !meta_window_requested_bypass_compositor (window))
|
if (priv->argb32 && !meta_window_requested_bypass_compositor (window))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (!meta_window_is_monitor_sized (window))
|
if (!meta_window_is_monitor_sized (window))
|
||||||
@@ -363,14 +387,6 @@ meta_surface_actor_x11_dispose (GObject *object)
|
|||||||
G_OBJECT_CLASS (meta_surface_actor_x11_parent_class)->dispose (object);
|
G_OBJECT_CLASS (meta_surface_actor_x11_parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
static MetaWindow *
|
|
||||||
meta_surface_actor_x11_get_window (MetaSurfaceActor *actor)
|
|
||||||
{
|
|
||||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (META_SURFACE_ACTOR_X11 (actor));
|
|
||||||
|
|
||||||
return priv->window;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_surface_actor_x11_class_init (MetaSurfaceActorX11Class *klass)
|
meta_surface_actor_x11_class_init (MetaSurfaceActorX11Class *klass)
|
||||||
{
|
{
|
||||||
@@ -381,13 +397,12 @@ meta_surface_actor_x11_class_init (MetaSurfaceActorX11Class *klass)
|
|||||||
|
|
||||||
surface_actor_class->process_damage = meta_surface_actor_x11_process_damage;
|
surface_actor_class->process_damage = meta_surface_actor_x11_process_damage;
|
||||||
surface_actor_class->pre_paint = meta_surface_actor_x11_pre_paint;
|
surface_actor_class->pre_paint = meta_surface_actor_x11_pre_paint;
|
||||||
|
surface_actor_class->is_argb32 = meta_surface_actor_x11_is_argb32;
|
||||||
surface_actor_class->is_visible = meta_surface_actor_x11_is_visible;
|
surface_actor_class->is_visible = meta_surface_actor_x11_is_visible;
|
||||||
|
|
||||||
surface_actor_class->should_unredirect = meta_surface_actor_x11_should_unredirect;
|
surface_actor_class->should_unredirect = meta_surface_actor_x11_should_unredirect;
|
||||||
surface_actor_class->set_unredirected = meta_surface_actor_x11_set_unredirected;
|
surface_actor_class->set_unredirected = meta_surface_actor_x11_set_unredirected;
|
||||||
surface_actor_class->is_unredirected = meta_surface_actor_x11_is_unredirected;
|
surface_actor_class->is_unredirected = meta_surface_actor_x11_is_unredirected;
|
||||||
|
|
||||||
surface_actor_class->get_window = meta_surface_actor_x11_get_window;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -436,10 +451,11 @@ meta_surface_actor_x11_new (MetaWindow *window)
|
|||||||
g_signal_connect_object (priv->window, "notify::decorated",
|
g_signal_connect_object (priv->window, "notify::decorated",
|
||||||
G_CALLBACK (window_decorated_notify), self, 0);
|
G_CALLBACK (window_decorated_notify), self, 0);
|
||||||
|
|
||||||
|
update_is_argb32 (self);
|
||||||
|
|
||||||
priv->unredirected = FALSE;
|
priv->unredirected = FALSE;
|
||||||
sync_unredirected (self);
|
sync_unredirected (self);
|
||||||
|
|
||||||
clutter_actor_set_reactive (CLUTTER_ACTOR (self), TRUE);
|
|
||||||
return META_SURFACE_ACTOR (self);
|
return META_SURFACE_ACTOR (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
#include <meta/meta-shaped-texture.h>
|
#include <meta/meta-shaped-texture.h>
|
||||||
|
#include "meta-wayland-private.h"
|
||||||
#include "meta-cullable.h"
|
#include "meta-cullable.h"
|
||||||
#include "meta-shaped-texture-private.h"
|
#include "meta-shaped-texture-private.h"
|
||||||
|
|
||||||
@@ -263,26 +264,7 @@ meta_surface_actor_pre_paint (MetaSurfaceActor *self)
|
|||||||
gboolean
|
gboolean
|
||||||
meta_surface_actor_is_argb32 (MetaSurfaceActor *self)
|
meta_surface_actor_is_argb32 (MetaSurfaceActor *self)
|
||||||
{
|
{
|
||||||
MetaShapedTexture *stex = meta_surface_actor_get_texture (self);
|
return META_SURFACE_ACTOR_GET_CLASS (self)->is_argb32 (self);
|
||||||
CoglTexture *texture = meta_shaped_texture_get_texture (stex);
|
|
||||||
|
|
||||||
/* If we don't have a texture, like during initialization, assume
|
|
||||||
* that we're ARGB32. */
|
|
||||||
if (!texture)
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
switch (cogl_texture_get_components (texture))
|
|
||||||
{
|
|
||||||
case COGL_TEXTURE_COMPONENTS_A:
|
|
||||||
case COGL_TEXTURE_COMPONENTS_RGBA:
|
|
||||||
return TRUE;
|
|
||||||
case COGL_TEXTURE_COMPONENTS_RG:
|
|
||||||
case COGL_TEXTURE_COMPONENTS_RGB:
|
|
||||||
case COGL_TEXTURE_COMPONENTS_DEPTH:
|
|
||||||
return FALSE;
|
|
||||||
default:
|
|
||||||
g_assert_not_reached ();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
@@ -330,9 +312,3 @@ meta_surface_actor_is_unredirected (MetaSurfaceActor *self)
|
|||||||
{
|
{
|
||||||
return META_SURFACE_ACTOR_GET_CLASS (self)->is_unredirected (self);
|
return META_SURFACE_ACTOR_GET_CLASS (self)->is_unredirected (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
MetaWindow *
|
|
||||||
meta_surface_actor_get_window (MetaSurfaceActor *self)
|
|
||||||
{
|
|
||||||
return META_SURFACE_ACTOR_GET_CLASS (self)->get_window (self);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
#include <meta/meta-shaped-texture.h>
|
#include <meta/meta-shaped-texture.h>
|
||||||
#include <meta/window.h>
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
@@ -29,14 +28,13 @@ struct _MetaSurfaceActorClass
|
|||||||
void (* process_damage) (MetaSurfaceActor *actor,
|
void (* process_damage) (MetaSurfaceActor *actor,
|
||||||
int x, int y, int width, int height);
|
int x, int y, int width, int height);
|
||||||
void (* pre_paint) (MetaSurfaceActor *actor);
|
void (* pre_paint) (MetaSurfaceActor *actor);
|
||||||
|
gboolean (* is_argb32) (MetaSurfaceActor *actor);
|
||||||
gboolean (* is_visible) (MetaSurfaceActor *actor);
|
gboolean (* is_visible) (MetaSurfaceActor *actor);
|
||||||
|
|
||||||
gboolean (* should_unredirect) (MetaSurfaceActor *actor);
|
gboolean (* should_unredirect) (MetaSurfaceActor *actor);
|
||||||
void (* set_unredirected) (MetaSurfaceActor *actor,
|
void (* set_unredirected) (MetaSurfaceActor *actor,
|
||||||
gboolean unredirected);
|
gboolean unredirected);
|
||||||
gboolean (* is_unredirected) (MetaSurfaceActor *actor);
|
gboolean (* is_unredirected) (MetaSurfaceActor *actor);
|
||||||
|
|
||||||
MetaWindow *(* get_window) (MetaSurfaceActor *actor);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _MetaSurfaceActor
|
struct _MetaSurfaceActor
|
||||||
@@ -52,7 +50,6 @@ cairo_surface_t *meta_surface_actor_get_image (MetaSurfaceActor *self,
|
|||||||
cairo_rectangle_int_t *clip);
|
cairo_rectangle_int_t *clip);
|
||||||
|
|
||||||
MetaShapedTexture *meta_surface_actor_get_texture (MetaSurfaceActor *self);
|
MetaShapedTexture *meta_surface_actor_get_texture (MetaSurfaceActor *self);
|
||||||
MetaWindow *meta_surface_actor_get_window (MetaSurfaceActor *self);
|
|
||||||
|
|
||||||
gboolean meta_surface_actor_is_obscured (MetaSurfaceActor *self);
|
gboolean meta_surface_actor_is_obscured (MetaSurfaceActor *self);
|
||||||
gboolean meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor *self,
|
gboolean meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor *self,
|
||||||
|
|||||||
@@ -5,6 +5,9 @@
|
|||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <wayland-server.h>
|
||||||
|
#include <meta-wayland-private.h>
|
||||||
|
|
||||||
#include <X11/extensions/Xdamage.h>
|
#include <X11/extensions/Xdamage.h>
|
||||||
#include <meta/compositor-mutter.h>
|
#include <meta/compositor-mutter.h>
|
||||||
#include "meta-surface-actor.h"
|
#include "meta-surface-actor.h"
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include "frame.h"
|
#include "frame.h"
|
||||||
#include <meta/window.h>
|
#include <meta/window.h>
|
||||||
#include <meta/meta-shaped-texture.h>
|
#include <meta/meta-shaped-texture.h>
|
||||||
|
#include "xprops.h"
|
||||||
|
|
||||||
#include "compositor-private.h"
|
#include "compositor-private.h"
|
||||||
#include "meta-shaped-texture-private.h"
|
#include "meta-shaped-texture-private.h"
|
||||||
@@ -27,18 +28,17 @@
|
|||||||
#include "meta-window-actor-private.h"
|
#include "meta-window-actor-private.h"
|
||||||
#include "meta-texture-rectangle.h"
|
#include "meta-texture-rectangle.h"
|
||||||
#include "region-utils.h"
|
#include "region-utils.h"
|
||||||
#include "meta-monitor-manager.h"
|
#include "meta-wayland-private.h"
|
||||||
|
#include "monitor-private.h"
|
||||||
#include "meta-cullable.h"
|
#include "meta-cullable.h"
|
||||||
|
|
||||||
#include "meta-surface-actor.h"
|
#include "meta-surface-actor.h"
|
||||||
#include "meta-surface-actor-x11.h"
|
#include "meta-surface-actor-x11.h"
|
||||||
|
|
||||||
#include "wayland/meta-wayland-surface.h"
|
|
||||||
|
|
||||||
struct _MetaWindowActorPrivate
|
struct _MetaWindowActorPrivate
|
||||||
{
|
{
|
||||||
MetaWindow *window;
|
MetaWindow *window;
|
||||||
MetaCompositor *compositor;
|
MetaScreen *screen;
|
||||||
|
|
||||||
MetaSurfaceActor *surface;
|
MetaSurfaceActor *surface;
|
||||||
|
|
||||||
@@ -371,11 +371,11 @@ meta_window_actor_update_surface (MetaWindowActor *self)
|
|||||||
static void
|
static void
|
||||||
meta_window_actor_constructed (GObject *object)
|
meta_window_actor_constructed (GObject *object)
|
||||||
{
|
{
|
||||||
MetaWindowActor *self = META_WINDOW_ACTOR (object);
|
MetaWindowActor *self = META_WINDOW_ACTOR (object);
|
||||||
MetaWindowActorPrivate *priv = self->priv;
|
MetaWindowActorPrivate *priv = self->priv;
|
||||||
MetaWindow *window = priv->window;
|
MetaWindow *window = priv->window;
|
||||||
|
|
||||||
priv->compositor = window->display->compositor;
|
priv->screen = window->screen;
|
||||||
|
|
||||||
meta_window_actor_update_surface (self);
|
meta_window_actor_update_surface (self);
|
||||||
|
|
||||||
@@ -389,15 +389,19 @@ meta_window_actor_constructed (GObject *object)
|
|||||||
static void
|
static void
|
||||||
meta_window_actor_dispose (GObject *object)
|
meta_window_actor_dispose (GObject *object)
|
||||||
{
|
{
|
||||||
MetaWindowActor *self = META_WINDOW_ACTOR (object);
|
MetaWindowActor *self = META_WINDOW_ACTOR (object);
|
||||||
MetaWindowActorPrivate *priv = self->priv;
|
MetaWindowActorPrivate *priv = self->priv;
|
||||||
MetaCompositor *compositor = priv->compositor;
|
MetaScreen *screen;
|
||||||
|
MetaCompScreen *info;
|
||||||
|
|
||||||
if (priv->disposed)
|
if (priv->disposed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
priv->disposed = TRUE;
|
priv->disposed = TRUE;
|
||||||
|
|
||||||
|
screen = priv->screen;
|
||||||
|
info = meta_screen_get_compositor_data (screen);
|
||||||
|
|
||||||
if (priv->send_frame_messages_timer != 0)
|
if (priv->send_frame_messages_timer != 0)
|
||||||
{
|
{
|
||||||
g_source_remove (priv->send_frame_messages_timer);
|
g_source_remove (priv->send_frame_messages_timer);
|
||||||
@@ -412,7 +416,7 @@ meta_window_actor_dispose (GObject *object)
|
|||||||
g_clear_pointer (&priv->unfocused_shadow, meta_shadow_unref);
|
g_clear_pointer (&priv->unfocused_shadow, meta_shadow_unref);
|
||||||
g_clear_pointer (&priv->shadow_shape, meta_window_shape_unref);
|
g_clear_pointer (&priv->shadow_shape, meta_window_shape_unref);
|
||||||
|
|
||||||
compositor->windows = g_list_remove (compositor->windows, (gconstpointer) self);
|
info->windows = g_list_remove (info->windows, (gconstpointer) self);
|
||||||
|
|
||||||
g_clear_object (&priv->window);
|
g_clear_object (&priv->window);
|
||||||
|
|
||||||
@@ -702,6 +706,7 @@ static gboolean
|
|||||||
meta_window_actor_has_shadow (MetaWindowActor *self)
|
meta_window_actor_has_shadow (MetaWindowActor *self)
|
||||||
{
|
{
|
||||||
MetaWindowActorPrivate *priv = self->priv;
|
MetaWindowActorPrivate *priv = self->priv;
|
||||||
|
MetaWindowType window_type = meta_window_get_window_type (priv->window);
|
||||||
|
|
||||||
if (priv->no_shadow)
|
if (priv->no_shadow)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@@ -709,7 +714,7 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
|
|||||||
/* Leaving out shadows for maximized and fullscreen windows is an effeciency
|
/* Leaving out shadows for maximized and fullscreen windows is an effeciency
|
||||||
* win and also prevents the unsightly effect of the shadow of maximized
|
* win and also prevents the unsightly effect of the shadow of maximized
|
||||||
* window appearing on an adjacent window */
|
* window appearing on an adjacent window */
|
||||||
if ((meta_window_get_maximized (priv->window) == META_MAXIMIZE_BOTH) ||
|
if ((meta_window_get_maximized (priv->window) == (META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL)) ||
|
||||||
meta_window_is_fullscreen (priv->window))
|
meta_window_is_fullscreen (priv->window))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
@@ -740,6 +745,25 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
|
|||||||
if (priv->window->override_redirect)
|
if (priv->window->override_redirect)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't put shadow around DND icon windows
|
||||||
|
*/
|
||||||
|
if (window_type == META_WINDOW_DND ||
|
||||||
|
window_type == META_WINDOW_DESKTOP)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (window_type == META_WINDOW_MENU
|
||||||
|
#if 0
|
||||||
|
|| window_type == META_WINDOW_DROPDOWN_MENU
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (window_type == META_WINDOW_TOOLTIP)
|
||||||
|
return TRUE;
|
||||||
|
#endif
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -827,7 +851,8 @@ static void
|
|||||||
queue_send_frame_messages_timeout (MetaWindowActor *self)
|
queue_send_frame_messages_timeout (MetaWindowActor *self)
|
||||||
{
|
{
|
||||||
MetaWindowActorPrivate *priv = self->priv;
|
MetaWindowActorPrivate *priv = self->priv;
|
||||||
MetaDisplay *display = meta_window_get_display (priv->window);
|
MetaScreen *screen = priv->screen;
|
||||||
|
MetaDisplay *display = meta_screen_get_display (screen);
|
||||||
gint64 current_time = meta_compositor_monotonic_time_to_server_time (display, g_get_monotonic_time ());
|
gint64 current_time = meta_compositor_monotonic_time_to_server_time (display, g_get_monotonic_time ());
|
||||||
MetaMonitorManager *monitor_manager = meta_monitor_manager_get ();
|
MetaMonitorManager *monitor_manager = meta_monitor_manager_get ();
|
||||||
MetaWindow *window = priv->window;
|
MetaWindow *window = priv->window;
|
||||||
@@ -939,10 +964,13 @@ start_simple_effect (MetaWindowActor *self,
|
|||||||
gulong event)
|
gulong event)
|
||||||
{
|
{
|
||||||
MetaWindowActorPrivate *priv = self->priv;
|
MetaWindowActorPrivate *priv = self->priv;
|
||||||
MetaCompositor *compositor = priv->compositor;
|
MetaCompScreen *info = meta_screen_get_compositor_data (priv->screen);
|
||||||
gint *counter = NULL;
|
gint *counter = NULL;
|
||||||
gboolean use_freeze_thaw = FALSE;
|
gboolean use_freeze_thaw = FALSE;
|
||||||
|
|
||||||
|
if (!info->plugin_mgr)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
switch (event)
|
switch (event)
|
||||||
{
|
{
|
||||||
case META_PLUGIN_MINIMIZE:
|
case META_PLUGIN_MINIMIZE:
|
||||||
@@ -970,7 +998,9 @@ start_simple_effect (MetaWindowActor *self,
|
|||||||
|
|
||||||
(*counter)++;
|
(*counter)++;
|
||||||
|
|
||||||
if (!meta_plugin_manager_event_simple (compositor->plugin_mgr, self, event))
|
if (!meta_plugin_manager_event_simple (info->plugin_mgr,
|
||||||
|
self,
|
||||||
|
event))
|
||||||
{
|
{
|
||||||
(*counter)--;
|
(*counter)--;
|
||||||
if (use_freeze_thaw)
|
if (use_freeze_thaw)
|
||||||
@@ -1091,11 +1121,15 @@ meta_window_actor_set_unredirected (MetaWindowActor *self,
|
|||||||
void
|
void
|
||||||
meta_window_actor_destroy (MetaWindowActor *self)
|
meta_window_actor_destroy (MetaWindowActor *self)
|
||||||
{
|
{
|
||||||
MetaWindowActorPrivate *priv = self->priv;
|
MetaWindow *window;
|
||||||
MetaWindow *window = priv->window;
|
MetaCompScreen *info;
|
||||||
MetaCompositor *compositor = priv->compositor;
|
MetaWindowActorPrivate *priv;
|
||||||
MetaWindowType window_type = meta_window_get_window_type (window);
|
MetaWindowType window_type;
|
||||||
|
|
||||||
|
priv = self->priv;
|
||||||
|
|
||||||
|
window = priv->window;
|
||||||
|
window_type = meta_window_get_window_type (window);
|
||||||
meta_window_set_compositor_private (window, NULL);
|
meta_window_set_compositor_private (window, NULL);
|
||||||
|
|
||||||
if (priv->send_frame_messages_timer != 0)
|
if (priv->send_frame_messages_timer != 0)
|
||||||
@@ -1108,7 +1142,8 @@ meta_window_actor_destroy (MetaWindowActor *self)
|
|||||||
* We remove the window from internal lookup hashes and thus any other
|
* We remove the window from internal lookup hashes and thus any other
|
||||||
* unmap events etc fail
|
* unmap events etc fail
|
||||||
*/
|
*/
|
||||||
compositor->windows = g_list_remove (compositor->windows, (gconstpointer) self);
|
info = meta_screen_get_compositor_data (priv->screen);
|
||||||
|
info->windows = g_list_remove (info->windows, (gconstpointer) self);
|
||||||
|
|
||||||
if (window_type == META_WINDOW_DROPDOWN_MENU ||
|
if (window_type == META_WINDOW_DROPDOWN_MENU ||
|
||||||
window_type == META_WINDOW_POPUP_MENU ||
|
window_type == META_WINDOW_POPUP_MENU ||
|
||||||
@@ -1169,14 +1204,18 @@ void
|
|||||||
meta_window_actor_show (MetaWindowActor *self,
|
meta_window_actor_show (MetaWindowActor *self,
|
||||||
MetaCompEffect effect)
|
MetaCompEffect effect)
|
||||||
{
|
{
|
||||||
MetaWindowActorPrivate *priv = self->priv;
|
MetaWindowActorPrivate *priv;
|
||||||
MetaCompositor *compositor = priv->compositor;
|
MetaCompScreen *info;
|
||||||
gulong event = 0;
|
gulong event;
|
||||||
|
|
||||||
|
priv = self->priv;
|
||||||
|
info = meta_screen_get_compositor_data (priv->screen);
|
||||||
|
|
||||||
g_return_if_fail (!priv->visible);
|
g_return_if_fail (!priv->visible);
|
||||||
|
|
||||||
self->priv->visible = TRUE;
|
self->priv->visible = TRUE;
|
||||||
|
|
||||||
|
event = 0;
|
||||||
switch (effect)
|
switch (effect)
|
||||||
{
|
{
|
||||||
case META_COMP_EFFECT_CREATE:
|
case META_COMP_EFFECT_CREATE:
|
||||||
@@ -1193,7 +1232,7 @@ meta_window_actor_show (MetaWindowActor *self,
|
|||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compositor->switch_workspace_in_progress ||
|
if (info->switch_workspace_in_progress ||
|
||||||
event == 0 ||
|
event == 0 ||
|
||||||
!start_simple_effect (self, event))
|
!start_simple_effect (self, event))
|
||||||
{
|
{
|
||||||
@@ -1205,9 +1244,12 @@ void
|
|||||||
meta_window_actor_hide (MetaWindowActor *self,
|
meta_window_actor_hide (MetaWindowActor *self,
|
||||||
MetaCompEffect effect)
|
MetaCompEffect effect)
|
||||||
{
|
{
|
||||||
MetaWindowActorPrivate *priv = self->priv;
|
MetaWindowActorPrivate *priv;
|
||||||
MetaCompositor *compositor = priv->compositor;
|
MetaCompScreen *info;
|
||||||
gulong event = 0;
|
gulong event;
|
||||||
|
|
||||||
|
priv = self->priv;
|
||||||
|
info = meta_screen_get_compositor_data (priv->screen);
|
||||||
|
|
||||||
g_return_if_fail (priv->visible);
|
g_return_if_fail (priv->visible);
|
||||||
|
|
||||||
@@ -1217,9 +1259,10 @@ meta_window_actor_hide (MetaWindowActor *self,
|
|||||||
* hold off on hiding the window, and do it after the workspace
|
* hold off on hiding the window, and do it after the workspace
|
||||||
* switch completes
|
* switch completes
|
||||||
*/
|
*/
|
||||||
if (compositor->switch_workspace_in_progress)
|
if (info->switch_workspace_in_progress)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
event = 0;
|
||||||
switch (effect)
|
switch (effect)
|
||||||
{
|
{
|
||||||
case META_COMP_EFFECT_DESTROY:
|
case META_COMP_EFFECT_DESTROY:
|
||||||
@@ -1245,8 +1288,7 @@ meta_window_actor_maximize (MetaWindowActor *self,
|
|||||||
MetaRectangle *old_rect,
|
MetaRectangle *old_rect,
|
||||||
MetaRectangle *new_rect)
|
MetaRectangle *new_rect)
|
||||||
{
|
{
|
||||||
MetaWindowActorPrivate *priv = self->priv;
|
MetaCompScreen *info = meta_screen_get_compositor_data (self->priv->screen);
|
||||||
MetaCompositor *compositor = priv->compositor;
|
|
||||||
|
|
||||||
/* The window has already been resized (in order to compute new_rect),
|
/* The window has already been resized (in order to compute new_rect),
|
||||||
* which by side effect caused the actor to be resized. Restore it to the
|
* which by side effect caused the actor to be resized. Restore it to the
|
||||||
@@ -1257,7 +1299,8 @@ meta_window_actor_maximize (MetaWindowActor *self,
|
|||||||
self->priv->maximize_in_progress++;
|
self->priv->maximize_in_progress++;
|
||||||
meta_window_actor_freeze (self);
|
meta_window_actor_freeze (self);
|
||||||
|
|
||||||
if (!meta_plugin_manager_event_maximize (compositor->plugin_mgr,
|
if (!info->plugin_mgr ||
|
||||||
|
!meta_plugin_manager_event_maximize (info->plugin_mgr,
|
||||||
self,
|
self,
|
||||||
META_PLUGIN_MAXIMIZE,
|
META_PLUGIN_MAXIMIZE,
|
||||||
new_rect->x, new_rect->y,
|
new_rect->x, new_rect->y,
|
||||||
@@ -1274,8 +1317,7 @@ meta_window_actor_unmaximize (MetaWindowActor *self,
|
|||||||
MetaRectangle *old_rect,
|
MetaRectangle *old_rect,
|
||||||
MetaRectangle *new_rect)
|
MetaRectangle *new_rect)
|
||||||
{
|
{
|
||||||
MetaWindowActorPrivate *priv = self->priv;
|
MetaCompScreen *info = meta_screen_get_compositor_data (self->priv->screen);
|
||||||
MetaCompositor *compositor = priv->compositor;
|
|
||||||
|
|
||||||
/* The window has already been resized (in order to compute new_rect),
|
/* The window has already been resized (in order to compute new_rect),
|
||||||
* which by side effect caused the actor to be resized. Restore it to the
|
* which by side effect caused the actor to be resized. Restore it to the
|
||||||
@@ -1286,7 +1328,8 @@ meta_window_actor_unmaximize (MetaWindowActor *self,
|
|||||||
self->priv->unmaximize_in_progress++;
|
self->priv->unmaximize_in_progress++;
|
||||||
meta_window_actor_freeze (self);
|
meta_window_actor_freeze (self);
|
||||||
|
|
||||||
if (!meta_plugin_manager_event_maximize (compositor->plugin_mgr,
|
if (!info->plugin_mgr ||
|
||||||
|
!meta_plugin_manager_event_maximize (info->plugin_mgr,
|
||||||
self,
|
self,
|
||||||
META_PLUGIN_UNMAXIMIZE,
|
META_PLUGIN_UNMAXIMIZE,
|
||||||
new_rect->x, new_rect->y,
|
new_rect->x, new_rect->y,
|
||||||
@@ -1300,8 +1343,8 @@ meta_window_actor_unmaximize (MetaWindowActor *self,
|
|||||||
MetaWindowActor *
|
MetaWindowActor *
|
||||||
meta_window_actor_new (MetaWindow *window)
|
meta_window_actor_new (MetaWindow *window)
|
||||||
{
|
{
|
||||||
MetaDisplay *display = meta_window_get_display (window);
|
MetaScreen *screen = meta_window_get_screen (window);
|
||||||
MetaCompositor *compositor = display->compositor;
|
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||||
MetaWindowActor *self;
|
MetaWindowActor *self;
|
||||||
MetaWindowActorPrivate *priv;
|
MetaWindowActorPrivate *priv;
|
||||||
ClutterActor *window_group;
|
ClutterActor *window_group;
|
||||||
@@ -1326,9 +1369,9 @@ meta_window_actor_new (MetaWindow *window)
|
|||||||
meta_window_set_compositor_private (window, G_OBJECT (self));
|
meta_window_set_compositor_private (window, G_OBJECT (self));
|
||||||
|
|
||||||
if (window->layer == META_LAYER_OVERRIDE_REDIRECT)
|
if (window->layer == META_LAYER_OVERRIDE_REDIRECT)
|
||||||
window_group = compositor->top_window_group;
|
window_group = info->top_window_group;
|
||||||
else
|
else
|
||||||
window_group = compositor->window_group;
|
window_group = info->window_group;
|
||||||
|
|
||||||
clutter_actor_add_child (window_group, CLUTTER_ACTOR (self));
|
clutter_actor_add_child (window_group, CLUTTER_ACTOR (self));
|
||||||
|
|
||||||
@@ -1337,7 +1380,7 @@ meta_window_actor_new (MetaWindow *window)
|
|||||||
/* Initial position in the stack is arbitrary; stacking will be synced
|
/* Initial position in the stack is arbitrary; stacking will be synced
|
||||||
* before we first paint.
|
* before we first paint.
|
||||||
*/
|
*/
|
||||||
compositor->windows = g_list_append (compositor->windows, self);
|
info->windows = g_list_append (info->windows, self);
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@@ -1428,7 +1471,6 @@ meta_window_actor_cull_out (MetaCullable *cullable,
|
|||||||
{
|
{
|
||||||
MetaWindowActor *self = META_WINDOW_ACTOR (cullable);
|
MetaWindowActor *self = META_WINDOW_ACTOR (cullable);
|
||||||
|
|
||||||
meta_cullable_cull_out_children (cullable, unobscured_region, clip_region);
|
|
||||||
meta_window_actor_set_clip_region_beneath (self, clip_region);
|
meta_window_actor_set_clip_region_beneath (self, clip_region);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1671,25 +1713,22 @@ build_and_scan_frame_mask (MetaWindowActor *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
meta_shaped_texture_set_mask_texture (stex, mask_texture);
|
meta_shaped_texture_set_mask_texture (stex, mask_texture);
|
||||||
if (mask_texture)
|
cogl_object_unref (mask_texture);
|
||||||
cogl_object_unref (mask_texture);
|
|
||||||
|
|
||||||
g_free (mask_data);
|
g_free (mask_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_window_actor_update_shape_region (MetaWindowActor *self)
|
meta_window_actor_update_shape_region (MetaWindowActor *self,
|
||||||
|
cairo_rectangle_int_t *client_area)
|
||||||
{
|
{
|
||||||
MetaWindowActorPrivate *priv = self->priv;
|
MetaWindowActorPrivate *priv = self->priv;
|
||||||
cairo_region_t *region = NULL;
|
cairo_region_t *region = NULL;
|
||||||
cairo_rectangle_int_t client_area;
|
|
||||||
|
|
||||||
meta_window_get_client_area_rect (priv->window, &client_area);
|
|
||||||
|
|
||||||
if (priv->window->frame != NULL && priv->window->shape_region != NULL)
|
if (priv->window->frame != NULL && priv->window->shape_region != NULL)
|
||||||
{
|
{
|
||||||
region = cairo_region_copy (priv->window->shape_region);
|
region = cairo_region_copy (priv->window->shape_region);
|
||||||
cairo_region_translate (region, client_area.x, client_area.y);
|
cairo_region_translate (region, client_area->x, client_area->y);
|
||||||
}
|
}
|
||||||
else if (priv->window->shape_region != NULL)
|
else if (priv->window->shape_region != NULL)
|
||||||
{
|
{
|
||||||
@@ -1700,11 +1739,11 @@ meta_window_actor_update_shape_region (MetaWindowActor *self)
|
|||||||
/* If we don't have a shape on the server, that means that
|
/* If we don't have a shape on the server, that means that
|
||||||
* we have an implicit shape of one rectangle covering the
|
* we have an implicit shape of one rectangle covering the
|
||||||
* entire window. */
|
* entire window. */
|
||||||
region = cairo_region_create_rectangle (&client_area);
|
region = cairo_region_create_rectangle (client_area);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((priv->window->shape_region != NULL) || (priv->window->frame != NULL))
|
if ((priv->window->shape_region != NULL) || (priv->window->frame != NULL))
|
||||||
build_and_scan_frame_mask (self, &client_area, region);
|
build_and_scan_frame_mask (self, client_area, region);
|
||||||
|
|
||||||
g_clear_pointer (&priv->shape_region, cairo_region_destroy);
|
g_clear_pointer (&priv->shape_region, cairo_region_destroy);
|
||||||
priv->shape_region = region;
|
priv->shape_region = region;
|
||||||
@@ -1715,23 +1754,41 @@ meta_window_actor_update_shape_region (MetaWindowActor *self)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_window_actor_update_input_region (MetaWindowActor *self)
|
meta_window_actor_update_input_region (MetaWindowActor *self,
|
||||||
|
cairo_rectangle_int_t *client_area)
|
||||||
{
|
{
|
||||||
MetaWindowActorPrivate *priv = self->priv;
|
MetaWindowActorPrivate *priv = self->priv;
|
||||||
MetaWindow *window = priv->window;
|
cairo_region_t *region = NULL;
|
||||||
cairo_region_t *region;
|
|
||||||
|
|
||||||
if (window->shape_region && window->input_region)
|
if (priv->window->frame != NULL)
|
||||||
{
|
{
|
||||||
region = cairo_region_copy (window->shape_region);
|
region = meta_frame_get_frame_bounds (priv->window->frame);
|
||||||
cairo_region_intersect (region, window->input_region);
|
/* client area is in client window coordinates, so translate the
|
||||||
|
* input region into that coordinate system and back */
|
||||||
|
cairo_region_translate (region, -client_area->x, -client_area->y);
|
||||||
|
cairo_region_union_rectangle (region, client_area);
|
||||||
|
cairo_region_translate (region, client_area->x, client_area->y);
|
||||||
|
}
|
||||||
|
else if (priv->window->shape_region != NULL ||
|
||||||
|
priv->window->input_region != NULL)
|
||||||
|
{
|
||||||
|
if (priv->window->shape_region != NULL)
|
||||||
|
{
|
||||||
|
region = cairo_region_copy (priv->window->shape_region);
|
||||||
|
|
||||||
|
if (priv->window->input_region != NULL)
|
||||||
|
cairo_region_intersect (region, priv->window->input_region);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
region = cairo_region_reference (priv->window->input_region);
|
||||||
}
|
}
|
||||||
else if (window->shape_region)
|
|
||||||
region = cairo_region_reference (window->shape_region);
|
|
||||||
else if (window->input_region)
|
|
||||||
region = cairo_region_reference (window->input_region);
|
|
||||||
else
|
else
|
||||||
region = NULL;
|
{
|
||||||
|
/* If we don't have a shape on the server, that means that
|
||||||
|
* we have an implicit shape of one rectangle covering the
|
||||||
|
* entire window. */
|
||||||
|
region = cairo_region_create_rectangle (client_area);
|
||||||
|
}
|
||||||
|
|
||||||
meta_surface_actor_set_input_region (priv->surface, region);
|
meta_surface_actor_set_input_region (priv->surface, region);
|
||||||
cairo_region_destroy (region);
|
cairo_region_destroy (region);
|
||||||
@@ -1746,9 +1803,9 @@ meta_window_actor_update_opaque_region (MetaWindowActor *self)
|
|||||||
|
|
||||||
if (argb32 && priv->window->opaque_region != NULL)
|
if (argb32 && priv->window->opaque_region != NULL)
|
||||||
{
|
{
|
||||||
cairo_rectangle_int_t client_area;
|
MetaFrameBorders borders;
|
||||||
|
|
||||||
meta_window_get_client_area_rect (priv->window, &client_area);
|
meta_frame_calc_borders (priv->window->frame, &borders);
|
||||||
|
|
||||||
/* The opaque region is defined to be a part of the
|
/* The opaque region is defined to be a part of the
|
||||||
* window which ARGB32 will always paint with opaque
|
* window which ARGB32 will always paint with opaque
|
||||||
@@ -1761,7 +1818,7 @@ meta_window_actor_update_opaque_region (MetaWindowActor *self)
|
|||||||
* case, graphical glitches will occur.
|
* case, graphical glitches will occur.
|
||||||
*/
|
*/
|
||||||
opaque_region = cairo_region_copy (priv->window->opaque_region);
|
opaque_region = cairo_region_copy (priv->window->opaque_region);
|
||||||
cairo_region_translate (opaque_region, client_area.x, client_area.y);
|
cairo_region_translate (opaque_region, borders.total.left, borders.total.top);
|
||||||
cairo_region_intersect (opaque_region, priv->shape_region);
|
cairo_region_intersect (opaque_region, priv->shape_region);
|
||||||
}
|
}
|
||||||
else if (argb32)
|
else if (argb32)
|
||||||
@@ -1777,15 +1834,27 @@ static void
|
|||||||
check_needs_reshape (MetaWindowActor *self)
|
check_needs_reshape (MetaWindowActor *self)
|
||||||
{
|
{
|
||||||
MetaWindowActorPrivate *priv = self->priv;
|
MetaWindowActorPrivate *priv = self->priv;
|
||||||
|
MetaFrameBorders borders;
|
||||||
|
cairo_rectangle_int_t client_area;
|
||||||
|
|
||||||
if (!priv->needs_reshape)
|
if (!priv->needs_reshape)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
meta_window_actor_update_shape_region (self);
|
meta_frame_calc_borders (priv->window->frame, &borders);
|
||||||
|
|
||||||
|
client_area.x = borders.total.left;
|
||||||
|
client_area.y = borders.total.top;
|
||||||
|
client_area.width = priv->window->rect.width;
|
||||||
|
if (priv->window->shaded)
|
||||||
|
client_area.height = 0;
|
||||||
|
else
|
||||||
|
client_area.height = priv->window->rect.height;
|
||||||
|
|
||||||
|
meta_window_actor_update_shape_region (self, &client_area);
|
||||||
|
|
||||||
if (priv->window->client_type == META_WINDOW_CLIENT_TYPE_X11)
|
if (priv->window->client_type == META_WINDOW_CLIENT_TYPE_X11)
|
||||||
{
|
{
|
||||||
meta_window_actor_update_input_region (self);
|
meta_window_actor_update_input_region (self, &client_area);
|
||||||
meta_window_actor_update_opaque_region (self);
|
meta_window_actor_update_opaque_region (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1853,7 +1922,8 @@ static void
|
|||||||
do_send_frame_drawn (MetaWindowActor *self, FrameData *frame)
|
do_send_frame_drawn (MetaWindowActor *self, FrameData *frame)
|
||||||
{
|
{
|
||||||
MetaWindowActorPrivate *priv = self->priv;
|
MetaWindowActorPrivate *priv = self->priv;
|
||||||
MetaDisplay *display = meta_window_get_display (priv->window);
|
MetaScreen *screen = priv->screen;
|
||||||
|
MetaDisplay *display = meta_screen_get_display (screen);
|
||||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||||
|
|
||||||
XClientMessageEvent ev = { 0, };
|
XClientMessageEvent ev = { 0, };
|
||||||
@@ -1905,7 +1975,7 @@ do_send_frame_timings (MetaWindowActor *self,
|
|||||||
gint64 presentation_time)
|
gint64 presentation_time)
|
||||||
{
|
{
|
||||||
MetaWindowActorPrivate *priv = self->priv;
|
MetaWindowActorPrivate *priv = self->priv;
|
||||||
MetaDisplay *display = meta_window_get_display (priv->window);
|
MetaDisplay *display = meta_screen_get_display (priv->screen);
|
||||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||||
|
|
||||||
XClientMessageEvent ev = { 0, };
|
XClientMessageEvent ev = { 0, };
|
||||||
|
|||||||
110
src/core/bell.c
110
src/core/bell.c
@@ -58,6 +58,88 @@
|
|||||||
#include <canberra-gtk.h>
|
#include <canberra-gtk.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* bell_flash_screen:
|
||||||
|
* @display: The display which owns the screen (rather redundant)
|
||||||
|
* @screen: The screen to flash
|
||||||
|
*
|
||||||
|
* Flashes one entire screen. This is done by making a window the size of the
|
||||||
|
* whole screen (or reusing the old one, if it's still around), mapping it,
|
||||||
|
* painting it white and then black, and then unmapping it. We set saveunder so
|
||||||
|
* that all the windows behind it come back immediately.
|
||||||
|
*
|
||||||
|
* Unlike frame flashes, we don't do fullscreen flashes with a timeout; rather,
|
||||||
|
* we do them in one go, because we don't have to rely on the theme code
|
||||||
|
* redrawing the frame for us in order to do the flash.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Bug: The way I read it, this appears not to do the flash
|
||||||
|
* the first time we flash a particular display. Am I wrong?
|
||||||
|
*
|
||||||
|
* Bug: This appears to destroy our current XSync status.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
bell_flash_screen (MetaDisplay *display,
|
||||||
|
MetaScreen *screen)
|
||||||
|
{
|
||||||
|
Window root = screen->xroot;
|
||||||
|
int width = screen->rect.width;
|
||||||
|
int height = screen->rect.height;
|
||||||
|
|
||||||
|
if (screen->flash_window == None)
|
||||||
|
{
|
||||||
|
Visual *visual = (Visual *)CopyFromParent;
|
||||||
|
XSetWindowAttributes xswa;
|
||||||
|
int depth = CopyFromParent;
|
||||||
|
xswa.save_under = True;
|
||||||
|
xswa.override_redirect = True;
|
||||||
|
/*
|
||||||
|
* TODO: use XGetVisualInfo and determine which is an
|
||||||
|
* overlay, if one is present, and use the Overlay visual
|
||||||
|
* for this window (for performance reasons).
|
||||||
|
* Not sure how to tell this yet...
|
||||||
|
*/
|
||||||
|
screen->flash_window = XCreateWindow (display->xdisplay, root,
|
||||||
|
0, 0, width, height,
|
||||||
|
0, depth,
|
||||||
|
InputOutput,
|
||||||
|
visual,
|
||||||
|
/* note: XSun doesn't like SaveUnder here */
|
||||||
|
CWSaveUnder | CWOverrideRedirect,
|
||||||
|
&xswa);
|
||||||
|
XSelectInput (display->xdisplay, screen->flash_window, ExposureMask);
|
||||||
|
XMapWindow (display->xdisplay, screen->flash_window);
|
||||||
|
XSync (display->xdisplay, False);
|
||||||
|
XFlush (display->xdisplay);
|
||||||
|
XUnmapWindow (display->xdisplay, screen->flash_window);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* just draw something in the window */
|
||||||
|
GC gc = XCreateGC (display->xdisplay, screen->flash_window, 0, NULL);
|
||||||
|
XMapWindow (display->xdisplay, screen->flash_window);
|
||||||
|
XSetForeground (display->xdisplay, gc,
|
||||||
|
WhitePixel (display->xdisplay,
|
||||||
|
XScreenNumberOfScreen (screen->xscreen)));
|
||||||
|
XFillRectangle (display->xdisplay, screen->flash_window, gc,
|
||||||
|
0, 0, width, height);
|
||||||
|
XSetForeground (display->xdisplay, gc,
|
||||||
|
BlackPixel (display->xdisplay,
|
||||||
|
XScreenNumberOfScreen (screen->xscreen)));
|
||||||
|
XFillRectangle (display->xdisplay, screen->flash_window, gc,
|
||||||
|
0, 0, width, height);
|
||||||
|
XFlush (display->xdisplay);
|
||||||
|
XSync (display->xdisplay, False);
|
||||||
|
XUnmapWindow (display->xdisplay, screen->flash_window);
|
||||||
|
XFreeGC (display->xdisplay, gc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (meta_prefs_get_focus_mode () != G_DESKTOP_FOCUS_MODE_CLICK &&
|
||||||
|
!display->mouse_mode)
|
||||||
|
meta_display_increment_focus_sentinel (display);
|
||||||
|
XFlush (display->xdisplay);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* bell_flash_fullscreen:
|
* bell_flash_fullscreen:
|
||||||
* @display: The display the event came in on
|
* @display: The display the event came in on
|
||||||
@@ -74,8 +156,34 @@ static void
|
|||||||
bell_flash_fullscreen (MetaDisplay *display,
|
bell_flash_fullscreen (MetaDisplay *display,
|
||||||
XkbAnyEvent *xkb_ev)
|
XkbAnyEvent *xkb_ev)
|
||||||
{
|
{
|
||||||
|
XkbBellNotifyEvent *xkb_bell_ev = (XkbBellNotifyEvent *) xkb_ev;
|
||||||
|
MetaScreen *screen;
|
||||||
|
|
||||||
g_assert (xkb_ev->xkb_type == XkbBellNotify);
|
g_assert (xkb_ev->xkb_type == XkbBellNotify);
|
||||||
meta_compositor_flash_screen (display->compositor, display->screen);
|
if (xkb_bell_ev->window != None)
|
||||||
|
{
|
||||||
|
screen = meta_display_screen_for_xwindow (display, xkb_bell_ev->window);
|
||||||
|
if (screen)
|
||||||
|
{
|
||||||
|
if (display->compositor)
|
||||||
|
meta_compositor_flash_screen (display->compositor, screen);
|
||||||
|
else
|
||||||
|
bell_flash_screen (display, screen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GSList *screen_list = display->screens;
|
||||||
|
while (screen_list)
|
||||||
|
{
|
||||||
|
screen = (MetaScreen *) screen_list->data;
|
||||||
|
if (display->compositor)
|
||||||
|
meta_compositor_flash_screen (display->compositor, screen);
|
||||||
|
else
|
||||||
|
bell_flash_screen (display, screen);
|
||||||
|
screen_list = screen_list->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -425,9 +425,8 @@ setup_constraint_info (ConstraintInfo *info,
|
|||||||
* the monitor.
|
* the monitor.
|
||||||
*/
|
*/
|
||||||
if (meta_prefs_get_force_fullscreen() &&
|
if (meta_prefs_get_force_fullscreen() &&
|
||||||
window->client_type != META_WINDOW_CLIENT_TYPE_WAYLAND &&
|
|
||||||
!window->hide_titlebar_when_maximized &&
|
!window->hide_titlebar_when_maximized &&
|
||||||
(window->decorated || !meta_window_is_client_decorated (window)) &&
|
window->decorated &&
|
||||||
meta_rectangle_equal (new, &monitor_info->rect) &&
|
meta_rectangle_equal (new, &monitor_info->rect) &&
|
||||||
window->has_fullscreen_func &&
|
window->has_fullscreen_func &&
|
||||||
!window->fullscreen)
|
!window->fullscreen)
|
||||||
@@ -492,17 +491,12 @@ place_window_if_needed(MetaWindow *window,
|
|||||||
!window->minimized &&
|
!window->minimized &&
|
||||||
!window->fullscreen)
|
!window->fullscreen)
|
||||||
{
|
{
|
||||||
MetaRectangle orig_rect;
|
|
||||||
MetaRectangle placed_rect;
|
MetaRectangle placed_rect;
|
||||||
MetaWorkspace *cur_workspace;
|
MetaWorkspace *cur_workspace;
|
||||||
const MetaMonitorInfo *monitor_info;
|
const MetaMonitorInfo *monitor_info;
|
||||||
|
|
||||||
meta_window_get_frame_rect (window, &placed_rect);
|
meta_window_get_frame_rect (window, &placed_rect);
|
||||||
|
meta_window_place (window, info->orig.x, info->orig.y,
|
||||||
orig_rect = info->orig;
|
|
||||||
extend_by_frame (window, &orig_rect);
|
|
||||||
|
|
||||||
meta_window_place (window, orig_rect.x, orig_rect.y,
|
|
||||||
&placed_rect.x, &placed_rect.y);
|
&placed_rect.x, &placed_rect.y);
|
||||||
did_placement = TRUE;
|
did_placement = TRUE;
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,16 @@
|
|||||||
#include "window-private.h"
|
#include "window-private.h"
|
||||||
#include "frame.h"
|
#include "frame.h"
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
META_IS_CONFIGURE_REQUEST = 1 << 0,
|
||||||
|
META_DO_GRAVITY_ADJUST = 1 << 1,
|
||||||
|
META_IS_USER_ACTION = 1 << 2,
|
||||||
|
META_IS_MOVE_ACTION = 1 << 3,
|
||||||
|
META_IS_RESIZE_ACTION = 1 << 4,
|
||||||
|
META_IS_WAYLAND_RESIZE = 1 << 5
|
||||||
|
} MetaMoveResizeFlags;
|
||||||
|
|
||||||
void meta_window_constrain (MetaWindow *window,
|
void meta_window_constrain (MetaWindow *window,
|
||||||
MetaMoveResizeFlags flags,
|
MetaMoveResizeFlags flags,
|
||||||
int resize_gravity,
|
int resize_gravity,
|
||||||
|
|||||||
@@ -274,7 +274,7 @@ meta_core_lower_beneath_grab_window (Display *xdisplay,
|
|||||||
MetaStackWindow stack_sibling;
|
MetaStackWindow stack_sibling;
|
||||||
|
|
||||||
display = meta_display_for_x_display (xdisplay);
|
display = meta_display_for_x_display (xdisplay);
|
||||||
screen = display->screen;
|
screen = meta_display_screen_for_xwindow (display, xwindow);
|
||||||
grab_window = display->grab_window;
|
grab_window = display->grab_window;
|
||||||
|
|
||||||
if (grab_window == NULL)
|
if (grab_window == NULL)
|
||||||
@@ -328,7 +328,8 @@ meta_core_maximize (Display *xdisplay,
|
|||||||
if (meta_prefs_get_raise_on_click ())
|
if (meta_prefs_get_raise_on_click ())
|
||||||
meta_window_raise (window);
|
meta_window_raise (window);
|
||||||
|
|
||||||
meta_window_maximize (window, META_MAXIMIZE_BOTH);
|
meta_window_maximize (window,
|
||||||
|
META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -341,9 +342,11 @@ meta_core_toggle_maximize_vertically (Display *xdisplay,
|
|||||||
meta_window_raise (window);
|
meta_window_raise (window);
|
||||||
|
|
||||||
if (META_WINDOW_MAXIMIZED_VERTICALLY (window))
|
if (META_WINDOW_MAXIMIZED_VERTICALLY (window))
|
||||||
meta_window_unmaximize (window, META_MAXIMIZE_VERTICAL);
|
meta_window_unmaximize (window,
|
||||||
|
META_MAXIMIZE_VERTICAL);
|
||||||
else
|
else
|
||||||
meta_window_maximize (window, META_MAXIMIZE_VERTICAL);
|
meta_window_maximize (window,
|
||||||
|
META_MAXIMIZE_VERTICAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -356,9 +359,11 @@ meta_core_toggle_maximize_horizontally (Display *xdisplay,
|
|||||||
meta_window_raise (window);
|
meta_window_raise (window);
|
||||||
|
|
||||||
if (META_WINDOW_MAXIMIZED_HORIZONTALLY (window))
|
if (META_WINDOW_MAXIMIZED_HORIZONTALLY (window))
|
||||||
meta_window_unmaximize (window, META_MAXIMIZE_HORIZONTAL);
|
meta_window_unmaximize (window,
|
||||||
|
META_MAXIMIZE_HORIZONTAL);
|
||||||
else
|
else
|
||||||
meta_window_maximize (window, META_MAXIMIZE_HORIZONTAL);
|
meta_window_maximize (window,
|
||||||
|
META_MAXIMIZE_HORIZONTAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -371,9 +376,11 @@ meta_core_toggle_maximize (Display *xdisplay,
|
|||||||
meta_window_raise (window);
|
meta_window_raise (window);
|
||||||
|
|
||||||
if (META_WINDOW_MAXIMIZED (window))
|
if (META_WINDOW_MAXIMIZED (window))
|
||||||
meta_window_unmaximize (window, META_MAXIMIZE_BOTH);
|
meta_window_unmaximize (window,
|
||||||
|
META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
|
||||||
else
|
else
|
||||||
meta_window_maximize (window, META_MAXIMIZE_BOTH);
|
meta_window_maximize (window,
|
||||||
|
META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -385,7 +392,8 @@ meta_core_unmaximize (Display *xdisplay,
|
|||||||
if (meta_prefs_get_raise_on_click ())
|
if (meta_prefs_get_raise_on_click ())
|
||||||
meta_window_raise (window);
|
meta_window_raise (window);
|
||||||
|
|
||||||
meta_window_unmaximize (window, META_MAXIMIZE_BOTH);
|
meta_window_unmaximize (window,
|
||||||
|
META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -603,10 +611,13 @@ meta_core_get_workspace_name_with_index (Display *xdisplay,
|
|||||||
int index)
|
int index)
|
||||||
{
|
{
|
||||||
MetaDisplay *display;
|
MetaDisplay *display;
|
||||||
|
MetaScreen *screen;
|
||||||
MetaWorkspace *workspace;
|
MetaWorkspace *workspace;
|
||||||
|
|
||||||
display = meta_display_for_x_display (xdisplay);
|
display = meta_display_for_x_display (xdisplay);
|
||||||
workspace = meta_screen_get_workspace_by_index (display->screen, index);
|
screen = meta_display_screen_for_root (display, xroot);
|
||||||
|
g_assert (screen != NULL);
|
||||||
|
workspace = meta_screen_get_workspace_by_index (screen, index);
|
||||||
return workspace ? meta_workspace_get_name (workspace) : NULL;
|
return workspace ? meta_workspace_get_name (workspace) : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -627,7 +638,7 @@ meta_core_begin_grab_op (Display *xdisplay,
|
|||||||
MetaScreen *screen;
|
MetaScreen *screen;
|
||||||
|
|
||||||
display = meta_display_for_x_display (xdisplay);
|
display = meta_display_for_x_display (xdisplay);
|
||||||
screen = display->screen;
|
screen = meta_display_screen_for_xwindow (display, frame_xwindow);
|
||||||
|
|
||||||
g_assert (screen != NULL);
|
g_assert (screen != NULL);
|
||||||
|
|
||||||
@@ -667,6 +678,10 @@ meta_core_get_grab_frame (Display *xdisplay)
|
|||||||
display = meta_display_for_x_display (xdisplay);
|
display = meta_display_for_x_display (xdisplay);
|
||||||
|
|
||||||
g_assert (display != NULL);
|
g_assert (display != NULL);
|
||||||
|
g_assert (display->grab_op == META_GRAB_OP_NONE ||
|
||||||
|
display->grab_screen != NULL);
|
||||||
|
g_assert (display->grab_op == META_GRAB_OP_NONE ||
|
||||||
|
display->grab_screen->display->xdisplay == xdisplay);
|
||||||
|
|
||||||
if (display->grab_op != META_GRAB_OP_NONE &&
|
if (display->grab_op != META_GRAB_OP_NONE &&
|
||||||
display->grab_window &&
|
display->grab_window &&
|
||||||
@@ -711,6 +726,16 @@ meta_core_set_screen_cursor (Display *xdisplay,
|
|||||||
meta_frame_set_screen_cursor (window->frame, cursor);
|
meta_frame_set_screen_cursor (window->frame, cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_core_increment_event_serial (Display *xdisplay)
|
||||||
|
{
|
||||||
|
MetaDisplay *display;
|
||||||
|
|
||||||
|
display = meta_display_for_x_display (xdisplay);
|
||||||
|
|
||||||
|
meta_display_increment_event_serial (display);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_invalidate_default_icons (void)
|
meta_invalidate_default_icons (void)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -193,6 +193,12 @@ void meta_core_set_screen_cursor (Display *xdisplay,
|
|||||||
Window frame_on_screen,
|
Window frame_on_screen,
|
||||||
MetaCursor cursor);
|
MetaCursor cursor);
|
||||||
|
|
||||||
|
/* Used because we ignore EnterNotify when a window is unmapped that
|
||||||
|
* really shouldn't cause focus changes, by comparing the event serial
|
||||||
|
* of the EnterNotify and the UnmapNotify.
|
||||||
|
*/
|
||||||
|
void meta_core_increment_event_serial (Display *display);
|
||||||
|
|
||||||
void meta_invalidate_default_icons (void);
|
void meta_invalidate_default_icons (void);
|
||||||
|
|
||||||
void meta_core_add_old_event_mask (Display *xdisplay,
|
void meta_core_add_old_event_mask (Display *xdisplay,
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "wayland/meta-wayland-surface.h"
|
#include "meta-wayland-surface.h"
|
||||||
|
|
||||||
static void meta_window_present_delete_dialog (MetaWindow *window,
|
static void meta_window_present_delete_dialog (MetaWindow *window,
|
||||||
guint32 timestamp);
|
guint32 timestamp);
|
||||||
@@ -143,7 +143,31 @@ void
|
|||||||
meta_window_delete (MetaWindow *window,
|
meta_window_delete (MetaWindow *window,
|
||||||
guint32 timestamp)
|
guint32 timestamp)
|
||||||
{
|
{
|
||||||
META_WINDOW_GET_CLASS (window)->delete (window, timestamp);
|
if (window->client_type == META_WINDOW_CLIENT_TYPE_X11)
|
||||||
|
{
|
||||||
|
meta_error_trap_push (window->display);
|
||||||
|
if (window->delete_window)
|
||||||
|
{
|
||||||
|
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||||
|
"Deleting %s with delete_window request\n",
|
||||||
|
window->desc);
|
||||||
|
meta_window_send_icccm_message (window,
|
||||||
|
window->display->atom_WM_DELETE_WINDOW,
|
||||||
|
timestamp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||||
|
"Deleting %s with explicit kill\n",
|
||||||
|
window->desc);
|
||||||
|
XKillClient (window->display->xdisplay, window->xwindow);
|
||||||
|
}
|
||||||
|
meta_error_trap_pop (window->display);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
meta_wayland_surface_delete (window->surface);
|
||||||
|
}
|
||||||
|
|
||||||
meta_window_check_alive (window, timestamp);
|
meta_window_check_alive (window, timestamp);
|
||||||
|
|
||||||
@@ -176,10 +200,33 @@ meta_window_delete (MetaWindow *window,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_window_kill (MetaWindow *window)
|
meta_window_kill (MetaWindow *window)
|
||||||
{
|
{
|
||||||
META_WINDOW_GET_CLASS (window)->kill (window);
|
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||||
|
"Killing %s brutally\n",
|
||||||
|
window->desc);
|
||||||
|
|
||||||
|
if (!meta_window_is_remote (window) &&
|
||||||
|
window->net_wm_pid > 0)
|
||||||
|
{
|
||||||
|
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||||
|
"Killing %s with kill()\n",
|
||||||
|
window->desc);
|
||||||
|
|
||||||
|
if (kill (window->net_wm_pid, 9) < 0)
|
||||||
|
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||||
|
"Failed to signal %s: %s\n",
|
||||||
|
window->desc, strerror (errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||||
|
"Disconnecting %s with XKillClient()\n",
|
||||||
|
window->desc);
|
||||||
|
meta_error_trap_push (window->display);
|
||||||
|
XKillClient (window->display->xdisplay, window->xwindow);
|
||||||
|
meta_error_trap_pop (window->display);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -214,7 +261,8 @@ meta_window_present_delete_dialog (MetaWindow *window, guint32 timestamp)
|
|||||||
{
|
{
|
||||||
MetaWindow *w = tmp->data;
|
MetaWindow *w = tmp->data;
|
||||||
|
|
||||||
if (w->transient_for == window && w->res_class &&
|
if (w->xtransient_for == window->xwindow &&
|
||||||
|
w->res_class &&
|
||||||
g_ascii_strcasecmp (w->res_class, "mutter-dialog") == 0)
|
g_ascii_strcasecmp (w->res_class, "mutter-dialog") == 0)
|
||||||
{
|
{
|
||||||
meta_window_activate (w, timestamp);
|
meta_window_activate (w, timestamp);
|
||||||
|
|||||||
@@ -92,7 +92,6 @@ struct _MetaDisplay
|
|||||||
Display *xdisplay;
|
Display *xdisplay;
|
||||||
|
|
||||||
int clutter_event_filter;
|
int clutter_event_filter;
|
||||||
GSource *x11_event_source;
|
|
||||||
|
|
||||||
Window leader_window;
|
Window leader_window;
|
||||||
Window timestamp_pinging_window;
|
Window timestamp_pinging_window;
|
||||||
@@ -146,12 +145,18 @@ struct _MetaDisplay
|
|||||||
* multiple events with the same serial.
|
* multiple events with the same serial.
|
||||||
*/
|
*/
|
||||||
guint focused_by_us : 1;
|
guint focused_by_us : 1;
|
||||||
|
|
||||||
|
guint static_gravity_works : 1;
|
||||||
|
|
||||||
/*< private-ish >*/
|
/*< private-ish >*/
|
||||||
MetaScreen *screen;
|
guint error_trap_synced_at_last_pop : 1;
|
||||||
|
GSList *screens;
|
||||||
|
MetaScreen *active_screen;
|
||||||
GHashTable *xids;
|
GHashTable *xids;
|
||||||
GHashTable *wayland_windows;
|
GHashTable *wayland_windows;
|
||||||
|
int error_traps;
|
||||||
|
int (* error_trap_handler) (Display *display,
|
||||||
|
XErrorEvent *error);
|
||||||
int server_grab_count;
|
int server_grab_count;
|
||||||
|
|
||||||
/* serials of leave/unmap events that may
|
/* serials of leave/unmap events that may
|
||||||
@@ -187,6 +192,7 @@ struct _MetaDisplay
|
|||||||
|
|
||||||
/* current window operation */
|
/* current window operation */
|
||||||
MetaGrabOp grab_op;
|
MetaGrabOp grab_op;
|
||||||
|
MetaScreen *grab_screen;
|
||||||
MetaWindow *grab_window;
|
MetaWindow *grab_window;
|
||||||
Window grab_xwindow;
|
Window grab_xwindow;
|
||||||
int grab_button;
|
int grab_button;
|
||||||
@@ -209,6 +215,7 @@ struct _MetaDisplay
|
|||||||
gboolean grab_threshold_movement_reached; /* raise_on_click == FALSE. */
|
gboolean grab_threshold_movement_reached; /* raise_on_click == FALSE. */
|
||||||
MetaResizePopup *grab_resize_popup;
|
MetaResizePopup *grab_resize_popup;
|
||||||
GTimeVal grab_last_moveresize_time;
|
GTimeVal grab_last_moveresize_time;
|
||||||
|
guint32 grab_motion_notify_time;
|
||||||
GList* grab_old_window_stacking;
|
GList* grab_old_window_stacking;
|
||||||
MetaEdgeResistanceData *grab_edge_resistance_data;
|
MetaEdgeResistanceData *grab_edge_resistance_data;
|
||||||
unsigned int grab_last_user_action_was_snap;
|
unsigned int grab_last_user_action_was_snap;
|
||||||
@@ -226,8 +233,8 @@ struct _MetaDisplay
|
|||||||
int grab_resize_timeout_id;
|
int grab_resize_timeout_id;
|
||||||
|
|
||||||
/* Keybindings stuff */
|
/* Keybindings stuff */
|
||||||
GHashTable *key_bindings;
|
MetaKeyBinding *key_bindings;
|
||||||
GHashTable *key_bindings_index;
|
int n_key_bindings;
|
||||||
int min_keycode;
|
int min_keycode;
|
||||||
int max_keycode;
|
int max_keycode;
|
||||||
KeySym *keymap;
|
KeySym *keymap;
|
||||||
@@ -254,8 +261,6 @@ struct _MetaDisplay
|
|||||||
/* Closing down the display */
|
/* Closing down the display */
|
||||||
int closing;
|
int closing;
|
||||||
|
|
||||||
GSList *error_traps;
|
|
||||||
|
|
||||||
/* Managed by group.c */
|
/* Managed by group.c */
|
||||||
GHashTable *groups_by_leader;
|
GHashTable *groups_by_leader;
|
||||||
|
|
||||||
@@ -349,6 +354,10 @@ struct _MetaDisplayClass
|
|||||||
gboolean meta_display_open (void);
|
gboolean meta_display_open (void);
|
||||||
void meta_display_close (MetaDisplay *display,
|
void meta_display_close (MetaDisplay *display,
|
||||||
guint32 timestamp);
|
guint32 timestamp);
|
||||||
|
MetaScreen* meta_display_screen_for_x_screen (MetaDisplay *display,
|
||||||
|
Screen *screen);
|
||||||
|
MetaScreen* meta_display_screen_for_xwindow (MetaDisplay *display,
|
||||||
|
Window xindow);
|
||||||
void meta_display_grab (MetaDisplay *display);
|
void meta_display_grab (MetaDisplay *display);
|
||||||
void meta_display_ungrab (MetaDisplay *display);
|
void meta_display_ungrab (MetaDisplay *display);
|
||||||
|
|
||||||
@@ -448,9 +457,6 @@ int meta_resize_gravity_from_grab_op (MetaGrabOp op);
|
|||||||
gboolean meta_grab_op_is_moving (MetaGrabOp op);
|
gboolean meta_grab_op_is_moving (MetaGrabOp op);
|
||||||
gboolean meta_grab_op_is_resizing (MetaGrabOp op);
|
gboolean meta_grab_op_is_resizing (MetaGrabOp op);
|
||||||
gboolean meta_grab_op_is_mouse (MetaGrabOp op);
|
gboolean meta_grab_op_is_mouse (MetaGrabOp op);
|
||||||
gboolean meta_grab_op_is_clicking (MetaGrabOp op);
|
|
||||||
gboolean meta_grab_op_is_wayland (MetaGrabOp op);
|
|
||||||
gboolean meta_grab_op_is_keyboard (MetaGrabOp op);
|
|
||||||
|
|
||||||
void meta_display_devirtualize_modifiers (MetaDisplay *display,
|
void meta_display_devirtualize_modifiers (MetaDisplay *display,
|
||||||
MetaVirtualModifier modifiers,
|
MetaVirtualModifier modifiers,
|
||||||
@@ -483,16 +489,4 @@ void meta_display_set_input_focus_xwindow (MetaDisplay *display,
|
|||||||
Window window,
|
Window window,
|
||||||
guint32 timestamp);
|
guint32 timestamp);
|
||||||
|
|
||||||
void meta_display_sync_wayland_input_focus (MetaDisplay *display);
|
|
||||||
void meta_display_update_focus_window (MetaDisplay *display,
|
|
||||||
MetaWindow *window,
|
|
||||||
Window xwindow,
|
|
||||||
gulong serial,
|
|
||||||
gboolean focused_by_us);
|
|
||||||
|
|
||||||
void meta_display_sanity_check_timestamps (MetaDisplay *display,
|
|
||||||
guint32 timestamp);
|
|
||||||
gboolean meta_display_timestamp_too_old (MetaDisplay *display,
|
|
||||||
guint32 *timestamp);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
3010
src/core/display.c
3010
src/core/display.c
File diff suppressed because it is too large
Load Diff
@@ -30,6 +30,7 @@
|
|||||||
*/
|
*/
|
||||||
#define WINDOW_EDGES_RELEVANT(window, display) \
|
#define WINDOW_EDGES_RELEVANT(window, display) \
|
||||||
meta_window_should_be_showing (window) && \
|
meta_window_should_be_showing (window) && \
|
||||||
|
window->screen == display->grab_screen && \
|
||||||
window != display->grab_window && \
|
window != display->grab_window && \
|
||||||
window->type != META_WINDOW_DESKTOP && \
|
window->type != META_WINDOW_DESKTOP && \
|
||||||
window->type != META_WINDOW_MENU && \
|
window->type != META_WINDOW_MENU && \
|
||||||
@@ -962,9 +963,9 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
|
|||||||
/*
|
/*
|
||||||
* 1st: Get the list of relevant windows, from bottom to top
|
* 1st: Get the list of relevant windows, from bottom to top
|
||||||
*/
|
*/
|
||||||
stacked_windows =
|
stacked_windows =
|
||||||
meta_stack_list_windows (display->screen->stack,
|
meta_stack_list_windows (display->grab_screen->stack,
|
||||||
display->screen->active_workspace);
|
display->grab_screen->active_workspace);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 2nd: we need to separate that stacked list into a list of windows that
|
* 2nd: we need to separate that stacked list into a list of windows that
|
||||||
@@ -1025,7 +1026,7 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
|
|||||||
* by other windows or DOCKS, but that's handled below).
|
* by other windows or DOCKS, but that's handled below).
|
||||||
*/
|
*/
|
||||||
meta_rectangle_intersect (&cur_rect,
|
meta_rectangle_intersect (&cur_rect,
|
||||||
&display->screen->rect,
|
&display->grab_screen->rect,
|
||||||
&reduced);
|
&reduced);
|
||||||
|
|
||||||
new_edges = NULL;
|
new_edges = NULL;
|
||||||
@@ -1122,8 +1123,8 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
|
|||||||
*/
|
*/
|
||||||
cache_edges (display,
|
cache_edges (display,
|
||||||
edges,
|
edges,
|
||||||
display->screen->active_workspace->monitor_edges,
|
display->grab_screen->active_workspace->monitor_edges,
|
||||||
display->screen->active_workspace->screen_edges);
|
display->grab_screen->active_workspace->screen_edges);
|
||||||
g_list_free (edges);
|
g_list_free (edges);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2014 Red Hat
|
* Copyright (C) 2001 Havoc Pennington, error trapping inspired by GDK
|
||||||
*
|
* code copyrighted by the GTK team.
|
||||||
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License as
|
* modify it under the terms of the GNU General Public License as
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
@@ -12,11 +13,9 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* General Public License for more details.
|
* General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
||||||
* 02111-1307, USA.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,250 +27,42 @@
|
|||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <meta/errors.h>
|
#include <meta/errors.h>
|
||||||
#include "display-private.h"
|
#include "display-private.h"
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <gdk/gdk.h>
|
||||||
|
|
||||||
/* This is a copy-paste of the error handling code in GDK, modified
|
/* In GTK+-3.0, the error trapping code was significantly rewritten. The new code
|
||||||
* so that it works with mutter's internal structures, since we don't
|
* has some neat features (like knowing automatically if a sync is needed or not
|
||||||
* have a GDK display open. */
|
* and handling errors asynchronously when the error code isn't needed immediately),
|
||||||
|
* but it's basically incompatible with the hacks we played with GTK+-2.0 to
|
||||||
/* compare X sequence numbers handling wraparound */
|
* use a custom error handler along with gdk_error_trap_push().
|
||||||
#define SEQUENCE_COMPARE(a,op,b) (((long) (a) - (long) (b)) op 0)
|
*
|
||||||
|
* Since the main point of our custom error trap was to get the error logged
|
||||||
typedef struct _GdkErrorTrap GdkErrorTrap;
|
* to the right place, with GTK+-3.0 we simply omit our own error handler and
|
||||||
|
* use the GTK+ handling straight-up.
|
||||||
struct _GdkErrorTrap
|
* (See https://bugzilla.gnome.org/show_bug.cgi?id=630216 for restoring logging.)
|
||||||
{
|
*/
|
||||||
/* Next sequence when trap was pushed, i.e. first sequence to
|
|
||||||
* ignore
|
|
||||||
*/
|
|
||||||
gulong start_sequence;
|
|
||||||
|
|
||||||
/* Next sequence when trap was popped, i.e. first sequence
|
|
||||||
* to not ignore. 0 if trap is still active.
|
|
||||||
*/
|
|
||||||
gulong end_sequence;
|
|
||||||
|
|
||||||
/* Most recent error code within the sequence */
|
|
||||||
int error_code;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* delivers an error event from the error handler in gdkmain-x11.c */
|
|
||||||
static void
|
|
||||||
meta_display_error_event (MetaDisplay *display,
|
|
||||||
XErrorEvent *error)
|
|
||||||
{
|
|
||||||
GSList *tmp_list;
|
|
||||||
gboolean ignore;
|
|
||||||
|
|
||||||
ignore = FALSE;
|
|
||||||
for (tmp_list = display->error_traps;
|
|
||||||
tmp_list != NULL;
|
|
||||||
tmp_list = tmp_list->next)
|
|
||||||
{
|
|
||||||
GdkErrorTrap *trap;
|
|
||||||
|
|
||||||
trap = tmp_list->data;
|
|
||||||
|
|
||||||
if (SEQUENCE_COMPARE (trap->start_sequence, <=, error->serial) &&
|
|
||||||
(trap->end_sequence == 0 ||
|
|
||||||
SEQUENCE_COMPARE (trap->end_sequence, >, error->serial)))
|
|
||||||
{
|
|
||||||
ignore = TRUE;
|
|
||||||
trap->error_code = error->error_code;
|
|
||||||
break; /* only innermost trap gets the error code */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ignore)
|
|
||||||
{
|
|
||||||
gchar buf[64];
|
|
||||||
gchar *msg;
|
|
||||||
|
|
||||||
XGetErrorText (display->xdisplay, error->error_code, buf, 63);
|
|
||||||
|
|
||||||
msg =
|
|
||||||
g_strdup_printf ("mutter received an X Window System error: %s\n"
|
|
||||||
" (Details: serial %ld error_code %d request_code %d minor_code %d)\n",
|
|
||||||
buf,
|
|
||||||
error->serial,
|
|
||||||
error->error_code,
|
|
||||||
error->request_code,
|
|
||||||
error->minor_code);
|
|
||||||
|
|
||||||
g_error ("%s", msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
gdk_x_error (Display *xdisplay,
|
|
||||||
XErrorEvent *error)
|
|
||||||
{
|
|
||||||
MetaDisplay *display = meta_display_for_x_display (xdisplay);
|
|
||||||
meta_display_error_event (display, error);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* non-GDK previous error handler */
|
|
||||||
typedef int (*GdkXErrorHandler) (Display *, XErrorEvent *);
|
|
||||||
static GdkXErrorHandler _gdk_old_error_handler;
|
|
||||||
/* number of times we've pushed the GDK error handler */
|
|
||||||
static int _gdk_error_handler_push_count = 0;
|
|
||||||
|
|
||||||
static void
|
|
||||||
_gdk_x11_error_handler_push (void)
|
|
||||||
{
|
|
||||||
GdkXErrorHandler previous;
|
|
||||||
|
|
||||||
previous = XSetErrorHandler (gdk_x_error);
|
|
||||||
|
|
||||||
if (_gdk_error_handler_push_count > 0)
|
|
||||||
{
|
|
||||||
if (previous != gdk_x_error)
|
|
||||||
g_warning ("XSetErrorHandler() called with a GDK error trap pushed. Don't do that.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_gdk_old_error_handler = previous;
|
|
||||||
}
|
|
||||||
|
|
||||||
_gdk_error_handler_push_count += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_gdk_x11_error_handler_pop (void)
|
|
||||||
{
|
|
||||||
g_return_if_fail (_gdk_error_handler_push_count > 0);
|
|
||||||
|
|
||||||
_gdk_error_handler_push_count -= 1;
|
|
||||||
|
|
||||||
if (_gdk_error_handler_push_count == 0)
|
|
||||||
{
|
|
||||||
XSetErrorHandler (_gdk_old_error_handler);
|
|
||||||
_gdk_old_error_handler = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
delete_outdated_error_traps (MetaDisplay *display)
|
|
||||||
{
|
|
||||||
GSList *tmp_list;
|
|
||||||
gulong processed_sequence;
|
|
||||||
|
|
||||||
processed_sequence = XLastKnownRequestProcessed (display->xdisplay);
|
|
||||||
|
|
||||||
tmp_list = display->error_traps;
|
|
||||||
while (tmp_list != NULL)
|
|
||||||
{
|
|
||||||
GdkErrorTrap *trap = tmp_list->data;
|
|
||||||
|
|
||||||
if (trap->end_sequence != 0 &&
|
|
||||||
SEQUENCE_COMPARE (trap->end_sequence, <=, processed_sequence))
|
|
||||||
{
|
|
||||||
GSList *free_me = tmp_list;
|
|
||||||
|
|
||||||
tmp_list = tmp_list->next;
|
|
||||||
display->error_traps = g_slist_delete_link (display->error_traps, free_me);
|
|
||||||
g_slice_free (GdkErrorTrap, trap);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tmp_list = tmp_list->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_error_trap_push (MetaDisplay *display)
|
meta_error_trap_push (MetaDisplay *display)
|
||||||
{
|
{
|
||||||
GdkErrorTrap *trap;
|
gdk_error_trap_push ();
|
||||||
|
|
||||||
delete_outdated_error_traps (display);
|
|
||||||
|
|
||||||
/* set up the Xlib callback to tell us about errors */
|
|
||||||
_gdk_x11_error_handler_push ();
|
|
||||||
|
|
||||||
trap = g_slice_new0 (GdkErrorTrap);
|
|
||||||
|
|
||||||
trap->start_sequence = XNextRequest (display->xdisplay);
|
|
||||||
trap->error_code = Success;
|
|
||||||
|
|
||||||
display->error_traps =
|
|
||||||
g_slist_prepend (display->error_traps, trap);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gint
|
|
||||||
meta_error_trap_pop_internal (MetaDisplay *display,
|
|
||||||
gboolean need_code)
|
|
||||||
{
|
|
||||||
GdkErrorTrap *trap;
|
|
||||||
GSList *tmp_list;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
g_return_val_if_fail (display->error_traps != NULL, Success);
|
|
||||||
|
|
||||||
/* Find the first trap that hasn't been popped already */
|
|
||||||
trap = NULL; /* quiet gcc */
|
|
||||||
for (tmp_list = display->error_traps;
|
|
||||||
tmp_list != NULL;
|
|
||||||
tmp_list = tmp_list->next)
|
|
||||||
{
|
|
||||||
trap = tmp_list->data;
|
|
||||||
|
|
||||||
if (trap->end_sequence == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_return_val_if_fail (trap != NULL, Success);
|
|
||||||
g_assert (trap->end_sequence == 0);
|
|
||||||
|
|
||||||
/* May need to sync to fill in trap->error_code if we care about
|
|
||||||
* getting an error code.
|
|
||||||
*/
|
|
||||||
if (need_code)
|
|
||||||
{
|
|
||||||
gulong processed_sequence;
|
|
||||||
gulong next_sequence;
|
|
||||||
|
|
||||||
next_sequence = XNextRequest (display->xdisplay);
|
|
||||||
processed_sequence = XLastKnownRequestProcessed (display->xdisplay);
|
|
||||||
|
|
||||||
/* If our last request was already processed, there is no point
|
|
||||||
* in syncing. i.e. if last request was a round trip (or even if
|
|
||||||
* we got an event with the serial of a non-round-trip)
|
|
||||||
*/
|
|
||||||
if ((next_sequence - 1) != processed_sequence)
|
|
||||||
{
|
|
||||||
XSync (display->xdisplay, False);
|
|
||||||
}
|
|
||||||
|
|
||||||
result = trap->error_code;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = Success;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* record end of trap, giving us a range of
|
|
||||||
* error sequences we'll ignore.
|
|
||||||
*/
|
|
||||||
trap->end_sequence = XNextRequest (display->xdisplay);
|
|
||||||
|
|
||||||
/* remove the Xlib callback */
|
|
||||||
_gdk_x11_error_handler_pop ();
|
|
||||||
|
|
||||||
/* we may already be outdated */
|
|
||||||
delete_outdated_error_traps (display);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_error_trap_pop (MetaDisplay *display)
|
meta_error_trap_pop (MetaDisplay *display)
|
||||||
{
|
{
|
||||||
meta_error_trap_pop_internal (display, FALSE);
|
gdk_error_trap_pop_ignored ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_error_trap_push_with_return (MetaDisplay *display)
|
||||||
|
{
|
||||||
|
gdk_error_trap_push ();
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
meta_error_trap_pop_with_return (MetaDisplay *display)
|
meta_error_trap_pop_with_return (MetaDisplay *display)
|
||||||
{
|
{
|
||||||
return meta_error_trap_pop_internal (display, TRUE);
|
return gdk_error_trap_pop ();
|
||||||
}
|
}
|
||||||
|
|||||||
2266
src/core/events.c
2266
src/core/events.c
File diff suppressed because it is too large
Load Diff
@@ -1,32 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2001 Havoc Pennington
|
|
||||||
* Copyright (C) 2002, 2003, 2004 Red Hat, Inc.
|
|
||||||
* Copyright (C) 2003, 2004 Rob Adams
|
|
||||||
* Copyright (C) 2004-2006 Elijah Newren
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <meta/display.h>
|
|
||||||
|
|
||||||
#ifndef META_EVENTS_H
|
|
||||||
#define META_EVENTS_H
|
|
||||||
|
|
||||||
void meta_display_init_events (MetaDisplay *display);
|
|
||||||
void meta_display_free_events (MetaDisplay *display);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -35,7 +35,8 @@
|
|||||||
ButtonPressMask | ButtonReleaseMask | \
|
ButtonPressMask | ButtonReleaseMask | \
|
||||||
PointerMotionMask | PointerMotionHintMask | \
|
PointerMotionMask | PointerMotionHintMask | \
|
||||||
EnterWindowMask | LeaveWindowMask | \
|
EnterWindowMask | LeaveWindowMask | \
|
||||||
FocusChangeMask)
|
FocusChangeMask | \
|
||||||
|
ColormapChangeMask)
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_window_ensure_frame (MetaWindow *window)
|
meta_window_ensure_frame (MetaWindow *window)
|
||||||
@@ -92,6 +93,7 @@ meta_window_ensure_frame (MetaWindow *window)
|
|||||||
visual = NULL;
|
visual = NULL;
|
||||||
|
|
||||||
frame->xwindow = meta_ui_create_frame_window (window->screen->ui,
|
frame->xwindow = meta_ui_create_frame_window (window->screen->ui,
|
||||||
|
window->display->xdisplay,
|
||||||
visual,
|
visual,
|
||||||
frame->rect.x,
|
frame->rect.x,
|
||||||
frame->rect.y,
|
frame->rect.y,
|
||||||
|
|||||||
@@ -230,7 +230,7 @@ read_rgb_icon (MetaDisplay *display,
|
|||||||
int mini_w, mini_h;
|
int mini_w, mini_h;
|
||||||
gulong *data_as_long;
|
gulong *data_as_long;
|
||||||
|
|
||||||
meta_error_trap_push (display);
|
meta_error_trap_push_with_return (display);
|
||||||
type = None;
|
type = None;
|
||||||
data = NULL;
|
data = NULL;
|
||||||
result = XGetWindowProperty (display->xdisplay,
|
result = XGetWindowProperty (display->xdisplay,
|
||||||
@@ -504,7 +504,7 @@ get_kwm_win_icon (MetaDisplay *display,
|
|||||||
*pixmap = None;
|
*pixmap = None;
|
||||||
*mask = None;
|
*mask = None;
|
||||||
|
|
||||||
meta_error_trap_push (display);
|
meta_error_trap_push_with_return (display);
|
||||||
icons = NULL;
|
icons = NULL;
|
||||||
result = XGetWindowProperty (display->xdisplay, xwindow,
|
result = XGetWindowProperty (display->xdisplay, xwindow,
|
||||||
display->atom__KWM_WIN_ICON,
|
display->atom__KWM_WIN_ICON,
|
||||||
@@ -30,7 +30,6 @@
|
|||||||
#include <gio/gio.h>
|
#include <gio/gio.h>
|
||||||
#include <meta/keybindings.h>
|
#include <meta/keybindings.h>
|
||||||
|
|
||||||
typedef struct _MetaKeyHandler MetaKeyHandler;
|
|
||||||
struct _MetaKeyHandler
|
struct _MetaKeyHandler
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
@@ -48,48 +47,9 @@ struct _MetaKeyBinding
|
|||||||
KeyCode keycode;
|
KeyCode keycode;
|
||||||
unsigned int mask;
|
unsigned int mask;
|
||||||
MetaVirtualModifier modifiers;
|
MetaVirtualModifier modifiers;
|
||||||
gint flags;
|
|
||||||
MetaKeyHandler *handler;
|
MetaKeyHandler *handler;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* MetaKeyCombo:
|
|
||||||
* @keysym: keysym
|
|
||||||
* @keycode: keycode
|
|
||||||
* @modifiers: modifiers
|
|
||||||
*/
|
|
||||||
typedef struct _MetaKeyCombo MetaKeyCombo;
|
|
||||||
struct _MetaKeyCombo
|
|
||||||
{
|
|
||||||
unsigned int keysym;
|
|
||||||
unsigned int keycode;
|
|
||||||
MetaVirtualModifier modifiers;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char *name;
|
|
||||||
GSettings *settings;
|
|
||||||
|
|
||||||
MetaKeyBindingAction action;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A list of MetaKeyCombos. Each of them is bound to
|
|
||||||
* this keypref. If one has keysym==modifiers==0, it is
|
|
||||||
* ignored.
|
|
||||||
*/
|
|
||||||
GSList *combos;
|
|
||||||
|
|
||||||
/* for keybindings that can have shift or not like Alt+Tab */
|
|
||||||
gboolean add_shift:1;
|
|
||||||
|
|
||||||
/* for keybindings that apply only to a window */
|
|
||||||
gboolean per_window:1;
|
|
||||||
|
|
||||||
/* for keybindings not added with meta_display_add_keybinding() */
|
|
||||||
gboolean builtin:1;
|
|
||||||
} MetaKeyPref;
|
|
||||||
|
|
||||||
void meta_display_init_keys (MetaDisplay *display);
|
void meta_display_init_keys (MetaDisplay *display);
|
||||||
void meta_display_shutdown_keys (MetaDisplay *display);
|
void meta_display_shutdown_keys (MetaDisplay *display);
|
||||||
void meta_screen_grab_keys (MetaScreen *screen);
|
void meta_screen_grab_keys (MetaScreen *screen);
|
||||||
@@ -117,8 +77,5 @@ gboolean meta_prefs_add_keybinding (const char *name,
|
|||||||
|
|
||||||
gboolean meta_prefs_remove_keybinding (const char *name);
|
gboolean meta_prefs_remove_keybinding (const char *name);
|
||||||
|
|
||||||
GList *meta_prefs_get_keybindings (void);
|
|
||||||
void meta_prefs_get_overlay_binding (MetaKeyCombo *combo);
|
|
||||||
const char *meta_prefs_get_iso_next_group_option (void);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -42,7 +42,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#define _XOPEN_SOURCE /* for putenv() and some signal-related functions */
|
#define _SVID_SOURCE /* for putenv() and some signal-related functions */
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <meta/main.h>
|
#include <meta/main.h>
|
||||||
@@ -50,11 +50,14 @@
|
|||||||
#include "display-private.h"
|
#include "display-private.h"
|
||||||
#include <meta/errors.h>
|
#include <meta/errors.h>
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
|
#include "session.h"
|
||||||
#include <meta/prefs.h>
|
#include <meta/prefs.h>
|
||||||
#include <meta/compositor.h>
|
#include <meta/compositor.h>
|
||||||
|
#include "meta-wayland-private.h"
|
||||||
|
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
#include <glib-unix.h>
|
#include <glib-unix.h>
|
||||||
|
#include <gdk/gdkx.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@@ -70,16 +73,12 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
|
#include <clutter/x11/clutter-x11.h>
|
||||||
|
|
||||||
#ifdef HAVE_INTROSPECTION
|
#ifdef HAVE_INTROSPECTION
|
||||||
#include <girepository.h>
|
#include <girepository.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "x11/session.h"
|
|
||||||
|
|
||||||
#include "wayland/meta-wayland.h"
|
|
||||||
#include "backends/meta-backend.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The exit code we'll return to our parent process when we eventually die.
|
* The exit code we'll return to our parent process when we eventually die.
|
||||||
*/
|
*/
|
||||||
@@ -191,7 +190,6 @@ static gboolean opt_replace_wm;
|
|||||||
static gboolean opt_disable_sm;
|
static gboolean opt_disable_sm;
|
||||||
static gboolean opt_sync;
|
static gboolean opt_sync;
|
||||||
static gboolean opt_wayland;
|
static gboolean opt_wayland;
|
||||||
static gboolean opt_display_server;
|
|
||||||
|
|
||||||
static GOptionEntry meta_options[] = {
|
static GOptionEntry meta_options[] = {
|
||||||
{
|
{
|
||||||
@@ -235,11 +233,6 @@ static GOptionEntry meta_options[] = {
|
|||||||
N_("Run as a wayland compositor"),
|
N_("Run as a wayland compositor"),
|
||||||
NULL
|
NULL
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"display-server", 0, 0, G_OPTION_ARG_NONE,
|
|
||||||
&opt_display_server,
|
|
||||||
N_("Run as a full display server, rather than nested")
|
|
||||||
},
|
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -266,6 +259,72 @@ meta_get_option_context (void)
|
|||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Mutter is responsible for pulling events off the X queue, so Clutter
|
||||||
|
* doesn't need (and shouldn't) run its normal event source which polls
|
||||||
|
* the X fd, but we do have to deal with dispatching events that accumulate
|
||||||
|
* in the clutter queue. This happens, for example, when clutter generate
|
||||||
|
* enter/leave events on mouse motion - several events are queued in the
|
||||||
|
* clutter queue but only one dispatched. It could also happen because of
|
||||||
|
* explicit calls to clutter_event_put(). We add a very simple custom
|
||||||
|
* event loop source which is simply responsible for pulling events off
|
||||||
|
* of the queue and dispatching them before we block for new events.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
event_prepare (GSource *source,
|
||||||
|
gint *timeout_)
|
||||||
|
{
|
||||||
|
*timeout_ = -1;
|
||||||
|
|
||||||
|
return clutter_events_pending ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
event_check (GSource *source)
|
||||||
|
{
|
||||||
|
return clutter_events_pending ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
event_dispatch (GSource *source,
|
||||||
|
GSourceFunc callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
ClutterEvent *event = clutter_event_get ();
|
||||||
|
|
||||||
|
if (event)
|
||||||
|
{
|
||||||
|
clutter_do_event (event);
|
||||||
|
clutter_event_free (event);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GSourceFuncs event_funcs = {
|
||||||
|
event_prepare,
|
||||||
|
event_check,
|
||||||
|
event_dispatch
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_clutter_init (void)
|
||||||
|
{
|
||||||
|
clutter_x11_set_display (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
|
||||||
|
clutter_x11_disable_event_retrieval ();
|
||||||
|
|
||||||
|
if (CLUTTER_INIT_SUCCESS == clutter_init (NULL, NULL))
|
||||||
|
{
|
||||||
|
GSource *source = g_source_new (&event_funcs, sizeof (GSource));
|
||||||
|
g_source_attach (source, NULL);
|
||||||
|
g_source_unref (source);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
meta_fatal ("Unable to initialize Clutter.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* meta_select_display:
|
* meta_select_display:
|
||||||
*
|
*
|
||||||
@@ -342,7 +401,8 @@ meta_init (void)
|
|||||||
if (g_getenv ("MUTTER_DEBUG"))
|
if (g_getenv ("MUTTER_DEBUG"))
|
||||||
meta_set_debugging (TRUE);
|
meta_set_debugging (TRUE);
|
||||||
|
|
||||||
if (opt_display_server)
|
/* We consider running from mutter-launch equivalent to running from bare metal. */
|
||||||
|
if (getenv ("WESTON_LAUNCHER_SOCK"))
|
||||||
clutter_set_windowing_backend (CLUTTER_WINDOWING_EGL);
|
clutter_set_windowing_backend (CLUTTER_WINDOWING_EGL);
|
||||||
|
|
||||||
meta_set_is_wayland_compositor (opt_wayland);
|
meta_set_is_wayland_compositor (opt_wayland);
|
||||||
|
|||||||
46
src/core/meta-cursor-tracker-private.h
Normal file
46
src/core/meta-cursor-tracker-private.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2013 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Author: Giovanni Campagna <gcampagn@redhat.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef META_CURSOR_TRACKER_PRIVATE_H
|
||||||
|
#define META_CURSOR_TRACKER_PRIVATE_H
|
||||||
|
|
||||||
|
#include <meta/meta-cursor-tracker.h>
|
||||||
|
#include <wayland-server.h>
|
||||||
|
#include <clutter/clutter.h>
|
||||||
|
|
||||||
|
gboolean meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
|
||||||
|
XEvent *xevent);
|
||||||
|
|
||||||
|
void meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker,
|
||||||
|
MetaCursor cursor);
|
||||||
|
void meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
|
||||||
|
struct wl_resource *buffer,
|
||||||
|
int hot_x,
|
||||||
|
int hot_y);
|
||||||
|
void meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker);
|
||||||
|
void meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
|
||||||
|
MetaCursor cursor);
|
||||||
|
|
||||||
|
void meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
|
||||||
|
int new_x,
|
||||||
|
int new_y);
|
||||||
|
void meta_cursor_tracker_paint (MetaCursorTracker *tracker);
|
||||||
|
#endif
|
||||||
@@ -39,14 +39,76 @@
|
|||||||
#include <gbm.h>
|
#include <gbm.h>
|
||||||
|
|
||||||
#include <gdk/gdk.h>
|
#include <gdk/gdk.h>
|
||||||
#include <gdk/gdkx.h>
|
|
||||||
|
|
||||||
#include "meta-cursor-private.h"
|
#include <X11/cursorfont.h>
|
||||||
|
#include <X11/extensions/Xfixes.h>
|
||||||
|
#include <X11/Xcursor/Xcursor.h>
|
||||||
|
|
||||||
#include "meta-cursor-tracker-private.h"
|
#include "meta-cursor-tracker-private.h"
|
||||||
#include "screen-private.h"
|
#include "screen-private.h"
|
||||||
#include "meta-monitor-manager.h"
|
#include "meta-wayland-private.h"
|
||||||
|
#include "monitor-private.h"
|
||||||
|
|
||||||
#include "wayland/meta-wayland-private.h"
|
#define META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_X 7
|
||||||
|
#define META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_Y 4
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
CoglTexture2D *texture;
|
||||||
|
struct gbm_bo *bo;
|
||||||
|
int hot_x, hot_y;
|
||||||
|
|
||||||
|
int ref_count;
|
||||||
|
} MetaCursorReference;
|
||||||
|
|
||||||
|
struct _MetaCursorTracker {
|
||||||
|
GObject parent_instance;
|
||||||
|
|
||||||
|
MetaScreen *screen;
|
||||||
|
|
||||||
|
gboolean is_showing;
|
||||||
|
gboolean has_hw_cursor;
|
||||||
|
|
||||||
|
/* The cursor tracker stores the cursor for the current grab
|
||||||
|
* operation, the cursor for the window with pointer focus, and
|
||||||
|
* the cursor for the root window, which contains either the
|
||||||
|
* default arrow cursor or the 'busy' hourglass if we're launching
|
||||||
|
* an app.
|
||||||
|
*
|
||||||
|
* We choose the first one available -- if there's a grab cursor,
|
||||||
|
* we choose that cursor, if there's window cursor, we choose that,
|
||||||
|
* otherwise we choose the root cursor.
|
||||||
|
*
|
||||||
|
* The displayed_cursor contains the chosen cursor.
|
||||||
|
*/
|
||||||
|
MetaCursorReference *displayed_cursor;
|
||||||
|
|
||||||
|
MetaCursorReference *grab_cursor;
|
||||||
|
|
||||||
|
/* Wayland clients can set a NULL buffer as their cursor
|
||||||
|
* explicitly, which means that we shouldn't display anything.
|
||||||
|
* So, we can't simply store a NULL in window_cursor to
|
||||||
|
* determine an unset window cursor; we need an extra boolean.
|
||||||
|
*/
|
||||||
|
gboolean has_window_cursor;
|
||||||
|
MetaCursorReference *window_cursor;
|
||||||
|
|
||||||
|
MetaCursorReference *root_cursor;
|
||||||
|
|
||||||
|
MetaCursorReference *default_cursors[META_CURSOR_LAST];
|
||||||
|
|
||||||
|
int current_x, current_y;
|
||||||
|
MetaRectangle current_rect;
|
||||||
|
MetaRectangle previous_rect;
|
||||||
|
gboolean previous_is_valid;
|
||||||
|
|
||||||
|
CoglPipeline *pipeline;
|
||||||
|
int drm_fd;
|
||||||
|
struct gbm_device *gbm;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _MetaCursorTrackerClass {
|
||||||
|
GObjectClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT);
|
G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT);
|
||||||
|
|
||||||
@@ -62,6 +124,360 @@ static void meta_cursor_tracker_set_crtc_has_hw_cursor (MetaCursorTracker *track
|
|||||||
gboolean has_hw_cursor);
|
gboolean has_hw_cursor);
|
||||||
static void sync_cursor (MetaCursorTracker *tracker);
|
static void sync_cursor (MetaCursorTracker *tracker);
|
||||||
|
|
||||||
|
static MetaCursorReference *
|
||||||
|
meta_cursor_reference_ref (MetaCursorReference *self)
|
||||||
|
{
|
||||||
|
g_assert (self->ref_count > 0);
|
||||||
|
self->ref_count++;
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_cursor_reference_unref (MetaCursorReference *self)
|
||||||
|
{
|
||||||
|
self->ref_count--;
|
||||||
|
|
||||||
|
if (self->ref_count == 0)
|
||||||
|
{
|
||||||
|
cogl_object_unref (self->texture);
|
||||||
|
if (self->bo)
|
||||||
|
gbm_bo_destroy (self->bo);
|
||||||
|
|
||||||
|
g_slice_free (MetaCursorReference, self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
translate_meta_cursor (MetaCursor cursor,
|
||||||
|
guint *glyph_out,
|
||||||
|
const char **name_out)
|
||||||
|
{
|
||||||
|
guint glyph = XC_num_glyphs;
|
||||||
|
const char *name = NULL;
|
||||||
|
|
||||||
|
switch (cursor)
|
||||||
|
{
|
||||||
|
case META_CURSOR_DEFAULT:
|
||||||
|
glyph = XC_left_ptr;
|
||||||
|
break;
|
||||||
|
case META_CURSOR_NORTH_RESIZE:
|
||||||
|
glyph = XC_top_side;
|
||||||
|
break;
|
||||||
|
case META_CURSOR_SOUTH_RESIZE:
|
||||||
|
glyph = XC_bottom_side;
|
||||||
|
break;
|
||||||
|
case META_CURSOR_WEST_RESIZE:
|
||||||
|
glyph = XC_left_side;
|
||||||
|
break;
|
||||||
|
case META_CURSOR_EAST_RESIZE:
|
||||||
|
glyph = XC_right_side;
|
||||||
|
break;
|
||||||
|
case META_CURSOR_SE_RESIZE:
|
||||||
|
glyph = XC_bottom_right_corner;
|
||||||
|
break;
|
||||||
|
case META_CURSOR_SW_RESIZE:
|
||||||
|
glyph = XC_bottom_left_corner;
|
||||||
|
break;
|
||||||
|
case META_CURSOR_NE_RESIZE:
|
||||||
|
glyph = XC_top_right_corner;
|
||||||
|
break;
|
||||||
|
case META_CURSOR_NW_RESIZE:
|
||||||
|
glyph = XC_top_left_corner;
|
||||||
|
break;
|
||||||
|
case META_CURSOR_MOVE_OR_RESIZE_WINDOW:
|
||||||
|
glyph = XC_fleur;
|
||||||
|
break;
|
||||||
|
case META_CURSOR_BUSY:
|
||||||
|
glyph = XC_watch;
|
||||||
|
break;
|
||||||
|
case META_CURSOR_DND_IN_DRAG:
|
||||||
|
name = "dnd-none";
|
||||||
|
break;
|
||||||
|
case META_CURSOR_DND_MOVE:
|
||||||
|
name = "dnd-move";
|
||||||
|
break;
|
||||||
|
case META_CURSOR_DND_COPY:
|
||||||
|
name = "dnd-copy";
|
||||||
|
break;
|
||||||
|
case META_CURSOR_DND_UNSUPPORTED_TARGET:
|
||||||
|
name = "dnd-none";
|
||||||
|
break;
|
||||||
|
case META_CURSOR_POINTING_HAND:
|
||||||
|
glyph = XC_hand2;
|
||||||
|
break;
|
||||||
|
case META_CURSOR_CROSSHAIR:
|
||||||
|
glyph = XC_crosshair;
|
||||||
|
break;
|
||||||
|
case META_CURSOR_IBEAM:
|
||||||
|
glyph = XC_xterm;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
glyph = 0; /* silence compiler */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*glyph_out = glyph;
|
||||||
|
*name_out = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Cursor
|
||||||
|
load_cursor_on_server (MetaDisplay *display,
|
||||||
|
MetaCursor cursor)
|
||||||
|
{
|
||||||
|
Cursor xcursor;
|
||||||
|
guint glyph;
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
translate_meta_cursor (cursor, &glyph, &name);
|
||||||
|
|
||||||
|
if (name != NULL)
|
||||||
|
xcursor = XcursorLibraryLoadCursor (display->xdisplay, name);
|
||||||
|
else
|
||||||
|
xcursor = XCreateFontCursor (display->xdisplay, glyph);
|
||||||
|
|
||||||
|
return xcursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cursor
|
||||||
|
meta_display_create_x_cursor (MetaDisplay *display,
|
||||||
|
MetaCursor cursor)
|
||||||
|
{
|
||||||
|
return load_cursor_on_server (display, cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
static XcursorImage *
|
||||||
|
load_cursor_on_client (MetaDisplay *display,
|
||||||
|
MetaCursor cursor)
|
||||||
|
{
|
||||||
|
XcursorImage *image;
|
||||||
|
guint glyph;
|
||||||
|
const char *name;
|
||||||
|
const char *theme = XcursorGetTheme (display->xdisplay);
|
||||||
|
int size = XcursorGetDefaultSize (display->xdisplay);
|
||||||
|
|
||||||
|
translate_meta_cursor (cursor, &glyph, &name);
|
||||||
|
|
||||||
|
if (name != NULL)
|
||||||
|
image = XcursorLibraryLoadImage (name, theme, size);
|
||||||
|
else
|
||||||
|
image = XcursorShapeLoadImage (glyph, theme, size);
|
||||||
|
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MetaCursorReference *
|
||||||
|
meta_cursor_reference_from_theme (MetaCursorTracker *tracker,
|
||||||
|
MetaCursor cursor)
|
||||||
|
{
|
||||||
|
XcursorImage *image;
|
||||||
|
int width, height, rowstride;
|
||||||
|
CoglPixelFormat cogl_format;
|
||||||
|
uint32_t gbm_format;
|
||||||
|
ClutterBackend *clutter_backend;
|
||||||
|
CoglContext *cogl_context;
|
||||||
|
MetaCursorReference *self;
|
||||||
|
|
||||||
|
image = load_cursor_on_client (tracker->screen->display, cursor);
|
||||||
|
if (!image)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
width = image->width;
|
||||||
|
height = image->height;
|
||||||
|
rowstride = width * 4;
|
||||||
|
|
||||||
|
gbm_format = GBM_FORMAT_ARGB8888;
|
||||||
|
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||||
|
cogl_format = COGL_PIXEL_FORMAT_BGRA_8888;
|
||||||
|
#else
|
||||||
|
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
self = g_slice_new0 (MetaCursorReference);
|
||||||
|
self->ref_count = 1;
|
||||||
|
self->hot_x = image->xhot;
|
||||||
|
self->hot_y = image->yhot;
|
||||||
|
|
||||||
|
clutter_backend = clutter_get_default_backend ();
|
||||||
|
cogl_context = clutter_backend_get_cogl_context (clutter_backend);
|
||||||
|
self->texture = cogl_texture_2d_new_from_data (cogl_context,
|
||||||
|
width, height,
|
||||||
|
cogl_format,
|
||||||
|
rowstride,
|
||||||
|
(uint8_t*)image->pixels,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (tracker->gbm)
|
||||||
|
{
|
||||||
|
if (width > 64 || height > 64)
|
||||||
|
{
|
||||||
|
meta_warning ("Invalid theme cursor size (must be at most 64x64)\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gbm_device_is_format_supported (tracker->gbm, gbm_format,
|
||||||
|
GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE))
|
||||||
|
{
|
||||||
|
uint32_t buf[64 * 64];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
self->bo = gbm_bo_create (tracker->gbm, 64, 64,
|
||||||
|
gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
|
||||||
|
|
||||||
|
memset (buf, 0, sizeof(buf));
|
||||||
|
for (i = 0; i < height; i++)
|
||||||
|
memcpy (buf + i * 64, image->pixels + i * width, width * 4);
|
||||||
|
|
||||||
|
gbm_bo_write (self->bo, buf, 64 * 64 * 4);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
meta_warning ("HW cursor for format %d not supported\n", gbm_format);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
XcursorImageDestroy (image);
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MetaCursorReference *
|
||||||
|
meta_cursor_reference_take_texture (CoglTexture2D *texture)
|
||||||
|
{
|
||||||
|
MetaCursorReference *self;
|
||||||
|
|
||||||
|
self = g_slice_new0 (MetaCursorReference);
|
||||||
|
self->ref_count = 1;
|
||||||
|
|
||||||
|
self->texture = texture;
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MetaCursorReference *
|
||||||
|
meta_cursor_reference_from_buffer (MetaCursorTracker *tracker,
|
||||||
|
struct wl_resource *buffer,
|
||||||
|
int hot_x,
|
||||||
|
int hot_y)
|
||||||
|
{
|
||||||
|
ClutterBackend *backend;
|
||||||
|
CoglContext *cogl_context;
|
||||||
|
MetaCursorReference *self;
|
||||||
|
CoglPixelFormat cogl_format;
|
||||||
|
struct wl_shm_buffer *shm_buffer;
|
||||||
|
uint32_t gbm_format;
|
||||||
|
|
||||||
|
self = g_slice_new0 (MetaCursorReference);
|
||||||
|
self->ref_count = 1;
|
||||||
|
self->hot_x = hot_x;
|
||||||
|
self->hot_y = hot_y;
|
||||||
|
|
||||||
|
backend = clutter_get_default_backend ();
|
||||||
|
cogl_context = clutter_backend_get_cogl_context (backend);
|
||||||
|
|
||||||
|
shm_buffer = wl_shm_buffer_get (buffer);
|
||||||
|
if (shm_buffer)
|
||||||
|
{
|
||||||
|
int rowstride = wl_shm_buffer_get_stride (shm_buffer);
|
||||||
|
int width = wl_shm_buffer_get_width (shm_buffer);
|
||||||
|
int height = wl_shm_buffer_get_height (shm_buffer);
|
||||||
|
|
||||||
|
switch (wl_shm_buffer_get_format (shm_buffer))
|
||||||
|
{
|
||||||
|
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||||
|
case WL_SHM_FORMAT_ARGB8888:
|
||||||
|
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888_PRE;
|
||||||
|
gbm_format = GBM_FORMAT_ARGB8888;
|
||||||
|
break;
|
||||||
|
case WL_SHM_FORMAT_XRGB8888:
|
||||||
|
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888;
|
||||||
|
gbm_format = GBM_FORMAT_XRGB8888;
|
||||||
|
break;
|
||||||
|
#else
|
||||||
|
case WL_SHM_FORMAT_ARGB8888:
|
||||||
|
cogl_format = COGL_PIXEL_FORMAT_BGRA_8888_PRE;
|
||||||
|
gbm_format = GBM_FORMAT_ARGB8888;
|
||||||
|
break;
|
||||||
|
case WL_SHM_FORMAT_XRGB8888:
|
||||||
|
cogl_format = COGL_PIXEL_FORMAT_BGRA_8888;
|
||||||
|
gbm_format = GBM_FORMAT_XRGB8888;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
g_warn_if_reached ();
|
||||||
|
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888;
|
||||||
|
gbm_format = GBM_FORMAT_ARGB8888;
|
||||||
|
}
|
||||||
|
|
||||||
|
self->texture = cogl_texture_2d_new_from_data (cogl_context,
|
||||||
|
width, height,
|
||||||
|
cogl_format,
|
||||||
|
rowstride,
|
||||||
|
wl_shm_buffer_get_data (shm_buffer),
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (width > 64 || height > 64)
|
||||||
|
{
|
||||||
|
meta_warning ("Invalid cursor size (must be at most 64x64), falling back to software (GL) cursors\n");
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tracker->gbm)
|
||||||
|
{
|
||||||
|
if (gbm_device_is_format_supported (tracker->gbm, gbm_format,
|
||||||
|
GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE))
|
||||||
|
{
|
||||||
|
uint8_t *data;
|
||||||
|
uint8_t buf[4 * 64 * 64];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
self->bo = gbm_bo_create (tracker->gbm, 64, 64,
|
||||||
|
gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
|
||||||
|
|
||||||
|
data = wl_shm_buffer_get_data (shm_buffer);
|
||||||
|
memset (buf, 0, sizeof(buf));
|
||||||
|
for (i = 0; i < height; i++)
|
||||||
|
memcpy (buf + i * 4 * 64, data + i * rowstride, 4 * width);
|
||||||
|
|
||||||
|
gbm_bo_write (self->bo, buf, 64 * 64 * 4);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
meta_warning ("HW cursor for format %d not supported\n", gbm_format);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int width, height;
|
||||||
|
|
||||||
|
self->texture = cogl_wayland_texture_2d_new_from_buffer (cogl_context, buffer, NULL);
|
||||||
|
width = cogl_texture_get_width (COGL_TEXTURE (self->texture));
|
||||||
|
height = cogl_texture_get_height (COGL_TEXTURE (self->texture));
|
||||||
|
|
||||||
|
/* HW cursors must be 64x64, but 64x64 is huge, and no cursor theme actually uses
|
||||||
|
that, so themed cursors must be padded with transparent pixels to fill the
|
||||||
|
overlay. This is trivial if we have CPU access to the data, but it's not
|
||||||
|
possible if the buffer is in GPU memory (and possibly tiled too), so if we
|
||||||
|
don't get the right size, we fallback to GL.
|
||||||
|
*/
|
||||||
|
if (width != 64 || height != 64)
|
||||||
|
{
|
||||||
|
meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n");
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tracker->gbm)
|
||||||
|
{
|
||||||
|
self->bo = gbm_bo_import (tracker->gbm, GBM_BO_IMPORT_WL_BUFFER,
|
||||||
|
buffer, GBM_BO_USE_CURSOR_64X64);
|
||||||
|
if (!self->bo)
|
||||||
|
meta_warning ("Importing HW cursor from wl_buffer failed\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_cursor_tracker_init (MetaCursorTracker *self)
|
meta_cursor_tracker_init (MetaCursorTracker *self)
|
||||||
{
|
{
|
||||||
@@ -85,8 +501,8 @@ meta_cursor_tracker_finalize (GObject *object)
|
|||||||
meta_cursor_reference_unref (self->root_cursor);
|
meta_cursor_reference_unref (self->root_cursor);
|
||||||
|
|
||||||
for (i = 0; i < META_CURSOR_LAST; i++)
|
for (i = 0; i < META_CURSOR_LAST; i++)
|
||||||
if (self->theme_cursors[i])
|
if (self->default_cursors[i])
|
||||||
meta_cursor_reference_unref (self->theme_cursors[i]);
|
meta_cursor_reference_unref (self->default_cursors[i]);
|
||||||
|
|
||||||
if (self->pipeline)
|
if (self->pipeline)
|
||||||
cogl_object_unref (self->pipeline);
|
cogl_object_unref (self->pipeline);
|
||||||
@@ -153,9 +569,6 @@ make_wayland_cursor_tracker (MetaScreen *screen)
|
|||||||
|
|
||||||
compositor = meta_wayland_compositor_get_default ();
|
compositor = meta_wayland_compositor_get_default ();
|
||||||
compositor->seat->cursor_tracker = self;
|
compositor->seat->cursor_tracker = self;
|
||||||
meta_cursor_tracker_update_position (self,
|
|
||||||
wl_fixed_to_int (compositor->seat->pointer.x),
|
|
||||||
wl_fixed_to_int (compositor->seat->pointer.y));
|
|
||||||
|
|
||||||
#if defined(CLUTTER_WINDOWING_EGL)
|
#if defined(CLUTTER_WINDOWING_EGL)
|
||||||
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
|
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
|
||||||
@@ -244,22 +657,6 @@ meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
|
|||||||
return TRUE;
|
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
|
static void
|
||||||
ensure_xfixes_cursor (MetaCursorTracker *tracker)
|
ensure_xfixes_cursor (MetaCursorTracker *tracker)
|
||||||
{
|
{
|
||||||
@@ -316,9 +713,10 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
|
|||||||
|
|
||||||
if (sprite != NULL)
|
if (sprite != NULL)
|
||||||
{
|
{
|
||||||
MetaCursorReference *cursor = meta_cursor_reference_take_texture (sprite,
|
MetaCursorReference *cursor = meta_cursor_reference_take_texture (sprite);
|
||||||
cursor_image->xhot,
|
cursor->hot_x = cursor_image->xhot;
|
||||||
cursor_image->yhot);
|
cursor->hot_y = cursor_image->yhot;
|
||||||
|
|
||||||
set_window_cursor (tracker, TRUE, cursor);
|
set_window_cursor (tracker, TRUE, cursor);
|
||||||
}
|
}
|
||||||
XFree (cursor_image);
|
XFree (cursor_image);
|
||||||
@@ -338,7 +736,7 @@ meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker)
|
|||||||
ensure_xfixes_cursor (tracker);
|
ensure_xfixes_cursor (tracker);
|
||||||
|
|
||||||
if (tracker->displayed_cursor)
|
if (tracker->displayed_cursor)
|
||||||
return meta_cursor_reference_get_cogl_texture (tracker->displayed_cursor, NULL, NULL);
|
return COGL_TEXTURE (tracker->displayed_cursor->texture);
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -361,7 +759,13 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
|
|||||||
ensure_xfixes_cursor (tracker);
|
ensure_xfixes_cursor (tracker);
|
||||||
|
|
||||||
if (tracker->displayed_cursor)
|
if (tracker->displayed_cursor)
|
||||||
meta_cursor_reference_get_cogl_texture (tracker->displayed_cursor, x, y);
|
{
|
||||||
|
MetaCursorReference *displayed_cursor = tracker->displayed_cursor;
|
||||||
|
if (x)
|
||||||
|
*x = displayed_cursor->hot_x;
|
||||||
|
if (y)
|
||||||
|
*y = displayed_cursor->hot_y;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (x)
|
if (x)
|
||||||
@@ -371,21 +775,43 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static MetaCursorReference *
|
||||||
|
ensure_wayland_cursor (MetaCursorTracker *tracker,
|
||||||
|
MetaCursor cursor)
|
||||||
|
{
|
||||||
|
if (!tracker->default_cursors[cursor])
|
||||||
|
{
|
||||||
|
tracker->default_cursors[cursor] = meta_cursor_reference_from_theme (tracker, cursor);
|
||||||
|
if (!tracker->default_cursors[cursor])
|
||||||
|
meta_warning ("Failed to load cursor from theme\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return meta_cursor_reference_ref (tracker->default_cursors[cursor]);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker,
|
meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker,
|
||||||
MetaCursorReference *cursor)
|
MetaCursor cursor)
|
||||||
{
|
{
|
||||||
g_clear_pointer (&tracker->grab_cursor, meta_cursor_reference_unref);
|
g_clear_pointer (&tracker->grab_cursor, meta_cursor_reference_unref);
|
||||||
if (cursor)
|
if (cursor != META_CURSOR_DEFAULT)
|
||||||
tracker->grab_cursor = meta_cursor_reference_ref (cursor);
|
tracker->grab_cursor = ensure_wayland_cursor (tracker, cursor);
|
||||||
|
|
||||||
sync_cursor (tracker);
|
sync_cursor (tracker);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
|
meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
|
||||||
MetaCursorReference *cursor)
|
struct wl_resource *buffer,
|
||||||
|
int hot_x,
|
||||||
|
int hot_y)
|
||||||
{
|
{
|
||||||
|
MetaCursorReference *cursor;
|
||||||
|
|
||||||
|
if (buffer)
|
||||||
|
cursor = meta_cursor_reference_from_buffer (tracker, buffer, hot_x, hot_y);
|
||||||
|
else
|
||||||
|
cursor = NULL;
|
||||||
|
|
||||||
set_window_cursor (tracker, TRUE, cursor);
|
set_window_cursor (tracker, TRUE, cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -396,23 +822,26 @@ meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
|
meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
|
||||||
MetaCursorReference *cursor)
|
MetaCursor cursor)
|
||||||
{
|
{
|
||||||
g_clear_pointer (&tracker->root_cursor, meta_cursor_reference_unref);
|
Cursor xcursor;
|
||||||
if (cursor)
|
MetaDisplay *display = tracker->screen->display;
|
||||||
tracker->root_cursor = meta_cursor_reference_ref (cursor);
|
|
||||||
|
|
||||||
sync_cursor (tracker);
|
/* First create a cursor for X11 applications that don't specify their own */
|
||||||
}
|
xcursor = meta_display_create_x_cursor (display, cursor);
|
||||||
|
|
||||||
static gboolean
|
XDefineCursor (display->xdisplay, tracker->screen->xroot, xcursor);
|
||||||
should_have_hw_cursor (MetaCursorTracker *tracker)
|
XFlush (display->xdisplay);
|
||||||
{
|
XFreeCursor (display->xdisplay, xcursor);
|
||||||
if (tracker->displayed_cursor)
|
|
||||||
return (meta_cursor_reference_get_gbm_bo (tracker->displayed_cursor, NULL, NULL) != NULL);
|
/* Now update the real root cursor */
|
||||||
else
|
if (meta_is_wayland_compositor ())
|
||||||
return FALSE;
|
{
|
||||||
|
g_clear_pointer (&tracker->root_cursor, meta_cursor_reference_unref);
|
||||||
|
tracker->root_cursor = ensure_wayland_cursor (tracker, cursor);
|
||||||
|
sync_cursor (tracker);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -423,7 +852,7 @@ update_hw_cursor (MetaCursorTracker *tracker)
|
|||||||
unsigned int i, n_crtcs;
|
unsigned int i, n_crtcs;
|
||||||
gboolean enabled;
|
gboolean enabled;
|
||||||
|
|
||||||
enabled = should_have_hw_cursor (tracker);
|
enabled = tracker->displayed_cursor && tracker->displayed_cursor->bo != NULL;
|
||||||
tracker->has_hw_cursor = enabled;
|
tracker->has_hw_cursor = enabled;
|
||||||
|
|
||||||
monitors = meta_monitor_manager_get ();
|
monitors = meta_monitor_manager_get ();
|
||||||
@@ -484,23 +913,6 @@ get_displayed_cursor (MetaCursorTracker *tracker)
|
|||||||
return tracker->root_cursor;
|
return tracker->root_cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
update_displayed_cursor (MetaCursorTracker *tracker)
|
|
||||||
{
|
|
||||||
if (meta_is_wayland_compositor ())
|
|
||||||
{
|
|
||||||
if (tracker->displayed_cursor)
|
|
||||||
{
|
|
||||||
CoglTexture *texture = meta_cursor_reference_get_cogl_texture (tracker->displayed_cursor, NULL, NULL);
|
|
||||||
cogl_pipeline_set_layer_texture (tracker->pipeline, 0, texture);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
cogl_pipeline_set_layer_texture (tracker->pipeline, 0, NULL);
|
|
||||||
|
|
||||||
update_hw_cursor (tracker);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sync_displayed_cursor (MetaCursorTracker *tracker)
|
sync_displayed_cursor (MetaCursorTracker *tracker)
|
||||||
{
|
{
|
||||||
@@ -513,7 +925,16 @@ sync_displayed_cursor (MetaCursorTracker *tracker)
|
|||||||
if (displayed_cursor)
|
if (displayed_cursor)
|
||||||
tracker->displayed_cursor = meta_cursor_reference_ref (displayed_cursor);
|
tracker->displayed_cursor = meta_cursor_reference_ref (displayed_cursor);
|
||||||
|
|
||||||
update_displayed_cursor (tracker);
|
if (meta_is_wayland_compositor ())
|
||||||
|
{
|
||||||
|
if (displayed_cursor)
|
||||||
|
cogl_pipeline_set_layer_texture (tracker->pipeline, 0, COGL_TEXTURE (displayed_cursor->texture));
|
||||||
|
else
|
||||||
|
cogl_pipeline_set_layer_texture (tracker->pipeline, 0, NULL);
|
||||||
|
|
||||||
|
update_hw_cursor (tracker);
|
||||||
|
}
|
||||||
|
|
||||||
g_signal_emit (tracker, signals[CURSOR_CHANGED], 0);
|
g_signal_emit (tracker, signals[CURSOR_CHANGED], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -526,13 +947,14 @@ meta_cursor_tracker_queue_redraw (MetaCursorTracker *tracker)
|
|||||||
|
|
||||||
g_assert (meta_is_wayland_compositor ());
|
g_assert (meta_is_wayland_compositor ());
|
||||||
|
|
||||||
/* Clear the location the cursor was at before, if we need to. */
|
|
||||||
if (tracker->previous_is_valid)
|
if (tracker->previous_is_valid)
|
||||||
{
|
{
|
||||||
clip.x = tracker->previous_rect.x;
|
cairo_rectangle_int_t clip = {
|
||||||
clip.y = tracker->previous_rect.y;
|
.x = tracker->previous_rect.x,
|
||||||
clip.width = tracker->previous_rect.width;
|
.y = tracker->previous_rect.y,
|
||||||
clip.height = tracker->previous_rect.height;
|
.width = tracker->previous_rect.width,
|
||||||
|
.height = tracker->previous_rect.height
|
||||||
|
};
|
||||||
clutter_actor_queue_redraw_with_clip (stage, &clip);
|
clutter_actor_queue_redraw_with_clip (stage, &clip);
|
||||||
tracker->previous_is_valid = FALSE;
|
tracker->previous_is_valid = FALSE;
|
||||||
}
|
}
|
||||||
@@ -557,15 +979,10 @@ sync_cursor (MetaCursorTracker *tracker)
|
|||||||
|
|
||||||
if (displayed_cursor)
|
if (displayed_cursor)
|
||||||
{
|
{
|
||||||
CoglTexture *texture;
|
tracker->current_rect.x = tracker->current_x - displayed_cursor->hot_x;
|
||||||
int hot_x, hot_y;
|
tracker->current_rect.y = tracker->current_y - displayed_cursor->hot_y;
|
||||||
|
tracker->current_rect.width = cogl_texture_get_width (COGL_TEXTURE (displayed_cursor->texture));
|
||||||
texture = meta_cursor_reference_get_cogl_texture (displayed_cursor, &hot_x, &hot_y);
|
tracker->current_rect.height = cogl_texture_get_height (COGL_TEXTURE (displayed_cursor->texture));
|
||||||
|
|
||||||
tracker->current_rect.x = tracker->current_x - hot_x;
|
|
||||||
tracker->current_rect.y = tracker->current_y - hot_y;
|
|
||||||
tracker->current_rect.width = cogl_texture_get_width (COGL_TEXTURE (texture));
|
|
||||||
tracker->current_rect.height = cogl_texture_get_height (COGL_TEXTURE (texture));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -626,16 +1043,15 @@ meta_cursor_tracker_set_crtc_has_hw_cursor (MetaCursorTracker *tracker,
|
|||||||
if (has)
|
if (has)
|
||||||
{
|
{
|
||||||
MetaCursorReference *displayed_cursor = tracker->displayed_cursor;
|
MetaCursorReference *displayed_cursor = tracker->displayed_cursor;
|
||||||
struct gbm_bo *bo;
|
|
||||||
union gbm_bo_handle handle;
|
union gbm_bo_handle handle;
|
||||||
int width, height;
|
int width, height;
|
||||||
int hot_x, hot_y;
|
int hot_x, hot_y;
|
||||||
|
|
||||||
bo = meta_cursor_reference_get_gbm_bo (displayed_cursor, &hot_x, &hot_y);
|
handle = gbm_bo_get_handle (displayed_cursor->bo);
|
||||||
|
width = gbm_bo_get_width (displayed_cursor->bo);
|
||||||
handle = gbm_bo_get_handle (bo);
|
height = gbm_bo_get_height (displayed_cursor->bo);
|
||||||
width = gbm_bo_get_width (bo);
|
hot_x = displayed_cursor->hot_x;
|
||||||
height = gbm_bo_get_height (bo);
|
hot_y = displayed_cursor->hot_y;
|
||||||
|
|
||||||
drmModeSetCursor2 (tracker->drm_fd, crtc->crtc_id, handle.u32,
|
drmModeSetCursor2 (tracker->drm_fd, crtc->crtc_id, handle.u32,
|
||||||
width, height, hot_x, hot_y);
|
width, height, hot_x, hot_y);
|
||||||
@@ -658,13 +1074,12 @@ get_pointer_position_gdk (int *x,
|
|||||||
GdkScreen *gscreen;
|
GdkScreen *gscreen;
|
||||||
|
|
||||||
gmanager = gdk_display_get_device_manager (gdk_display_get_default ());
|
gmanager = gdk_display_get_device_manager (gdk_display_get_default ());
|
||||||
gdevice = gdk_x11_device_manager_lookup (gmanager, META_VIRTUAL_CORE_POINTER_ID);
|
gdevice = gdk_device_manager_get_client_pointer (gmanager);
|
||||||
|
|
||||||
gdk_device_get_position (gdevice, &gscreen, x, y);
|
gdk_device_get_position (gdevice, &gscreen, x, y);
|
||||||
if (mods)
|
gdk_device_get_state (gdevice,
|
||||||
gdk_device_get_state (gdevice,
|
gdk_screen_get_root_window (gscreen),
|
||||||
gdk_screen_get_root_window (gscreen),
|
NULL, (GdkModifierType*)mods);
|
||||||
NULL, (GdkModifierType*)mods);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -680,12 +1095,9 @@ get_pointer_position_clutter (int *x,
|
|||||||
cdevice = clutter_device_manager_get_core_device (cmanager, CLUTTER_POINTER_DEVICE);
|
cdevice = clutter_device_manager_get_core_device (cmanager, CLUTTER_POINTER_DEVICE);
|
||||||
|
|
||||||
clutter_input_device_get_coords (cdevice, NULL, &point);
|
clutter_input_device_get_coords (cdevice, NULL, &point);
|
||||||
if (x)
|
*x = point.x;
|
||||||
*x = point.x;
|
*y = point.y;
|
||||||
if (y)
|
*mods = clutter_input_device_get_modifier_state (cdevice);
|
||||||
*y = point.y;
|
|
||||||
if (mods)
|
|
||||||
*mods = clutter_input_device_get_modifier_state (cdevice);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -727,12 +1139,3 @@ meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker,
|
|||||||
tracker->screen->xroot);
|
tracker->screen->xroot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
meta_cursor_tracker_force_update (MetaCursorTracker *tracker)
|
|
||||||
{
|
|
||||||
g_assert (meta_is_wayland_compositor ());
|
|
||||||
|
|
||||||
update_hw_cursor (tracker);
|
|
||||||
sync_cursor (tracker);
|
|
||||||
}
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2013 Red Hat, Inc.
|
* Copyright 2013 Red Hat, Inc.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License as
|
* modify it under the terms of the GNU General Public License as
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
* General Public License for more details.
|
* General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
@@ -20,9 +20,10 @@
|
|||||||
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
|
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef META_IDLE_MONITOR_DBUS_H
|
#include <meta/meta-idle-monitor.h>
|
||||||
#define META_IDLE_MONITOR_DBUS_H
|
|
||||||
|
void meta_idle_monitor_handle_xevent_all (XEvent *xevent);
|
||||||
|
|
||||||
|
void meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor);
|
||||||
|
|
||||||
void meta_idle_monitor_init_dbus (void);
|
void meta_idle_monitor_init_dbus (void);
|
||||||
|
|
||||||
#endif
|
|
||||||
996
src/core/meta-idle-monitor.c
Normal file
996
src/core/meta-idle-monitor.c
Normal file
@@ -0,0 +1,996 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2013 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
|
||||||
|
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:idle-monitor
|
||||||
|
* @title: MetaIdleMonitor
|
||||||
|
* @short_description: Mutter idle counter (similar to X's IDLETIME)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <clutter/clutter.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/extensions/sync.h>
|
||||||
|
|
||||||
|
#include <meta/util.h>
|
||||||
|
#include <meta/main.h>
|
||||||
|
#include <meta/meta-idle-monitor.h>
|
||||||
|
#include "display-private.h"
|
||||||
|
#include "meta-idle-monitor-private.h"
|
||||||
|
#include "meta-dbus-idle-monitor.h"
|
||||||
|
|
||||||
|
G_STATIC_ASSERT(sizeof(unsigned long) == sizeof(gpointer));
|
||||||
|
|
||||||
|
struct _MetaIdleMonitor
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
|
||||||
|
GHashTable *watches;
|
||||||
|
GHashTable *alarms;
|
||||||
|
int device_id;
|
||||||
|
|
||||||
|
/* X11 implementation */
|
||||||
|
Display *display;
|
||||||
|
int sync_event_base;
|
||||||
|
XSyncCounter counter;
|
||||||
|
XSyncAlarm user_active_alarm;
|
||||||
|
|
||||||
|
/* Wayland implementation */
|
||||||
|
guint64 last_event_time;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _MetaIdleMonitorClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
MetaIdleMonitor *monitor;
|
||||||
|
guint id;
|
||||||
|
MetaIdleMonitorWatchFunc callback;
|
||||||
|
gpointer user_data;
|
||||||
|
GDestroyNotify notify;
|
||||||
|
guint64 timeout_msec;
|
||||||
|
|
||||||
|
/* x11 */
|
||||||
|
XSyncAlarm xalarm;
|
||||||
|
int idle_source_id;
|
||||||
|
|
||||||
|
/* wayland */
|
||||||
|
GSource *timeout_source;
|
||||||
|
} MetaIdleMonitorWatch;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
PROP_DEVICE_ID,
|
||||||
|
PROP_LAST,
|
||||||
|
};
|
||||||
|
|
||||||
|
static GParamSpec *obj_props[PROP_LAST];
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (MetaIdleMonitor, meta_idle_monitor, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
static MetaIdleMonitor *device_monitors[256];
|
||||||
|
static int device_id_max;
|
||||||
|
|
||||||
|
static gint64
|
||||||
|
_xsyncvalue_to_int64 (XSyncValue value)
|
||||||
|
{
|
||||||
|
return ((guint64) XSyncValueHigh32 (value)) << 32
|
||||||
|
| (guint64) XSyncValueLow32 (value);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GUINT64_TO_XSYNCVALUE(value, ret) XSyncIntsToValue (ret, (value) & 0xFFFFFFFF, ((guint64)(value)) >> 32)
|
||||||
|
|
||||||
|
static void
|
||||||
|
fire_watch (MetaIdleMonitorWatch *watch)
|
||||||
|
{
|
||||||
|
MetaIdleMonitor *monitor;
|
||||||
|
guint id;
|
||||||
|
gboolean is_user_active_watch;
|
||||||
|
|
||||||
|
monitor = watch->monitor;
|
||||||
|
g_object_ref (monitor);
|
||||||
|
|
||||||
|
if (watch->idle_source_id)
|
||||||
|
{
|
||||||
|
g_source_remove (watch->idle_source_id);
|
||||||
|
watch->idle_source_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
id = watch->id;
|
||||||
|
is_user_active_watch = (watch->timeout_msec == 0);
|
||||||
|
|
||||||
|
if (watch->callback)
|
||||||
|
watch->callback (monitor, id, watch->user_data);
|
||||||
|
|
||||||
|
if (is_user_active_watch)
|
||||||
|
meta_idle_monitor_remove_watch (monitor, id);
|
||||||
|
|
||||||
|
g_object_unref (monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
static XSyncAlarm
|
||||||
|
_xsync_alarm_set (MetaIdleMonitor *monitor,
|
||||||
|
XSyncTestType test_type,
|
||||||
|
guint64 interval,
|
||||||
|
gboolean want_events)
|
||||||
|
{
|
||||||
|
XSyncAlarmAttributes attr;
|
||||||
|
XSyncValue delta;
|
||||||
|
guint flags;
|
||||||
|
|
||||||
|
flags = XSyncCACounter | XSyncCAValueType | XSyncCATestType |
|
||||||
|
XSyncCAValue | XSyncCADelta | XSyncCAEvents;
|
||||||
|
|
||||||
|
XSyncIntToValue (&delta, 0);
|
||||||
|
attr.trigger.counter = monitor->counter;
|
||||||
|
attr.trigger.value_type = XSyncAbsolute;
|
||||||
|
attr.delta = delta;
|
||||||
|
attr.events = want_events;
|
||||||
|
|
||||||
|
GUINT64_TO_XSYNCVALUE (interval, &attr.trigger.wait_value);
|
||||||
|
attr.trigger.test_type = test_type;
|
||||||
|
return XSyncCreateAlarm (monitor->display, flags, &attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ensure_alarm_rescheduled (Display *dpy,
|
||||||
|
XSyncAlarm alarm)
|
||||||
|
{
|
||||||
|
XSyncAlarmAttributes attr;
|
||||||
|
|
||||||
|
/* Some versions of Xorg have an issue where alarms aren't
|
||||||
|
* always rescheduled. Calling XSyncChangeAlarm, even
|
||||||
|
* without any attributes, will reschedule the alarm. */
|
||||||
|
XSyncChangeAlarm (dpy, alarm, 0, &attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_alarm_enabled (Display *dpy,
|
||||||
|
XSyncAlarm alarm,
|
||||||
|
gboolean enabled)
|
||||||
|
{
|
||||||
|
XSyncAlarmAttributes attr;
|
||||||
|
attr.events = enabled;
|
||||||
|
XSyncChangeAlarm (dpy, alarm, XSyncCAEvents, &attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
check_x11_watch (gpointer data,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
MetaIdleMonitorWatch *watch = data;
|
||||||
|
XSyncAlarm alarm = (XSyncAlarm) user_data;
|
||||||
|
|
||||||
|
if (watch->xalarm != alarm)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fire_watch (watch);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_idle_monitor_handle_xevent (MetaIdleMonitor *monitor,
|
||||||
|
XSyncAlarmNotifyEvent *alarm_event)
|
||||||
|
{
|
||||||
|
XSyncAlarm alarm;
|
||||||
|
GList *watches;
|
||||||
|
gboolean has_alarm;
|
||||||
|
|
||||||
|
if (alarm_event->state != XSyncAlarmActive)
|
||||||
|
return;
|
||||||
|
|
||||||
|
alarm = alarm_event->alarm;
|
||||||
|
|
||||||
|
has_alarm = FALSE;
|
||||||
|
|
||||||
|
if (alarm == monitor->user_active_alarm)
|
||||||
|
{
|
||||||
|
set_alarm_enabled (monitor->display,
|
||||||
|
alarm,
|
||||||
|
FALSE);
|
||||||
|
has_alarm = TRUE;
|
||||||
|
}
|
||||||
|
else if (g_hash_table_contains (monitor->alarms, (gpointer) alarm))
|
||||||
|
{
|
||||||
|
ensure_alarm_rescheduled (monitor->display,
|
||||||
|
alarm);
|
||||||
|
has_alarm = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_alarm)
|
||||||
|
{
|
||||||
|
watches = g_hash_table_get_values (monitor->watches);
|
||||||
|
|
||||||
|
g_list_foreach (watches, check_x11_watch, (gpointer) alarm);
|
||||||
|
g_list_free (watches);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_idle_monitor_handle_xevent_all (XEvent *xevent)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i <= device_id_max; i++)
|
||||||
|
if (device_monitors[i])
|
||||||
|
meta_idle_monitor_handle_xevent (device_monitors[i], (XSyncAlarmNotifyEvent*)xevent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
counter_name_for_device (int device_id)
|
||||||
|
{
|
||||||
|
if (device_id > 0)
|
||||||
|
return g_strdup_printf ("DEVICEIDLETIME %d", device_id);
|
||||||
|
|
||||||
|
return g_strdup ("IDLETIME");
|
||||||
|
}
|
||||||
|
|
||||||
|
static XSyncCounter
|
||||||
|
find_idletime_counter (MetaIdleMonitor *monitor)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int ncounters;
|
||||||
|
XSyncSystemCounter *counters;
|
||||||
|
XSyncCounter counter = None;
|
||||||
|
char *counter_name;
|
||||||
|
|
||||||
|
counter_name = counter_name_for_device (monitor->device_id);
|
||||||
|
counters = XSyncListSystemCounters (monitor->display, &ncounters);
|
||||||
|
for (i = 0; i < ncounters; i++)
|
||||||
|
{
|
||||||
|
if (counters[i].name != NULL && strcmp (counters[i].name, counter_name) == 0)
|
||||||
|
{
|
||||||
|
counter = counters[i].counter;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
XSyncFreeSystemCounterList (counters);
|
||||||
|
g_free (counter_name);
|
||||||
|
|
||||||
|
return counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
static guint32
|
||||||
|
get_next_watch_serial (void)
|
||||||
|
{
|
||||||
|
static guint32 serial = 0;
|
||||||
|
g_atomic_int_inc (&serial);
|
||||||
|
return serial;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
idle_monitor_watch_free (MetaIdleMonitorWatch *watch)
|
||||||
|
{
|
||||||
|
MetaIdleMonitor *monitor;
|
||||||
|
|
||||||
|
if (watch == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
monitor = watch->monitor;
|
||||||
|
g_object_ref (monitor);
|
||||||
|
|
||||||
|
if (watch->idle_source_id)
|
||||||
|
{
|
||||||
|
g_source_remove (watch->idle_source_id);
|
||||||
|
watch->idle_source_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (watch->notify != NULL)
|
||||||
|
watch->notify (watch->user_data);
|
||||||
|
|
||||||
|
if (watch->xalarm != monitor->user_active_alarm &&
|
||||||
|
watch->xalarm != None)
|
||||||
|
{
|
||||||
|
XSyncDestroyAlarm (monitor->display, watch->xalarm);
|
||||||
|
g_hash_table_remove (monitor->alarms, (gpointer) watch->xalarm);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (watch->timeout_source != NULL)
|
||||||
|
g_source_destroy (watch->timeout_source);
|
||||||
|
|
||||||
|
g_object_unref (monitor);
|
||||||
|
g_slice_free (MetaIdleMonitorWatch, watch);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_xsync (MetaIdleMonitor *monitor)
|
||||||
|
{
|
||||||
|
monitor->counter = find_idletime_counter (monitor);
|
||||||
|
/* IDLETIME counter not found? */
|
||||||
|
if (monitor->counter == None)
|
||||||
|
{
|
||||||
|
meta_warning ("IDLETIME counter not found\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
monitor->user_active_alarm = _xsync_alarm_set (monitor, XSyncNegativeTransition, 1, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_idle_monitor_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
MetaIdleMonitor *monitor;
|
||||||
|
|
||||||
|
monitor = META_IDLE_MONITOR (object);
|
||||||
|
|
||||||
|
g_clear_pointer (&monitor->watches, g_hash_table_destroy);
|
||||||
|
g_clear_pointer (&monitor->alarms, g_hash_table_destroy);
|
||||||
|
|
||||||
|
if (monitor->user_active_alarm != None)
|
||||||
|
{
|
||||||
|
XSyncDestroyAlarm (monitor->display, monitor->user_active_alarm);
|
||||||
|
monitor->user_active_alarm = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (meta_idle_monitor_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_idle_monitor_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_DEVICE_ID:
|
||||||
|
g_value_set_int (value, monitor->device_id);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_idle_monitor_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_DEVICE_ID:
|
||||||
|
monitor->device_id = g_value_get_int (value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_idle_monitor_constructed (GObject *object)
|
||||||
|
{
|
||||||
|
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
|
||||||
|
|
||||||
|
if (!meta_is_wayland_compositor ())
|
||||||
|
{
|
||||||
|
monitor->display = meta_get_display ()->xdisplay;
|
||||||
|
init_xsync (monitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_idle_monitor_class_init (MetaIdleMonitorClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->dispose = meta_idle_monitor_dispose;
|
||||||
|
object_class->constructed = meta_idle_monitor_constructed;
|
||||||
|
object_class->get_property = meta_idle_monitor_get_property;
|
||||||
|
object_class->set_property = meta_idle_monitor_set_property;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MetaIdleMonitor:device_id:
|
||||||
|
*
|
||||||
|
* The device to listen to idletime on.
|
||||||
|
*/
|
||||||
|
obj_props[PROP_DEVICE_ID] =
|
||||||
|
g_param_spec_int ("device-id",
|
||||||
|
"Device ID",
|
||||||
|
"The device to listen to idletime on",
|
||||||
|
0, 255, 0,
|
||||||
|
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||||
|
g_object_class_install_property (object_class, PROP_DEVICE_ID, obj_props[PROP_DEVICE_ID]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_idle_monitor_init (MetaIdleMonitor *monitor)
|
||||||
|
{
|
||||||
|
monitor->watches = g_hash_table_new_full (NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
(GDestroyNotify)idle_monitor_watch_free);
|
||||||
|
|
||||||
|
monitor->alarms = g_hash_table_new (NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ensure_device_monitor (int device_id)
|
||||||
|
{
|
||||||
|
if (device_monitors[device_id])
|
||||||
|
return;
|
||||||
|
|
||||||
|
device_monitors[device_id] = g_object_new (META_TYPE_IDLE_MONITOR, "device-id", device_id, NULL);
|
||||||
|
device_id_max = MAX (device_id_max, device_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* meta_idle_monitor_get_core:
|
||||||
|
*
|
||||||
|
* Returns: (transfer none): the #MetaIdleMonitor that tracks the server-global
|
||||||
|
* idletime for all devices. To track device-specific idletime,
|
||||||
|
* use meta_idle_monitor_get_for_device().
|
||||||
|
*/
|
||||||
|
MetaIdleMonitor *
|
||||||
|
meta_idle_monitor_get_core (void)
|
||||||
|
{
|
||||||
|
ensure_device_monitor (0);
|
||||||
|
return device_monitors[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* meta_idle_monitor_get_for_device:
|
||||||
|
* @device_id: the device to get the idle time for.
|
||||||
|
*
|
||||||
|
* Returns: (transfer none): a new #MetaIdleMonitor that tracks the
|
||||||
|
* device-specific idletime for @device. To track server-global idletime
|
||||||
|
* for all devices, use meta_idle_monitor_get_core().
|
||||||
|
*/
|
||||||
|
MetaIdleMonitor *
|
||||||
|
meta_idle_monitor_get_for_device (int device_id)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (device_id > 0 && device_id < 256, NULL);
|
||||||
|
|
||||||
|
ensure_device_monitor (device_id);
|
||||||
|
return device_monitors[device_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
wayland_dispatch_timeout (GSource *source,
|
||||||
|
GSourceFunc callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
MetaIdleMonitorWatch *watch = user_data;
|
||||||
|
|
||||||
|
fire_watch (watch);
|
||||||
|
g_source_set_ready_time (watch->timeout_source, -1);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GSourceFuncs wayland_source_funcs = {
|
||||||
|
NULL, /* prepare */
|
||||||
|
NULL, /* check */
|
||||||
|
wayland_dispatch_timeout,
|
||||||
|
NULL, /* finalize */
|
||||||
|
};
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fire_watch_idle (gpointer data)
|
||||||
|
{
|
||||||
|
MetaIdleMonitorWatch *watch = data;
|
||||||
|
|
||||||
|
watch->idle_source_id = 0;
|
||||||
|
fire_watch (watch);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MetaIdleMonitorWatch *
|
||||||
|
make_watch (MetaIdleMonitor *monitor,
|
||||||
|
guint64 timeout_msec,
|
||||||
|
MetaIdleMonitorWatchFunc callback,
|
||||||
|
gpointer user_data,
|
||||||
|
GDestroyNotify notify)
|
||||||
|
{
|
||||||
|
MetaIdleMonitorWatch *watch;
|
||||||
|
|
||||||
|
watch = g_slice_new0 (MetaIdleMonitorWatch);
|
||||||
|
watch->monitor = monitor;
|
||||||
|
watch->id = get_next_watch_serial ();
|
||||||
|
watch->callback = callback;
|
||||||
|
watch->user_data = user_data;
|
||||||
|
watch->notify = notify;
|
||||||
|
watch->timeout_msec = timeout_msec;
|
||||||
|
|
||||||
|
if (meta_is_wayland_compositor ())
|
||||||
|
{
|
||||||
|
if (timeout_msec != 0)
|
||||||
|
{
|
||||||
|
GSource *source = g_source_new (&wayland_source_funcs, sizeof (GSource));
|
||||||
|
|
||||||
|
g_source_set_callback (source, NULL, watch, NULL);
|
||||||
|
g_source_set_ready_time (source, monitor->last_event_time + timeout_msec * 1000);
|
||||||
|
g_source_attach (source, NULL);
|
||||||
|
g_source_unref (source);
|
||||||
|
|
||||||
|
watch->timeout_source = source;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (monitor->user_active_alarm != None)
|
||||||
|
{
|
||||||
|
if (timeout_msec != 0)
|
||||||
|
{
|
||||||
|
watch->xalarm = _xsync_alarm_set (monitor, XSyncPositiveTransition, timeout_msec, TRUE);
|
||||||
|
|
||||||
|
g_hash_table_add (monitor->alarms, (gpointer) watch->xalarm);
|
||||||
|
|
||||||
|
if (meta_idle_monitor_get_idletime (monitor) > (gint64)timeout_msec)
|
||||||
|
watch->idle_source_id = g_idle_add (fire_watch_idle, watch);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
watch->xalarm = monitor->user_active_alarm;
|
||||||
|
|
||||||
|
set_alarm_enabled (monitor->display, monitor->user_active_alarm, TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_hash_table_insert (monitor->watches,
|
||||||
|
GUINT_TO_POINTER (watch->id),
|
||||||
|
watch);
|
||||||
|
return watch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* meta_idle_monitor_add_idle_watch:
|
||||||
|
* @monitor: A #MetaIdleMonitor
|
||||||
|
* @interval_msec: The idletime interval, in milliseconds
|
||||||
|
* @callback: (allow-none): The callback to call when the user has
|
||||||
|
* accumulated @interval_msec milliseconds of idle time.
|
||||||
|
* @user_data: (allow-none): The user data to pass to the callback
|
||||||
|
* @notify: A #GDestroyNotify
|
||||||
|
*
|
||||||
|
* Returns: a watch id
|
||||||
|
*
|
||||||
|
* Adds a watch for a specific idle time. The callback will be called
|
||||||
|
* when the user has accumulated @interval_msec milliseconds of idle time.
|
||||||
|
* This function will return an ID that can either be passed to
|
||||||
|
* meta_idle_monitor_remove_watch(), or can be used to tell idle time
|
||||||
|
* watches apart if you have more than one.
|
||||||
|
*
|
||||||
|
* Also note that this function will only care about positive transitions
|
||||||
|
* (user's idle time exceeding a certain time). If you want to know about
|
||||||
|
* when the user has become active, use
|
||||||
|
* meta_idle_monitor_add_user_active_watch().
|
||||||
|
*/
|
||||||
|
guint
|
||||||
|
meta_idle_monitor_add_idle_watch (MetaIdleMonitor *monitor,
|
||||||
|
guint64 interval_msec,
|
||||||
|
MetaIdleMonitorWatchFunc callback,
|
||||||
|
gpointer user_data,
|
||||||
|
GDestroyNotify notify)
|
||||||
|
{
|
||||||
|
MetaIdleMonitorWatch *watch;
|
||||||
|
|
||||||
|
g_return_val_if_fail (META_IS_IDLE_MONITOR (monitor), 0);
|
||||||
|
g_return_val_if_fail (interval_msec > 0, 0);
|
||||||
|
|
||||||
|
watch = make_watch (monitor,
|
||||||
|
interval_msec,
|
||||||
|
callback,
|
||||||
|
user_data,
|
||||||
|
notify);
|
||||||
|
|
||||||
|
return watch->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* meta_idle_monitor_add_user_active_watch:
|
||||||
|
* @monitor: A #MetaIdleMonitor
|
||||||
|
* @callback: (allow-none): The callback to call when the user is
|
||||||
|
* active again.
|
||||||
|
* @user_data: (allow-none): The user data to pass to the callback
|
||||||
|
* @notify: A #GDestroyNotify
|
||||||
|
*
|
||||||
|
* Returns: a watch id
|
||||||
|
*
|
||||||
|
* Add a one-time watch to know when the user is active again.
|
||||||
|
* Note that this watch is one-time and will de-activate after the
|
||||||
|
* function is called, for efficiency purposes. It's most convenient
|
||||||
|
* to call this when an idle watch, as added by
|
||||||
|
* meta_idle_monitor_add_idle_watch(), has triggered.
|
||||||
|
*/
|
||||||
|
guint
|
||||||
|
meta_idle_monitor_add_user_active_watch (MetaIdleMonitor *monitor,
|
||||||
|
MetaIdleMonitorWatchFunc callback,
|
||||||
|
gpointer user_data,
|
||||||
|
GDestroyNotify notify)
|
||||||
|
{
|
||||||
|
MetaIdleMonitorWatch *watch;
|
||||||
|
|
||||||
|
g_return_val_if_fail (META_IS_IDLE_MONITOR (monitor), 0);
|
||||||
|
|
||||||
|
watch = make_watch (monitor,
|
||||||
|
0,
|
||||||
|
callback,
|
||||||
|
user_data,
|
||||||
|
notify);
|
||||||
|
|
||||||
|
return watch->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* meta_idle_monitor_remove_watch:
|
||||||
|
* @monitor: A #MetaIdleMonitor
|
||||||
|
* @id: A watch ID
|
||||||
|
*
|
||||||
|
* Removes an idle time watcher, previously added by
|
||||||
|
* meta_idle_monitor_add_idle_watch() or
|
||||||
|
* meta_idle_monitor_add_user_active_watch().
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
meta_idle_monitor_remove_watch (MetaIdleMonitor *monitor,
|
||||||
|
guint id)
|
||||||
|
{
|
||||||
|
g_return_if_fail (META_IS_IDLE_MONITOR (monitor));
|
||||||
|
|
||||||
|
g_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)
|
||||||
|
{
|
||||||
|
XSyncValue value;
|
||||||
|
|
||||||
|
if (meta_is_wayland_compositor ())
|
||||||
|
{
|
||||||
|
return (g_get_monotonic_time () - monitor->last_event_time) / 1000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!XSyncQueryCounter (monitor->display, monitor->counter, &value))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return _xsyncvalue_to_int64 (value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
MetaIdleMonitor *monitor;
|
||||||
|
GList *fired_watches;
|
||||||
|
} CheckWaylandClosure;
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
check_wayland_watch (gpointer key,
|
||||||
|
gpointer value,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
MetaIdleMonitorWatch *watch = value;
|
||||||
|
CheckWaylandClosure *closure = user_data;
|
||||||
|
gboolean steal;
|
||||||
|
|
||||||
|
if (watch->timeout_msec == 0)
|
||||||
|
{
|
||||||
|
closure->fired_watches = g_list_prepend (closure->fired_watches, watch);
|
||||||
|
steal = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_source_set_ready_time (watch->timeout_source,
|
||||||
|
closure->monitor->last_event_time +
|
||||||
|
watch->timeout_msec * 1000);
|
||||||
|
steal = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return steal;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fire_wayland_watch (gpointer watch,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
fire_watch (watch);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor)
|
||||||
|
{
|
||||||
|
CheckWaylandClosure closure;
|
||||||
|
|
||||||
|
monitor->last_event_time = g_get_monotonic_time ();
|
||||||
|
|
||||||
|
closure.monitor = monitor;
|
||||||
|
closure.fired_watches = NULL;
|
||||||
|
g_hash_table_foreach_steal (monitor->watches, check_wayland_watch, &closure);
|
||||||
|
|
||||||
|
g_list_foreach (closure.fired_watches, fire_wayland_watch, NULL);
|
||||||
|
g_list_free (closure.fired_watches);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
handle_get_idletime (MetaDBusIdleMonitor *skeleton,
|
||||||
|
GDBusMethodInvocation *invocation,
|
||||||
|
MetaIdleMonitor *monitor)
|
||||||
|
{
|
||||||
|
guint64 idletime;
|
||||||
|
|
||||||
|
idletime = meta_idle_monitor_get_idletime (monitor);
|
||||||
|
meta_dbus_idle_monitor_complete_get_idletime (skeleton, invocation, idletime);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
MetaDBusIdleMonitor *dbus_monitor;
|
||||||
|
MetaIdleMonitor *monitor;
|
||||||
|
char *dbus_name;
|
||||||
|
guint watch_id;
|
||||||
|
guint name_watcher_id;
|
||||||
|
} DBusWatch;
|
||||||
|
|
||||||
|
static void
|
||||||
|
destroy_dbus_watch (gpointer data)
|
||||||
|
{
|
||||||
|
DBusWatch *watch = data;
|
||||||
|
|
||||||
|
g_object_unref (watch->dbus_monitor);
|
||||||
|
g_object_unref (watch->monitor);
|
||||||
|
g_free (watch->dbus_name);
|
||||||
|
g_bus_unwatch_name (watch->name_watcher_id);
|
||||||
|
|
||||||
|
g_slice_free (DBusWatch, watch);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dbus_idle_callback (MetaIdleMonitor *monitor,
|
||||||
|
guint watch_id,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
DBusWatch *watch = user_data;
|
||||||
|
GDBusInterfaceSkeleton *skeleton = G_DBUS_INTERFACE_SKELETON (watch->dbus_monitor);
|
||||||
|
|
||||||
|
g_dbus_connection_emit_signal (g_dbus_interface_skeleton_get_connection (skeleton),
|
||||||
|
watch->dbus_name,
|
||||||
|
g_dbus_interface_skeleton_get_object_path (skeleton),
|
||||||
|
"org.gnome.Mutter.IdleMonitor",
|
||||||
|
"WatchFired",
|
||||||
|
g_variant_new ("(u)", watch_id),
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
name_vanished_callback (GDBusConnection *connection,
|
||||||
|
const char *name,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
DBusWatch *watch = user_data;
|
||||||
|
|
||||||
|
meta_idle_monitor_remove_watch (watch->monitor, watch->watch_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DBusWatch *
|
||||||
|
make_dbus_watch (MetaDBusIdleMonitor *skeleton,
|
||||||
|
GDBusMethodInvocation *invocation,
|
||||||
|
MetaIdleMonitor *monitor)
|
||||||
|
{
|
||||||
|
DBusWatch *watch;
|
||||||
|
|
||||||
|
watch = g_slice_new (DBusWatch);
|
||||||
|
watch->dbus_monitor = g_object_ref (skeleton);
|
||||||
|
watch->monitor = g_object_ref (monitor);
|
||||||
|
watch->dbus_name = g_strdup (g_dbus_method_invocation_get_sender (invocation));
|
||||||
|
watch->name_watcher_id = g_bus_watch_name_on_connection (g_dbus_method_invocation_get_connection (invocation),
|
||||||
|
watch->dbus_name,
|
||||||
|
G_BUS_NAME_WATCHER_FLAGS_NONE,
|
||||||
|
NULL, /* appeared */
|
||||||
|
name_vanished_callback,
|
||||||
|
watch, NULL);
|
||||||
|
|
||||||
|
return watch;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
handle_add_idle_watch (MetaDBusIdleMonitor *skeleton,
|
||||||
|
GDBusMethodInvocation *invocation,
|
||||||
|
guint64 interval,
|
||||||
|
MetaIdleMonitor *monitor)
|
||||||
|
{
|
||||||
|
DBusWatch *watch;
|
||||||
|
|
||||||
|
watch = make_dbus_watch (skeleton, invocation, monitor);
|
||||||
|
watch->watch_id = meta_idle_monitor_add_idle_watch (monitor, interval,
|
||||||
|
dbus_idle_callback, watch, destroy_dbus_watch);
|
||||||
|
|
||||||
|
meta_dbus_idle_monitor_complete_add_idle_watch (skeleton, invocation, watch->watch_id);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
handle_add_user_active_watch (MetaDBusIdleMonitor *skeleton,
|
||||||
|
GDBusMethodInvocation *invocation,
|
||||||
|
MetaIdleMonitor *monitor)
|
||||||
|
{
|
||||||
|
DBusWatch *watch;
|
||||||
|
|
||||||
|
watch = make_dbus_watch (skeleton, invocation, monitor);
|
||||||
|
watch->watch_id = meta_idle_monitor_add_user_active_watch (monitor,
|
||||||
|
dbus_idle_callback, watch,
|
||||||
|
destroy_dbus_watch);
|
||||||
|
|
||||||
|
meta_dbus_idle_monitor_complete_add_user_active_watch (skeleton, invocation, watch->watch_id);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
handle_remove_watch (MetaDBusIdleMonitor *skeleton,
|
||||||
|
GDBusMethodInvocation *invocation,
|
||||||
|
guint id,
|
||||||
|
MetaIdleMonitor *monitor)
|
||||||
|
{
|
||||||
|
meta_idle_monitor_remove_watch (monitor, id);
|
||||||
|
meta_dbus_idle_monitor_complete_remove_watch (skeleton, invocation);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
create_monitor_skeleton (GDBusObjectManagerServer *manager,
|
||||||
|
MetaIdleMonitor *monitor,
|
||||||
|
const char *path)
|
||||||
|
{
|
||||||
|
MetaDBusIdleMonitor *skeleton;
|
||||||
|
MetaDBusObjectSkeleton *object;
|
||||||
|
|
||||||
|
skeleton = meta_dbus_idle_monitor_skeleton_new ();
|
||||||
|
g_signal_connect_object (skeleton, "handle-add-idle-watch",
|
||||||
|
G_CALLBACK (handle_add_idle_watch), monitor, 0);
|
||||||
|
g_signal_connect_object (skeleton, "handle-add-user-active-watch",
|
||||||
|
G_CALLBACK (handle_add_user_active_watch), monitor, 0);
|
||||||
|
g_signal_connect_object (skeleton, "handle-remove-watch",
|
||||||
|
G_CALLBACK (handle_remove_watch), monitor, 0);
|
||||||
|
g_signal_connect_object (skeleton, "handle-get-idletime",
|
||||||
|
G_CALLBACK (handle_get_idletime), monitor, 0);
|
||||||
|
|
||||||
|
object = meta_dbus_object_skeleton_new (path);
|
||||||
|
meta_dbus_object_skeleton_set_idle_monitor (object, skeleton);
|
||||||
|
|
||||||
|
g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (object));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_device_added (ClutterDeviceManager *device_manager,
|
||||||
|
ClutterInputDevice *device,
|
||||||
|
GDBusObjectManagerServer *manager)
|
||||||
|
{
|
||||||
|
|
||||||
|
MetaIdleMonitor *monitor;
|
||||||
|
int device_id;
|
||||||
|
char *path;
|
||||||
|
|
||||||
|
device_id = clutter_input_device_get_device_id (device);
|
||||||
|
monitor = meta_idle_monitor_get_for_device (device_id);
|
||||||
|
path = g_strdup_printf ("/org/gnome/Mutter/IdleMonitor/Device%d", device_id);
|
||||||
|
|
||||||
|
create_monitor_skeleton (manager, monitor, path);
|
||||||
|
g_free (path);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_device_removed (ClutterDeviceManager *device_manager,
|
||||||
|
ClutterInputDevice *device,
|
||||||
|
GDBusObjectManagerServer *manager)
|
||||||
|
{
|
||||||
|
int device_id;
|
||||||
|
char *path;
|
||||||
|
|
||||||
|
device_id = clutter_input_device_get_device_id (device);
|
||||||
|
path = g_strdup_printf ("/org/gnome/Mutter/IdleMonitor/Device%d", device_id);
|
||||||
|
g_dbus_object_manager_server_unexport (manager, path);
|
||||||
|
g_free (path);
|
||||||
|
|
||||||
|
g_clear_object (&device_monitors[device_id]);
|
||||||
|
if (device_id == device_id_max)
|
||||||
|
device_id_max--;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_bus_acquired (GDBusConnection *connection,
|
||||||
|
const char *name,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GDBusObjectManagerServer *manager;
|
||||||
|
ClutterDeviceManager *device_manager;
|
||||||
|
MetaIdleMonitor *monitor;
|
||||||
|
GSList *devices, *iter;
|
||||||
|
char *path;
|
||||||
|
|
||||||
|
manager = g_dbus_object_manager_server_new ("/org/gnome/Mutter/IdleMonitor");
|
||||||
|
|
||||||
|
/* We never clear the core monitor, as that's supposed to cumulate idle times from
|
||||||
|
all devices */
|
||||||
|
monitor = meta_idle_monitor_get_core ();
|
||||||
|
path = g_strdup ("/org/gnome/Mutter/IdleMonitor/Core");
|
||||||
|
create_monitor_skeleton (manager, monitor, path);
|
||||||
|
g_free (path);
|
||||||
|
|
||||||
|
device_manager = clutter_device_manager_get_default ();
|
||||||
|
devices = clutter_device_manager_list_devices (device_manager);
|
||||||
|
|
||||||
|
for (iter = devices; iter; iter = iter->next)
|
||||||
|
on_device_added (device_manager, iter->data, manager);
|
||||||
|
|
||||||
|
g_slist_free (devices);
|
||||||
|
|
||||||
|
g_signal_connect_object (device_manager, "device-added",
|
||||||
|
G_CALLBACK (on_device_added), manager, 0);
|
||||||
|
g_signal_connect_object (device_manager, "device-removed",
|
||||||
|
G_CALLBACK (on_device_removed), manager, 0);
|
||||||
|
|
||||||
|
g_dbus_object_manager_server_set_connection (manager, connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_name_acquired (GDBusConnection *connection,
|
||||||
|
const char *name,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
meta_verbose ("Acquired name %s\n", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_name_lost (GDBusConnection *connection,
|
||||||
|
const char *name,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
meta_verbose ("Lost or failed to acquire name %s\n", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_idle_monitor_init_dbus (void)
|
||||||
|
{
|
||||||
|
static int dbus_name_id;
|
||||||
|
|
||||||
|
if (dbus_name_id > 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dbus_name_id = g_bus_own_name (G_BUS_TYPE_SESSION,
|
||||||
|
"org.gnome.Mutter.IdleMonitor",
|
||||||
|
G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
|
||||||
|
(meta_get_replace_current_wm () ?
|
||||||
|
G_BUS_NAME_OWNER_FLAGS_REPLACE : 0),
|
||||||
|
on_bus_acquired,
|
||||||
|
on_name_acquired,
|
||||||
|
on_name_lost,
|
||||||
|
NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* This file is shared between mutter (src/core/meta-display-config-shared.h)
|
/* This file is shared between mutter (src/core/meta-xrandr-shared.h)
|
||||||
and gnome-desktop (libgnome-desktop/meta-xrandr-shared.h).
|
and gnome-desktop (libgnome-desktop/meta-xrandr-shared.h).
|
||||||
|
|
||||||
The canonical place for all changes is mutter.
|
The canonical place for all changes is mutter.
|
||||||
@@ -24,8 +24,8 @@
|
|||||||
There should be no includes in this file.
|
There should be no includes in this file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef META_DISPLAY_CONFIG_SHARED_H
|
#ifndef META_XRANDR_SHARED_H
|
||||||
#define META_DISPLAY_CONFIG_SHARED_H
|
#define META_XRANDR_SHARED_H
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
META_POWER_SAVE_UNSUPPORTED = -1,
|
META_POWER_SAVE_UNSUPPORTED = -1,
|
||||||
@@ -35,4 +35,4 @@ typedef enum {
|
|||||||
META_POWER_SAVE_OFF,
|
META_POWER_SAVE_OFF,
|
||||||
} MetaPowerSave;
|
} MetaPowerSave;
|
||||||
|
|
||||||
#endif /* META_DISPLAY_CONFIG_SHARED_H */
|
#endif
|
||||||
@@ -34,14 +34,13 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "meta-monitor-config.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
#include <libupower-glib/upower.h>
|
#include <libupower-glib/upower.h>
|
||||||
|
|
||||||
#include <meta/main.h>
|
#include <meta/main.h>
|
||||||
#include <meta/errors.h>
|
#include <meta/errors.h>
|
||||||
|
#include "monitor-private.h"
|
||||||
|
|
||||||
/* These structures represent the intended/persistent configuration,
|
/* These structures represent the intended/persistent configuration,
|
||||||
as stored in the monitors.xml file.
|
as stored in the monitors.xml file.
|
||||||
@@ -23,8 +23,6 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "meta-monitor-manager-kms.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
@@ -38,6 +36,7 @@
|
|||||||
|
|
||||||
#include <meta/main.h>
|
#include <meta/main.h>
|
||||||
#include <meta/errors.h>
|
#include <meta/errors.h>
|
||||||
|
#include "monitor-private.h"
|
||||||
#include "edid.h"
|
#include "edid.h"
|
||||||
|
|
||||||
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
|
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
|
||||||
@@ -651,7 +650,7 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
|
|||||||
state = DRM_MODE_DPMS_SUSPEND;
|
state = DRM_MODE_DPMS_SUSPEND;
|
||||||
break;
|
break;
|
||||||
case META_POWER_SAVE_OFF:
|
case META_POWER_SAVE_OFF:
|
||||||
state = DRM_MODE_DPMS_OFF;
|
state = DRM_MODE_DPMS_SUSPEND;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
@@ -43,9 +43,9 @@
|
|||||||
#include "stack-tracker.h"
|
#include "stack-tracker.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include <wayland-server.h>
|
#include <wayland-server.h>
|
||||||
|
#include "meta-xrandr-shared.h"
|
||||||
|
|
||||||
#include "meta-display-config-shared.h"
|
#include "meta-dbus-xrandr.h"
|
||||||
#include "meta-dbus-display-config.h"
|
|
||||||
|
|
||||||
typedef struct _MetaMonitorManagerClass MetaMonitorManagerClass;
|
typedef struct _MetaMonitorManagerClass MetaMonitorManagerClass;
|
||||||
typedef struct _MetaMonitorManager MetaMonitorManager;
|
typedef struct _MetaMonitorManager MetaMonitorManager;
|
||||||
@@ -227,6 +227,8 @@ struct _MetaMonitorManager
|
|||||||
CRTCs refer to stuff that can drive outputs
|
CRTCs refer to stuff that can drive outputs
|
||||||
(like encoders, but less tied to the HW),
|
(like encoders, but less tied to the HW),
|
||||||
while monitor_infos refer to logical ones.
|
while monitor_infos refer to logical ones.
|
||||||
|
|
||||||
|
See also the comment in monitor-private.h
|
||||||
*/
|
*/
|
||||||
MetaOutput *outputs;
|
MetaOutput *outputs;
|
||||||
unsigned int n_outputs;
|
unsigned int n_outputs;
|
||||||
@@ -333,6 +335,57 @@ void meta_monitor_manager_apply_configuration (MetaMonitorManager
|
|||||||
void meta_monitor_manager_confirm_configuration (MetaMonitorManager *manager,
|
void meta_monitor_manager_confirm_configuration (MetaMonitorManager *manager,
|
||||||
gboolean ok);
|
gboolean ok);
|
||||||
|
|
||||||
|
#define META_TYPE_MONITOR_MANAGER_XRANDR (meta_monitor_manager_xrandr_get_type ())
|
||||||
|
#define META_MONITOR_MANAGER_XRANDR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandr))
|
||||||
|
#define META_MONITOR_MANAGER_XRANDR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandrClass))
|
||||||
|
#define META_IS_MONITOR_MANAGER_XRANDR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_MANAGER_XRANDR))
|
||||||
|
#define META_IS_MONITOR_MANAGER_XRANDR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MONITOR_MANAGER_XRANDR))
|
||||||
|
#define META_MONITOR_MANAGER_XRANDR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandrClass))
|
||||||
|
|
||||||
|
typedef struct _MetaMonitorManagerXrandrClass MetaMonitorManagerXrandrClass;
|
||||||
|
typedef struct _MetaMonitorManagerXrandr MetaMonitorManagerXrandr;
|
||||||
|
|
||||||
|
GType meta_monitor_manager_xrandr_get_type (void);
|
||||||
|
|
||||||
|
#define META_TYPE_MONITOR_MANAGER_KMS (meta_monitor_manager_kms_get_type ())
|
||||||
|
#define META_MONITOR_MANAGER_KMS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKms))
|
||||||
|
#define META_MONITOR_MANAGER_KMS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKmsClass))
|
||||||
|
#define META_IS_MONITOR_MANAGER_KMS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_MANAGER_KMS))
|
||||||
|
#define META_IS_MONITOR_MANAGER_KMS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MONITOR_MANAGER_KMS))
|
||||||
|
#define META_MONITOR_MANAGER_KMS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKmsClass))
|
||||||
|
|
||||||
|
typedef struct _MetaMonitorManagerKmsClass MetaMonitorManagerKmsClass;
|
||||||
|
typedef struct _MetaMonitorManagerKms MetaMonitorManagerKms;
|
||||||
|
|
||||||
|
GType meta_monitor_manager_kms_get_type (void);
|
||||||
|
|
||||||
|
#define META_TYPE_MONITOR_CONFIG (meta_monitor_config_get_type ())
|
||||||
|
#define META_MONITOR_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_CONFIG, MetaMonitorConfig))
|
||||||
|
#define META_MONITOR_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_CONFIG, MetaMonitorConfigClass))
|
||||||
|
#define META_IS_MONITOR_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_CONFIG))
|
||||||
|
#define META_IS_MONITOR_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MONITOR_CONFIG))
|
||||||
|
#define META_MONITOR_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MONITOR_CONFIG, MetaMonitorConfigClass))
|
||||||
|
|
||||||
|
GType meta_monitor_config_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
MetaMonitorConfig *meta_monitor_config_new (void);
|
||||||
|
|
||||||
|
gboolean meta_monitor_config_match_current (MetaMonitorConfig *config,
|
||||||
|
MetaMonitorManager *manager);
|
||||||
|
|
||||||
|
gboolean meta_monitor_config_apply_stored (MetaMonitorConfig *config,
|
||||||
|
MetaMonitorManager *manager);
|
||||||
|
|
||||||
|
void meta_monitor_config_make_default (MetaMonitorConfig *config,
|
||||||
|
MetaMonitorManager *manager);
|
||||||
|
|
||||||
|
void meta_monitor_config_update_current (MetaMonitorConfig *config,
|
||||||
|
MetaMonitorManager *manager);
|
||||||
|
void meta_monitor_config_make_persistent (MetaMonitorConfig *config);
|
||||||
|
|
||||||
|
void meta_monitor_config_restore_previous (MetaMonitorConfig *config,
|
||||||
|
MetaMonitorManager *manager);
|
||||||
|
|
||||||
void meta_crtc_info_free (MetaCRTCInfo *info);
|
void meta_crtc_info_free (MetaCRTCInfo *info);
|
||||||
void meta_output_info_free (MetaOutputInfo *info);
|
void meta_output_info_free (MetaOutputInfo *info);
|
||||||
|
|
||||||
@@ -25,8 +25,6 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "meta-monitor-manager-xrandr.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
@@ -38,8 +36,9 @@
|
|||||||
|
|
||||||
#include <meta/main.h>
|
#include <meta/main.h>
|
||||||
#include <meta/errors.h>
|
#include <meta/errors.h>
|
||||||
|
#include "monitor-private.h"
|
||||||
|
|
||||||
#include "edid.h"
|
#include "edid.h"
|
||||||
#include "meta-monitor-config.h"
|
|
||||||
|
|
||||||
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
|
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
|
||||||
|
|
||||||
@@ -25,8 +25,6 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "meta-monitor-manager.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -35,10 +33,12 @@
|
|||||||
#include <meta/main.h>
|
#include <meta/main.h>
|
||||||
#include "util-private.h"
|
#include "util-private.h"
|
||||||
#include <meta/errors.h>
|
#include <meta/errors.h>
|
||||||
#include "meta-monitor-config.h"
|
#include "monitor-private.h"
|
||||||
#include "backends/native/meta-monitor-manager-kms.h"
|
#include "meta-wayland-private.h"
|
||||||
#include "backends/x11/meta-monitor-manager-xrandr.h"
|
|
||||||
#include "meta-monitor-manager-dummy.h"
|
#include "meta-dbus-xrandr.h"
|
||||||
|
|
||||||
|
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
CONFIRM_DISPLAY_CHANGE,
|
CONFIRM_DISPLAY_CHANGE,
|
||||||
@@ -55,11 +55,196 @@ static int signals[SIGNALS_LAST];
|
|||||||
|
|
||||||
static void meta_monitor_manager_display_config_init (MetaDBusDisplayConfigIface *iface);
|
static void meta_monitor_manager_display_config_init (MetaDBusDisplayConfigIface *iface);
|
||||||
|
|
||||||
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaMonitorManager, meta_monitor_manager, META_DBUS_TYPE_DISPLAY_CONFIG_SKELETON,
|
G_DEFINE_TYPE_WITH_CODE (MetaMonitorManager, meta_monitor_manager, META_DBUS_TYPE_DISPLAY_CONFIG_SKELETON,
|
||||||
G_IMPLEMENT_INTERFACE (META_DBUS_TYPE_DISPLAY_CONFIG, meta_monitor_manager_display_config_init));
|
G_IMPLEMENT_INTERFACE (META_DBUS_TYPE_DISPLAY_CONFIG, meta_monitor_manager_display_config_init));
|
||||||
|
|
||||||
static void initialize_dbus_interface (MetaMonitorManager *manager);
|
static void initialize_dbus_interface (MetaMonitorManager *manager);
|
||||||
|
|
||||||
|
static void
|
||||||
|
read_current_dummy (MetaMonitorManager *manager)
|
||||||
|
{
|
||||||
|
manager->max_screen_width = 65535;
|
||||||
|
manager->max_screen_height = 65535;
|
||||||
|
manager->screen_width = 1024;
|
||||||
|
manager->screen_height = 768;
|
||||||
|
|
||||||
|
manager->modes = g_new0 (MetaMonitorMode, 1);
|
||||||
|
manager->n_modes = 1;
|
||||||
|
|
||||||
|
manager->modes[0].mode_id = 0;
|
||||||
|
manager->modes[0].width = 1024;
|
||||||
|
manager->modes[0].height = 768;
|
||||||
|
manager->modes[0].refresh_rate = 60.0;
|
||||||
|
|
||||||
|
manager->crtcs = g_new0 (MetaCRTC, 1);
|
||||||
|
manager->n_crtcs = 1;
|
||||||
|
|
||||||
|
manager->crtcs[0].crtc_id = 1;
|
||||||
|
manager->crtcs[0].rect.x = 0;
|
||||||
|
manager->crtcs[0].rect.y = 0;
|
||||||
|
manager->crtcs[0].rect.width = manager->modes[0].width;
|
||||||
|
manager->crtcs[0].rect.height = manager->modes[0].height;
|
||||||
|
manager->crtcs[0].current_mode = &manager->modes[0];
|
||||||
|
manager->crtcs[0].transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||||
|
manager->crtcs[0].all_transforms = ALL_WL_TRANSFORMS;
|
||||||
|
manager->crtcs[0].is_dirty = FALSE;
|
||||||
|
manager->crtcs[0].logical_monitor = NULL;
|
||||||
|
|
||||||
|
manager->outputs = g_new0 (MetaOutput, 1);
|
||||||
|
manager->n_outputs = 1;
|
||||||
|
|
||||||
|
manager->outputs[0].crtc = &manager->crtcs[0];
|
||||||
|
manager->outputs[0].output_id = 1;
|
||||||
|
manager->outputs[0].name = g_strdup ("LVDS");
|
||||||
|
manager->outputs[0].vendor = g_strdup ("MetaProducts Inc.");
|
||||||
|
manager->outputs[0].product = g_strdup ("unknown");
|
||||||
|
manager->outputs[0].serial = g_strdup ("0xC0FFEE");
|
||||||
|
manager->outputs[0].width_mm = 222;
|
||||||
|
manager->outputs[0].height_mm = 125;
|
||||||
|
manager->outputs[0].subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
|
||||||
|
manager->outputs[0].preferred_mode = &manager->modes[0];
|
||||||
|
manager->outputs[0].n_modes = 1;
|
||||||
|
manager->outputs[0].modes = g_new0 (MetaMonitorMode *, 1);
|
||||||
|
manager->outputs[0].modes[0] = &manager->modes[0];
|
||||||
|
manager->outputs[0].n_possible_crtcs = 1;
|
||||||
|
manager->outputs[0].possible_crtcs = g_new0 (MetaCRTC *, 1);
|
||||||
|
manager->outputs[0].possible_crtcs[0] = &manager->crtcs[0];
|
||||||
|
manager->outputs[0].n_possible_clones = 0;
|
||||||
|
manager->outputs[0].possible_clones = g_new0 (MetaOutput *, 0);
|
||||||
|
manager->outputs[0].backlight = -1;
|
||||||
|
manager->outputs[0].backlight_min = 0;
|
||||||
|
manager->outputs[0].backlight_max = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
apply_config_dummy (MetaMonitorManager *manager,
|
||||||
|
MetaCRTCInfo **crtcs,
|
||||||
|
unsigned int n_crtcs,
|
||||||
|
MetaOutputInfo **outputs,
|
||||||
|
unsigned int n_outputs)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
int screen_width = 0, screen_height = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < n_crtcs; i++)
|
||||||
|
{
|
||||||
|
MetaCRTCInfo *crtc_info = crtcs[i];
|
||||||
|
MetaCRTC *crtc = crtc_info->crtc;
|
||||||
|
crtc->is_dirty = TRUE;
|
||||||
|
|
||||||
|
if (crtc_info->mode == NULL)
|
||||||
|
{
|
||||||
|
crtc->rect.x = 0;
|
||||||
|
crtc->rect.y = 0;
|
||||||
|
crtc->rect.width = 0;
|
||||||
|
crtc->rect.height = 0;
|
||||||
|
crtc->current_mode = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MetaMonitorMode *mode;
|
||||||
|
MetaOutput *output;
|
||||||
|
int i, n_outputs;
|
||||||
|
int width, height;
|
||||||
|
|
||||||
|
mode = crtc_info->mode;
|
||||||
|
|
||||||
|
if (meta_monitor_transform_is_rotated (crtc_info->transform))
|
||||||
|
{
|
||||||
|
width = mode->height;
|
||||||
|
height = mode->width;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
width = mode->width;
|
||||||
|
height = mode->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
crtc->rect.x = crtc_info->x;
|
||||||
|
crtc->rect.y = crtc_info->y;
|
||||||
|
crtc->rect.width = width;
|
||||||
|
crtc->rect.height = height;
|
||||||
|
crtc->current_mode = mode;
|
||||||
|
crtc->transform = crtc_info->transform;
|
||||||
|
|
||||||
|
screen_width = MAX (screen_width, crtc_info->x + width);
|
||||||
|
screen_height = MAX (screen_height, crtc_info->y + height);
|
||||||
|
|
||||||
|
n_outputs = crtc_info->outputs->len;
|
||||||
|
for (i = 0; i < n_outputs; i++)
|
||||||
|
{
|
||||||
|
output = ((MetaOutput**)crtc_info->outputs->pdata)[i];
|
||||||
|
|
||||||
|
output->is_dirty = TRUE;
|
||||||
|
output->crtc = crtc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < n_outputs; i++)
|
||||||
|
{
|
||||||
|
MetaOutputInfo *output_info = outputs[i];
|
||||||
|
MetaOutput *output = output_info->output;
|
||||||
|
|
||||||
|
output->is_primary = output_info->is_primary;
|
||||||
|
output->is_presentation = output_info->is_presentation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable CRTCs not mentioned in the list */
|
||||||
|
for (i = 0; i < manager->n_crtcs; i++)
|
||||||
|
{
|
||||||
|
MetaCRTC *crtc = &manager->crtcs[i];
|
||||||
|
|
||||||
|
crtc->logical_monitor = NULL;
|
||||||
|
|
||||||
|
if (crtc->is_dirty)
|
||||||
|
{
|
||||||
|
crtc->is_dirty = FALSE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
crtc->rect.x = 0;
|
||||||
|
crtc->rect.y = 0;
|
||||||
|
crtc->rect.width = 0;
|
||||||
|
crtc->rect.height = 0;
|
||||||
|
crtc->current_mode = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable outputs not mentioned in the list */
|
||||||
|
for (i = 0; i < manager->n_outputs; i++)
|
||||||
|
{
|
||||||
|
MetaOutput *output = &manager->outputs[i];
|
||||||
|
|
||||||
|
if (output->is_dirty)
|
||||||
|
{
|
||||||
|
output->is_dirty = FALSE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
output->crtc = NULL;
|
||||||
|
output->is_primary = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
manager->screen_width = screen_width;
|
||||||
|
manager->screen_height = screen_height;
|
||||||
|
|
||||||
|
meta_monitor_manager_rebuild_derived (manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GBytes *
|
||||||
|
read_edid_dummy (MetaMonitorManager *manager,
|
||||||
|
MetaOutput *output)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
get_edid_file_dummy (MetaMonitorManager *manager,
|
||||||
|
MetaOutput *output)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_monitor_manager_init (MetaMonitorManager *manager)
|
meta_monitor_manager_init (MetaMonitorManager *manager)
|
||||||
{
|
{
|
||||||
@@ -183,7 +368,7 @@ get_default_backend (void)
|
|||||||
* we're a nested configuration, so return the dummy
|
* we're a nested configuration, so return the dummy
|
||||||
* monitor setup. */
|
* monitor setup. */
|
||||||
if (meta_is_wayland_compositor ())
|
if (meta_is_wayland_compositor ())
|
||||||
return META_TYPE_MONITOR_MANAGER_DUMMY;
|
return META_TYPE_MONITOR_MANAGER;
|
||||||
else
|
else
|
||||||
return META_TYPE_MONITOR_MANAGER_XRANDR;
|
return META_TYPE_MONITOR_MANAGER_XRANDR;
|
||||||
}
|
}
|
||||||
@@ -195,7 +380,7 @@ get_default_backend (void)
|
|||||||
/* Use the dummy implementation on Wayland for now.
|
/* Use the dummy implementation on Wayland for now.
|
||||||
* In the future, we should support wl_fullscreen_output
|
* In the future, we should support wl_fullscreen_output
|
||||||
* which will have CRTC management in the protocol. */
|
* which will have CRTC management in the protocol. */
|
||||||
return META_TYPE_MONITOR_MANAGER_DUMMY;
|
return META_TYPE_MONITOR_MANAGER;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -389,20 +574,6 @@ meta_monitor_manager_get_property (GObject *object,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static GBytes *
|
|
||||||
meta_monitor_manager_real_read_edid (MetaMonitorManager *manager,
|
|
||||||
MetaOutput *output)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *
|
|
||||||
meta_monitor_manager_real_get_edid_file (MetaMonitorManager *manager,
|
|
||||||
MetaOutput *output)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_monitor_manager_class_init (MetaMonitorManagerClass *klass)
|
meta_monitor_manager_class_init (MetaMonitorManagerClass *klass)
|
||||||
{
|
{
|
||||||
@@ -414,8 +585,10 @@ meta_monitor_manager_class_init (MetaMonitorManagerClass *klass)
|
|||||||
object_class->dispose = meta_monitor_manager_dispose;
|
object_class->dispose = meta_monitor_manager_dispose;
|
||||||
object_class->finalize = meta_monitor_manager_finalize;
|
object_class->finalize = meta_monitor_manager_finalize;
|
||||||
|
|
||||||
klass->get_edid_file = meta_monitor_manager_real_get_edid_file;
|
klass->read_current = read_current_dummy;
|
||||||
klass->read_edid = meta_monitor_manager_real_read_edid;
|
klass->apply_configuration = apply_config_dummy;
|
||||||
|
klass->get_edid_file = get_edid_file_dummy;
|
||||||
|
klass->read_edid = read_edid_dummy;
|
||||||
|
|
||||||
signals[CONFIRM_DISPLAY_CHANGE] =
|
signals[CONFIRM_DISPLAY_CHANGE] =
|
||||||
g_signal_new ("confirm-display-change",
|
g_signal_new ("confirm-display-change",
|
||||||
@@ -344,7 +344,7 @@ avoid_being_obscured_as_second_modal_dialog (MetaWindow *window,
|
|||||||
/* denied_focus_and_not_transient is only set when focus_window != NULL */
|
/* denied_focus_and_not_transient is only set when focus_window != NULL */
|
||||||
|
|
||||||
if (window->denied_focus_and_not_transient &&
|
if (window->denied_focus_and_not_transient &&
|
||||||
window->type == META_WINDOW_MODAL_DIALOG &&
|
window->wm_state_modal && /* FIXME: Maybe do this for all transients? */
|
||||||
meta_window_same_application (window, focus_window) &&
|
meta_window_same_application (window, focus_window) &&
|
||||||
window_overlaps_focus_window (window))
|
window_overlaps_focus_window (window))
|
||||||
{
|
{
|
||||||
@@ -610,7 +610,7 @@ meta_window_place (MetaWindow *window,
|
|||||||
meta_topic (META_DEBUG_PLACEMENT, "Placing window %s\n", window->desc);
|
meta_topic (META_DEBUG_PLACEMENT, "Placing window %s\n", window->desc);
|
||||||
|
|
||||||
windows = NULL;
|
windows = NULL;
|
||||||
|
|
||||||
switch (window->type)
|
switch (window->type)
|
||||||
{
|
{
|
||||||
/* Run placement algorithm on these. */
|
/* Run placement algorithm on these. */
|
||||||
@@ -638,7 +638,7 @@ meta_window_place (MetaWindow *window,
|
|||||||
case META_WINDOW_OVERRIDE_OTHER:
|
case META_WINDOW_OVERRIDE_OTHER:
|
||||||
goto done_no_constraints;
|
goto done_no_constraints;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (meta_prefs_get_disable_workarounds ())
|
if (meta_prefs_get_disable_workarounds ())
|
||||||
{
|
{
|
||||||
switch (window->type)
|
switch (window->type)
|
||||||
@@ -699,11 +699,18 @@ meta_window_place (MetaWindow *window,
|
|||||||
goto done_no_constraints;
|
goto done_no_constraints;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window->type == META_WINDOW_DIALOG ||
|
if ((window->type == META_WINDOW_DIALOG ||
|
||||||
window->type == META_WINDOW_MODAL_DIALOG)
|
window->type == META_WINDOW_MODAL_DIALOG) &&
|
||||||
|
window->xtransient_for != None)
|
||||||
{
|
{
|
||||||
MetaWindow *parent = meta_window_get_transient_for (window);
|
/* Center horizontally, at top of parent vertically */
|
||||||
|
|
||||||
|
MetaWindow *parent;
|
||||||
|
|
||||||
|
parent =
|
||||||
|
meta_display_lookup_x_window (window->display,
|
||||||
|
window->xtransient_for);
|
||||||
|
|
||||||
if (parent)
|
if (parent)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -57,6 +57,7 @@
|
|||||||
|
|
||||||
#define KEY_OVERLAY_KEY "overlay-key"
|
#define KEY_OVERLAY_KEY "overlay-key"
|
||||||
#define KEY_WORKSPACES_ONLY_ON_PRIMARY "workspaces-only-on-primary"
|
#define KEY_WORKSPACES_ONLY_ON_PRIMARY "workspaces-only-on-primary"
|
||||||
|
#define KEY_NO_TAB_POPUP "no-tab-popup"
|
||||||
|
|
||||||
/* These are the different schemas we are keeping
|
/* These are the different schemas we are keeping
|
||||||
* a GSettings instance for */
|
* a GSettings instance for */
|
||||||
@@ -111,6 +112,8 @@ static char **workspace_names = NULL;
|
|||||||
|
|
||||||
static gboolean workspaces_only_on_primary = FALSE;
|
static gboolean workspaces_only_on_primary = FALSE;
|
||||||
|
|
||||||
|
static gboolean no_tab_popup = FALSE;
|
||||||
|
|
||||||
static char *iso_next_group_option = NULL;
|
static char *iso_next_group_option = NULL;
|
||||||
|
|
||||||
static void handle_preference_update_enum (GSettings *settings,
|
static void handle_preference_update_enum (GSettings *settings,
|
||||||
@@ -362,6 +365,13 @@ static MetaBoolPreference preferences_bool[] =
|
|||||||
},
|
},
|
||||||
&workspaces_only_on_primary,
|
&workspaces_only_on_primary,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
{ KEY_NO_TAB_POPUP,
|
||||||
|
SCHEMA_MUTTER,
|
||||||
|
META_PREF_NO_TAB_POPUP,
|
||||||
|
},
|
||||||
|
&no_tab_popup,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
{ "auto-maximize",
|
{ "auto-maximize",
|
||||||
SCHEMA_MUTTER,
|
SCHEMA_MUTTER,
|
||||||
@@ -1803,6 +1813,9 @@ meta_preference_to_string (MetaPreference pref)
|
|||||||
case META_PREF_WORKSPACES_ONLY_ON_PRIMARY:
|
case META_PREF_WORKSPACES_ONLY_ON_PRIMARY:
|
||||||
return "WORKSPACES_ONLY_ON_PRIMARY";
|
return "WORKSPACES_ONLY_ON_PRIMARY";
|
||||||
|
|
||||||
|
case META_PREF_NO_TAB_POPUP:
|
||||||
|
return "NO_TAB_POPUP";
|
||||||
|
|
||||||
case META_PREF_DRAGGABLE_BORDER_WIDTH:
|
case META_PREF_DRAGGABLE_BORDER_WIDTH:
|
||||||
return "DRAGGABLE_BORDER_WIDTH";
|
return "DRAGGABLE_BORDER_WIDTH";
|
||||||
|
|
||||||
@@ -1856,7 +1869,7 @@ init_bindings (void)
|
|||||||
pref = g_new0 (MetaKeyPref, 1);
|
pref = g_new0 (MetaKeyPref, 1);
|
||||||
pref->name = g_strdup ("overlay-key");
|
pref->name = g_strdup ("overlay-key");
|
||||||
pref->action = META_KEYBINDING_ACTION_OVERLAY_KEY;
|
pref->action = META_KEYBINDING_ACTION_OVERLAY_KEY;
|
||||||
pref->combos = g_slist_prepend (pref->combos, &overlay_key_combo);
|
pref->bindings = g_slist_prepend (pref->bindings, &overlay_key_combo);
|
||||||
pref->builtin = 1;
|
pref->builtin = 1;
|
||||||
|
|
||||||
g_hash_table_insert (key_bindings, g_strdup ("overlay-key"), pref);
|
g_hash_table_insert (key_bindings, g_strdup ("overlay-key"), pref);
|
||||||
@@ -1866,7 +1879,7 @@ static gboolean
|
|||||||
update_binding (MetaKeyPref *binding,
|
update_binding (MetaKeyPref *binding,
|
||||||
gchar **strokes)
|
gchar **strokes)
|
||||||
{
|
{
|
||||||
GSList *old_combos, *a, *b;
|
GSList *old_bindings, *a, *b;
|
||||||
gboolean changed;
|
gboolean changed;
|
||||||
unsigned int keysym;
|
unsigned int keysym;
|
||||||
unsigned int keycode;
|
unsigned int keycode;
|
||||||
@@ -1878,8 +1891,8 @@ update_binding (MetaKeyPref *binding,
|
|||||||
"Binding \"%s\" has new GSettings value\n",
|
"Binding \"%s\" has new GSettings value\n",
|
||||||
binding->name);
|
binding->name);
|
||||||
|
|
||||||
old_combos = binding->combos;
|
old_bindings = binding->bindings;
|
||||||
binding->combos = NULL;
|
binding->bindings = NULL;
|
||||||
|
|
||||||
for (i = 0; strokes && strokes[i]; i++)
|
for (i = 0; strokes && strokes[i]; i++)
|
||||||
{
|
{
|
||||||
@@ -1920,17 +1933,17 @@ update_binding (MetaKeyPref *binding,
|
|||||||
combo->keysym = keysym;
|
combo->keysym = keysym;
|
||||||
combo->keycode = keycode;
|
combo->keycode = keycode;
|
||||||
combo->modifiers = mods;
|
combo->modifiers = mods;
|
||||||
binding->combos = g_slist_prepend (binding->combos, combo);
|
binding->bindings = g_slist_prepend (binding->bindings, combo);
|
||||||
|
|
||||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||||
"New keybinding for \"%s\" is keysym = 0x%x keycode = 0x%x mods = 0x%x\n",
|
"New keybinding for \"%s\" is keysym = 0x%x keycode = 0x%x mods = 0x%x\n",
|
||||||
binding->name, keysym, keycode, mods);
|
binding->name, keysym, keycode, mods);
|
||||||
}
|
}
|
||||||
|
|
||||||
binding->combos = g_slist_reverse (binding->combos);
|
binding->bindings = g_slist_reverse (binding->bindings);
|
||||||
|
|
||||||
a = old_combos;
|
a = old_bindings;
|
||||||
b = binding->combos;
|
b = binding->bindings;
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
if ((!a && b) || (a && !b))
|
if ((!a && b) || (a && !b))
|
||||||
@@ -1955,7 +1968,7 @@ update_binding (MetaKeyPref *binding,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_slist_free_full (old_combos, g_free);
|
g_slist_free_full (old_bindings, g_free);
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
@@ -2090,7 +2103,7 @@ meta_prefs_add_keybinding (const char *name,
|
|||||||
pref->name = g_strdup (name);
|
pref->name = g_strdup (name);
|
||||||
pref->settings = g_object_ref (settings);
|
pref->settings = g_object_ref (settings);
|
||||||
pref->action = action;
|
pref->action = action;
|
||||||
pref->combos = NULL;
|
pref->bindings = NULL;
|
||||||
pref->add_shift = (flags & META_KEY_BINDING_REVERSES) != 0;
|
pref->add_shift = (flags & META_KEY_BINDING_REVERSES) != 0;
|
||||||
pref->per_window = (flags & META_KEY_BINDING_PER_WINDOW) != 0;
|
pref->per_window = (flags & META_KEY_BINDING_PER_WINDOW) != 0;
|
||||||
pref->builtin = (flags & META_KEY_BINDING_BUILTIN) != 0;
|
pref->builtin = (flags & META_KEY_BINDING_BUILTIN) != 0;
|
||||||
@@ -2154,6 +2167,11 @@ meta_prefs_remove_keybinding (const char *name)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* meta_prefs_get_keybindings:
|
||||||
|
*
|
||||||
|
* Returns: (element-type MetaKeyPref) (transfer container):
|
||||||
|
*/
|
||||||
GList *
|
GList *
|
||||||
meta_prefs_get_keybindings ()
|
meta_prefs_get_keybindings ()
|
||||||
{
|
{
|
||||||
@@ -2254,7 +2272,7 @@ meta_prefs_get_window_binding (const char *name,
|
|||||||
|
|
||||||
if (pref->per_window)
|
if (pref->per_window)
|
||||||
{
|
{
|
||||||
GSList *s = pref->combos;
|
GSList *s = pref->bindings;
|
||||||
|
|
||||||
while (s)
|
while (s)
|
||||||
{
|
{
|
||||||
@@ -2302,6 +2320,25 @@ meta_prefs_get_workspaces_only_on_primary (void)
|
|||||||
return workspaces_only_on_primary;
|
return workspaces_only_on_primary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
meta_prefs_get_no_tab_popup (void)
|
||||||
|
{
|
||||||
|
return no_tab_popup;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_prefs_set_no_tab_popup (gboolean whether)
|
||||||
|
{
|
||||||
|
MetaBasePreference *pref;
|
||||||
|
|
||||||
|
if (find_pref (preferences_bool, sizeof(MetaBoolPreference),
|
||||||
|
KEY_NO_TAB_POPUP, &pref))
|
||||||
|
{
|
||||||
|
g_settings_set_boolean (SETTINGS (pref->schema), KEY_NO_TAB_POPUP, whether);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
meta_prefs_get_draggable_border_width (void)
|
meta_prefs_get_draggable_border_width (void)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
#include "stack-tracker.h"
|
#include "stack-tracker.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "meta-monitor-manager.h"
|
#include "monitor-private.h"
|
||||||
|
|
||||||
typedef void (* MetaScreenWindowFunc) (MetaScreen *screen, MetaWindow *window,
|
typedef void (* MetaScreenWindowFunc) (MetaScreen *screen, MetaWindow *window,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
@@ -64,6 +64,7 @@ struct _MetaScreen
|
|||||||
Visual *default_xvisual;
|
Visual *default_xvisual;
|
||||||
MetaRectangle rect; /* Size of screen; rect.x & rect.y are always 0 */
|
MetaRectangle rect; /* Size of screen; rect.x & rect.y are always 0 */
|
||||||
MetaUI *ui;
|
MetaUI *ui;
|
||||||
|
MetaTabPopup *tab_popup, *ws_popup;
|
||||||
|
|
||||||
guint tile_preview_timeout_id;
|
guint tile_preview_timeout_id;
|
||||||
|
|
||||||
@@ -82,6 +83,8 @@ struct _MetaScreen
|
|||||||
MetaCursorTracker *cursor_tracker;
|
MetaCursorTracker *cursor_tracker;
|
||||||
MetaCursor current_cursor;
|
MetaCursor current_cursor;
|
||||||
|
|
||||||
|
Window flash_window;
|
||||||
|
|
||||||
Window wm_sn_selection_window;
|
Window wm_sn_selection_window;
|
||||||
Atom wm_sn_atom;
|
Atom wm_sn_atom;
|
||||||
guint32 wm_sn_timestamp;
|
guint32 wm_sn_timestamp;
|
||||||
@@ -116,6 +119,9 @@ struct _MetaScreen
|
|||||||
guint all_keys_grabbed : 1;
|
guint all_keys_grabbed : 1;
|
||||||
|
|
||||||
int closing;
|
int closing;
|
||||||
|
|
||||||
|
/* Managed by compositor.c */
|
||||||
|
gpointer compositor_data;
|
||||||
|
|
||||||
/* Instead of unmapping withdrawn windows we can leave them mapped
|
/* Instead of unmapping withdrawn windows we can leave them mapped
|
||||||
* and restack them below a guard window. When using a compositor
|
* and restack them below a guard window. When using a compositor
|
||||||
@@ -144,6 +150,22 @@ void meta_screen_foreach_window (MetaScreen *scree
|
|||||||
|
|
||||||
void meta_screen_update_cursor (MetaScreen *screen);
|
void meta_screen_update_cursor (MetaScreen *screen);
|
||||||
|
|
||||||
|
void meta_screen_tab_popup_create (MetaScreen *screen,
|
||||||
|
MetaTabList list_type,
|
||||||
|
MetaTabShowType show_type,
|
||||||
|
MetaWindow *initial_window);
|
||||||
|
void meta_screen_tab_popup_forward (MetaScreen *screen);
|
||||||
|
void meta_screen_tab_popup_backward (MetaScreen *screen);
|
||||||
|
MetaWindow* meta_screen_tab_popup_get_selected (MetaScreen *screen);
|
||||||
|
void meta_screen_tab_popup_destroy (MetaScreen *screen);
|
||||||
|
|
||||||
|
void meta_screen_workspace_popup_create (MetaScreen *screen,
|
||||||
|
MetaWorkspace *initial_selection);
|
||||||
|
void meta_screen_workspace_popup_select (MetaScreen *screen,
|
||||||
|
MetaWorkspace *workspace);
|
||||||
|
MetaWorkspace*meta_screen_workspace_popup_get_selected (MetaScreen *screen);
|
||||||
|
void meta_screen_workspace_popup_destroy (MetaScreen *screen);
|
||||||
|
|
||||||
void meta_screen_update_tile_preview (MetaScreen *screen,
|
void meta_screen_update_tile_preview (MetaScreen *screen,
|
||||||
gboolean delay);
|
gboolean delay);
|
||||||
void meta_screen_hide_tile_preview (MetaScreen *screen);
|
void meta_screen_hide_tile_preview (MetaScreen *screen);
|
||||||
|
|||||||
@@ -39,9 +39,11 @@
|
|||||||
#include "workspace-private.h"
|
#include "workspace-private.h"
|
||||||
#include "keybindings-private.h"
|
#include "keybindings-private.h"
|
||||||
#include "stack.h"
|
#include "stack.h"
|
||||||
|
#include "xprops.h"
|
||||||
#include <meta/compositor.h>
|
#include <meta/compositor.h>
|
||||||
#include "mutter-enum-types.h"
|
#include "mutter-enum-types.h"
|
||||||
#include "core.h"
|
#include "core.h"
|
||||||
|
#include "meta-wayland-private.h"
|
||||||
#include "meta-cursor-tracker-private.h"
|
#include "meta-cursor-tracker-private.h"
|
||||||
|
|
||||||
#include <X11/extensions/Xinerama.h>
|
#include <X11/extensions/Xinerama.h>
|
||||||
@@ -52,8 +54,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "x11/xprops.h"
|
|
||||||
|
|
||||||
static char* get_screen_name (MetaDisplay *display,
|
static char* get_screen_name (MetaDisplay *display,
|
||||||
int number);
|
int number);
|
||||||
|
|
||||||
@@ -308,8 +308,6 @@ set_supported_hint (MetaScreen *screen)
|
|||||||
#include <meta/atomnames.h>
|
#include <meta/atomnames.h>
|
||||||
#undef item
|
#undef item
|
||||||
#undef EWMH_ATOMS_ONLY
|
#undef EWMH_ATOMS_ONLY
|
||||||
|
|
||||||
screen->display->atom__GTK_FRAME_EXTENTS,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
XChangeProperty (screen->display->xdisplay, screen->xroot,
|
XChangeProperty (screen->display->xdisplay, screen->xroot,
|
||||||
@@ -560,7 +558,7 @@ meta_screen_new (MetaDisplay *display,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* We want to find out when the current selection owner dies */
|
/* We want to find out when the current selection owner dies */
|
||||||
meta_error_trap_push (display);
|
meta_error_trap_push_with_return (display);
|
||||||
attrs.event_mask = StructureNotifyMask;
|
attrs.event_mask = StructureNotifyMask;
|
||||||
XChangeWindowAttributes (xdisplay,
|
XChangeWindowAttributes (xdisplay,
|
||||||
current_wm_sn_owner, CWEventMask, &attrs);
|
current_wm_sn_owner, CWEventMask, &attrs);
|
||||||
@@ -619,7 +617,7 @@ meta_screen_new (MetaDisplay *display,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* select our root window events */
|
/* select our root window events */
|
||||||
meta_error_trap_push (display);
|
meta_error_trap_push_with_return (display);
|
||||||
|
|
||||||
/* We need to or with the existing event mask since
|
/* We need to or with the existing event mask since
|
||||||
* gtk+ may be interested in other events.
|
* gtk+ may be interested in other events.
|
||||||
@@ -690,6 +688,7 @@ meta_screen_new (MetaDisplay *display,
|
|||||||
screen->current_cursor = -1; /* invalid/unset */
|
screen->current_cursor = -1; /* invalid/unset */
|
||||||
screen->default_xvisual = DefaultVisualOfScreen (screen->xscreen);
|
screen->default_xvisual = DefaultVisualOfScreen (screen->xscreen);
|
||||||
screen->default_depth = DefaultDepthOfScreen (screen->xscreen);
|
screen->default_depth = DefaultDepthOfScreen (screen->xscreen);
|
||||||
|
screen->flash_window = None;
|
||||||
|
|
||||||
screen->wm_sn_selection_window = new_wm_sn_owner;
|
screen->wm_sn_selection_window = new_wm_sn_owner;
|
||||||
screen->wm_sn_atom = wm_sn_atom;
|
screen->wm_sn_atom = wm_sn_atom;
|
||||||
@@ -707,6 +706,7 @@ meta_screen_new (MetaDisplay *display,
|
|||||||
screen->columns_of_workspaces = -1;
|
screen->columns_of_workspaces = -1;
|
||||||
screen->vertical_workspaces = FALSE;
|
screen->vertical_workspaces = FALSE;
|
||||||
screen->starting_corner = META_SCREEN_TOPLEFT;
|
screen->starting_corner = META_SCREEN_TOPLEFT;
|
||||||
|
screen->compositor_data = NULL;
|
||||||
screen->guard_window = None;
|
screen->guard_window = None;
|
||||||
|
|
||||||
reload_monitor_infos (screen);
|
reload_monitor_infos (screen);
|
||||||
@@ -757,7 +757,11 @@ meta_screen_new (MetaDisplay *display,
|
|||||||
screen->keys_grabbed = FALSE;
|
screen->keys_grabbed = FALSE;
|
||||||
meta_screen_grab_keys (screen);
|
meta_screen_grab_keys (screen);
|
||||||
|
|
||||||
screen->ui = meta_ui_new ();
|
screen->ui = meta_ui_new (screen->display->xdisplay,
|
||||||
|
screen->xscreen);
|
||||||
|
|
||||||
|
screen->tab_popup = NULL;
|
||||||
|
screen->ws_popup = NULL;
|
||||||
|
|
||||||
screen->tile_preview_timeout_id = 0;
|
screen->tile_preview_timeout_id = 0;
|
||||||
|
|
||||||
@@ -806,7 +810,11 @@ meta_screen_free (MetaScreen *screen,
|
|||||||
|
|
||||||
meta_display_grab (display);
|
meta_display_grab (display);
|
||||||
|
|
||||||
meta_compositor_unmanage (screen->display->compositor);
|
if (screen->display->compositor)
|
||||||
|
{
|
||||||
|
meta_compositor_unmanage_screen (screen->display->compositor,
|
||||||
|
screen);
|
||||||
|
}
|
||||||
|
|
||||||
meta_display_unmanage_windows_for_screen (display, screen, timestamp);
|
meta_display_unmanage_windows_for_screen (display, screen, timestamp);
|
||||||
|
|
||||||
@@ -837,7 +845,7 @@ meta_screen_free (MetaScreen *screen,
|
|||||||
meta_stack_free (screen->stack);
|
meta_stack_free (screen->stack);
|
||||||
meta_stack_tracker_free (screen->stack_tracker);
|
meta_stack_tracker_free (screen->stack_tracker);
|
||||||
|
|
||||||
meta_error_trap_push (screen->display);
|
meta_error_trap_push_with_return (screen->display);
|
||||||
XSelectInput (screen->display->xdisplay, screen->xroot, 0);
|
XSelectInput (screen->display->xdisplay, screen->xroot, 0);
|
||||||
if (meta_error_trap_pop_with_return (screen->display) != Success)
|
if (meta_error_trap_pop_with_return (screen->display) != Success)
|
||||||
meta_warning ("Could not release screen %d on display \"%s\"\n",
|
meta_warning ("Could not release screen %d on display \"%s\"\n",
|
||||||
@@ -897,6 +905,28 @@ meta_screen_manage_all_windows (MetaScreen *screen)
|
|||||||
meta_stack_thaw (screen->stack);
|
meta_stack_thaw (screen->stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* meta_screen_for_x_screen:
|
||||||
|
* @xscreen: an X screen structure.
|
||||||
|
*
|
||||||
|
* Gets the #MetaScreen corresponding to an X screen structure.
|
||||||
|
*
|
||||||
|
* Return value: (transfer none): the #MetaScreen for the X screen
|
||||||
|
* %NULL if Metacity is not managing the screen.
|
||||||
|
*/
|
||||||
|
MetaScreen*
|
||||||
|
meta_screen_for_x_screen (Screen *xscreen)
|
||||||
|
{
|
||||||
|
MetaDisplay *display;
|
||||||
|
|
||||||
|
display = meta_display_for_x_display (DisplayOfScreen (xscreen));
|
||||||
|
|
||||||
|
if (display == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return meta_display_screen_for_x_screen (display, xscreen);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
prefs_changed_callback (MetaPreference pref,
|
prefs_changed_callback (MetaPreference pref,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
@@ -1380,26 +1410,6 @@ update_focus_mode (MetaScreen *screen)
|
|||||||
/* nothing to do anymore */ ;
|
/* nothing to do anymore */ ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
meta_screen_update_cursor (MetaScreen *screen)
|
|
||||||
{
|
|
||||||
MetaDisplay *display = screen->display;
|
|
||||||
MetaCursor cursor = screen->current_cursor;
|
|
||||||
Cursor xcursor;
|
|
||||||
MetaCursorReference *cursor_ref;
|
|
||||||
|
|
||||||
cursor_ref = meta_cursor_reference_from_theme (screen->cursor_tracker, cursor);
|
|
||||||
meta_cursor_tracker_set_root_cursor (screen->cursor_tracker, cursor_ref);
|
|
||||||
meta_cursor_reference_unref (cursor_ref);
|
|
||||||
|
|
||||||
/* Set a cursor for X11 applications that don't specify their own */
|
|
||||||
xcursor = meta_display_create_x_cursor (display, cursor);
|
|
||||||
|
|
||||||
XDefineCursor (display->xdisplay, screen->xroot, xcursor);
|
|
||||||
XFlush (display->xdisplay);
|
|
||||||
XFreeCursor (display->xdisplay, xcursor);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_screen_set_cursor (MetaScreen *screen,
|
meta_screen_set_cursor (MetaScreen *screen,
|
||||||
MetaCursor cursor)
|
MetaCursor cursor)
|
||||||
@@ -1408,7 +1418,261 @@ meta_screen_set_cursor (MetaScreen *screen,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
screen->current_cursor = cursor;
|
screen->current_cursor = cursor;
|
||||||
meta_screen_update_cursor (screen);
|
meta_cursor_tracker_set_root_cursor (screen->cursor_tracker, cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_screen_update_cursor (MetaScreen *screen)
|
||||||
|
{
|
||||||
|
meta_cursor_tracker_set_root_cursor (screen->cursor_tracker,
|
||||||
|
screen->current_cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_screen_tab_popup_create (MetaScreen *screen,
|
||||||
|
MetaTabList list_type,
|
||||||
|
MetaTabShowType show_type,
|
||||||
|
MetaWindow *initial_selection)
|
||||||
|
{
|
||||||
|
MetaTabEntry *entries;
|
||||||
|
GList *tab_list;
|
||||||
|
GList *tmp;
|
||||||
|
int len;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (screen->tab_popup)
|
||||||
|
return;
|
||||||
|
|
||||||
|
tab_list = meta_display_get_tab_list (screen->display,
|
||||||
|
list_type,
|
||||||
|
screen,
|
||||||
|
screen->active_workspace);
|
||||||
|
|
||||||
|
len = g_list_length (tab_list);
|
||||||
|
|
||||||
|
entries = g_new (MetaTabEntry, len + 1);
|
||||||
|
entries[len].key = NULL;
|
||||||
|
entries[len].title = NULL;
|
||||||
|
entries[len].icon = NULL;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
tmp = tab_list;
|
||||||
|
while (i < len)
|
||||||
|
{
|
||||||
|
MetaWindow *window;
|
||||||
|
MetaRectangle r;
|
||||||
|
|
||||||
|
window = tmp->data;
|
||||||
|
|
||||||
|
entries[i].key = (MetaTabEntryKey) window;
|
||||||
|
entries[i].title = window->title;
|
||||||
|
entries[i].icon = g_object_ref (window->icon);
|
||||||
|
entries[i].blank = FALSE;
|
||||||
|
entries[i].hidden = !meta_window_showing_on_its_workspace (window);
|
||||||
|
entries[i].demands_attention = window->wm_state_demands_attention;
|
||||||
|
|
||||||
|
if (show_type == META_TAB_SHOW_INSTANTLY ||
|
||||||
|
!entries[i].hidden ||
|
||||||
|
!meta_window_get_icon_geometry (window, &r))
|
||||||
|
meta_window_get_frame_rect (window, &r);
|
||||||
|
|
||||||
|
entries[i].rect = r;
|
||||||
|
|
||||||
|
/* Find inside of highlight rectangle to be used when window is
|
||||||
|
* outlined for tabbing. This should be the size of the
|
||||||
|
* east/west frame, and the size of the south frame, on those
|
||||||
|
* sides. On the top it should be the size of the south frame
|
||||||
|
* edge.
|
||||||
|
*/
|
||||||
|
#define OUTLINE_WIDTH 5
|
||||||
|
/* Top side */
|
||||||
|
if (!entries[i].hidden &&
|
||||||
|
window->frame && window->frame->bottom_height > 0 &&
|
||||||
|
window->frame->child_y >= window->frame->bottom_height)
|
||||||
|
entries[i].inner_rect.y = window->frame->bottom_height;
|
||||||
|
else
|
||||||
|
entries[i].inner_rect.y = OUTLINE_WIDTH;
|
||||||
|
|
||||||
|
/* Bottom side */
|
||||||
|
if (!entries[i].hidden &&
|
||||||
|
window->frame && window->frame->bottom_height != 0)
|
||||||
|
entries[i].inner_rect.height = r.height
|
||||||
|
- entries[i].inner_rect.y - window->frame->bottom_height;
|
||||||
|
else
|
||||||
|
entries[i].inner_rect.height = r.height
|
||||||
|
- entries[i].inner_rect.y - OUTLINE_WIDTH;
|
||||||
|
|
||||||
|
/* Left side */
|
||||||
|
if (!entries[i].hidden && window->frame && window->frame->child_x != 0)
|
||||||
|
entries[i].inner_rect.x = window->frame->child_x;
|
||||||
|
else
|
||||||
|
entries[i].inner_rect.x = OUTLINE_WIDTH;
|
||||||
|
|
||||||
|
/* Right side */
|
||||||
|
if (!entries[i].hidden &&
|
||||||
|
window->frame && window->frame->right_width != 0)
|
||||||
|
entries[i].inner_rect.width = r.width
|
||||||
|
- entries[i].inner_rect.x - window->frame->right_width;
|
||||||
|
else
|
||||||
|
entries[i].inner_rect.width = r.width
|
||||||
|
- entries[i].inner_rect.x - OUTLINE_WIDTH;
|
||||||
|
|
||||||
|
++i;
|
||||||
|
tmp = tmp->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!meta_prefs_get_no_tab_popup ())
|
||||||
|
screen->tab_popup = meta_ui_tab_popup_new (entries,
|
||||||
|
screen->number,
|
||||||
|
len,
|
||||||
|
5, /* FIXME */
|
||||||
|
TRUE);
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
g_object_unref (entries[i].icon);
|
||||||
|
|
||||||
|
g_free (entries);
|
||||||
|
|
||||||
|
g_list_free (tab_list);
|
||||||
|
|
||||||
|
meta_ui_tab_popup_select (screen->tab_popup,
|
||||||
|
(MetaTabEntryKey) initial_selection);
|
||||||
|
|
||||||
|
if (show_type != META_TAB_SHOW_INSTANTLY)
|
||||||
|
meta_ui_tab_popup_set_showing (screen->tab_popup, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_screen_tab_popup_forward (MetaScreen *screen)
|
||||||
|
{
|
||||||
|
g_return_if_fail (screen->tab_popup != NULL);
|
||||||
|
|
||||||
|
meta_ui_tab_popup_forward (screen->tab_popup);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_screen_tab_popup_backward (MetaScreen *screen)
|
||||||
|
{
|
||||||
|
g_return_if_fail (screen->tab_popup != NULL);
|
||||||
|
|
||||||
|
meta_ui_tab_popup_backward (screen->tab_popup);
|
||||||
|
}
|
||||||
|
|
||||||
|
MetaWindow *
|
||||||
|
meta_screen_tab_popup_get_selected (MetaScreen *screen)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (screen->tab_popup != NULL, NULL);
|
||||||
|
|
||||||
|
return (MetaWindow *) meta_ui_tab_popup_get_selected (screen->tab_popup);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_screen_tab_popup_destroy (MetaScreen *screen)
|
||||||
|
{
|
||||||
|
if (screen->tab_popup)
|
||||||
|
{
|
||||||
|
meta_ui_tab_popup_free (screen->tab_popup);
|
||||||
|
screen->tab_popup = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_screen_workspace_popup_create (MetaScreen *screen,
|
||||||
|
MetaWorkspace *initial_selection)
|
||||||
|
{
|
||||||
|
MetaTabEntry *entries;
|
||||||
|
int len;
|
||||||
|
int i;
|
||||||
|
MetaWorkspaceLayout layout;
|
||||||
|
int n_workspaces;
|
||||||
|
int current_workspace;
|
||||||
|
|
||||||
|
if (screen->ws_popup || meta_prefs_get_no_tab_popup ())
|
||||||
|
return;
|
||||||
|
|
||||||
|
current_workspace = meta_workspace_index (screen->active_workspace);
|
||||||
|
n_workspaces = meta_screen_get_n_workspaces (screen);
|
||||||
|
|
||||||
|
meta_screen_calc_workspace_layout (screen, n_workspaces,
|
||||||
|
current_workspace, &layout);
|
||||||
|
|
||||||
|
len = layout.grid_area;
|
||||||
|
|
||||||
|
entries = g_new (MetaTabEntry, len + 1);
|
||||||
|
entries[len].key = NULL;
|
||||||
|
entries[len].title = NULL;
|
||||||
|
entries[len].icon = NULL;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while (i < len)
|
||||||
|
{
|
||||||
|
if (layout.grid[i] >= 0)
|
||||||
|
{
|
||||||
|
MetaWorkspace *workspace;
|
||||||
|
|
||||||
|
workspace = meta_screen_get_workspace_by_index (screen,
|
||||||
|
layout.grid[i]);
|
||||||
|
|
||||||
|
entries[i].key = (MetaTabEntryKey) workspace;
|
||||||
|
entries[i].title = meta_workspace_get_name (workspace);
|
||||||
|
entries[i].icon = NULL;
|
||||||
|
entries[i].blank = FALSE;
|
||||||
|
|
||||||
|
g_assert (entries[i].title != NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
entries[i].key = NULL;
|
||||||
|
entries[i].title = NULL;
|
||||||
|
entries[i].icon = NULL;
|
||||||
|
entries[i].blank = TRUE;
|
||||||
|
}
|
||||||
|
entries[i].hidden = FALSE;
|
||||||
|
entries[i].demands_attention = FALSE;
|
||||||
|
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
screen->ws_popup = meta_ui_tab_popup_new (entries,
|
||||||
|
screen->number,
|
||||||
|
len,
|
||||||
|
layout.cols,
|
||||||
|
FALSE);
|
||||||
|
|
||||||
|
g_free (entries);
|
||||||
|
meta_screen_free_workspace_layout (&layout);
|
||||||
|
|
||||||
|
meta_ui_tab_popup_select (screen->ws_popup,
|
||||||
|
(MetaTabEntryKey) initial_selection);
|
||||||
|
meta_ui_tab_popup_set_showing (screen->ws_popup, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_screen_workspace_popup_select (MetaScreen *screen,
|
||||||
|
MetaWorkspace *workspace)
|
||||||
|
{
|
||||||
|
g_return_if_fail (screen->ws_popup != NULL);
|
||||||
|
|
||||||
|
meta_ui_tab_popup_select (screen->ws_popup,
|
||||||
|
(MetaTabEntryKey) workspace);
|
||||||
|
}
|
||||||
|
|
||||||
|
MetaWorkspace *
|
||||||
|
meta_screen_workspace_popup_get_selected (MetaScreen *screen)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (screen->ws_popup != NULL, NULL);
|
||||||
|
|
||||||
|
return (MetaWorkspace *) meta_ui_tab_popup_get_selected (screen->ws_popup);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_screen_workspace_popup_destroy (MetaScreen *screen)
|
||||||
|
{
|
||||||
|
if (screen->ws_popup)
|
||||||
|
{
|
||||||
|
meta_ui_tab_popup_free (screen->ws_popup);
|
||||||
|
screen->ws_popup = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@@ -1449,10 +1713,11 @@ meta_screen_update_tile_preview_timeout (gpointer data)
|
|||||||
monitor = meta_window_get_current_tile_monitor_number (window);
|
monitor = meta_window_get_current_tile_monitor_number (window);
|
||||||
meta_window_get_current_tile_area (window, &tile_rect);
|
meta_window_get_current_tile_area (window, &tile_rect);
|
||||||
meta_compositor_show_tile_preview (screen->display->compositor,
|
meta_compositor_show_tile_preview (screen->display->compositor,
|
||||||
window, &tile_rect, monitor);
|
screen, window, &tile_rect, monitor);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
meta_compositor_hide_tile_preview (screen->display->compositor);
|
meta_compositor_hide_tile_preview (screen->display->compositor,
|
||||||
|
screen);
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@@ -1488,7 +1753,8 @@ meta_screen_hide_tile_preview (MetaScreen *screen)
|
|||||||
if (screen->tile_preview_timeout_id > 0)
|
if (screen->tile_preview_timeout_id > 0)
|
||||||
g_source_remove (screen->tile_preview_timeout_id);
|
g_source_remove (screen->tile_preview_timeout_id);
|
||||||
|
|
||||||
meta_compositor_hide_tile_preview (screen->display->compositor);
|
meta_compositor_hide_tile_preview (screen->display->compositor,
|
||||||
|
screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
MetaWindow*
|
MetaWindow*
|
||||||
@@ -1496,19 +1762,38 @@ meta_screen_get_mouse_window (MetaScreen *screen,
|
|||||||
MetaWindow *not_this_one)
|
MetaWindow *not_this_one)
|
||||||
{
|
{
|
||||||
MetaWindow *window;
|
MetaWindow *window;
|
||||||
int x, y;
|
Window root_return, child_return;
|
||||||
|
double root_x_return, root_y_return;
|
||||||
|
double win_x_return, win_y_return;
|
||||||
|
XIButtonState buttons;
|
||||||
|
XIModifierState mods;
|
||||||
|
XIGroupState group;
|
||||||
|
|
||||||
if (not_this_one)
|
if (not_this_one)
|
||||||
meta_topic (META_DEBUG_FOCUS,
|
meta_topic (META_DEBUG_FOCUS,
|
||||||
"Focusing mouse window excluding %s\n", not_this_one->desc);
|
"Focusing mouse window excluding %s\n", not_this_one->desc);
|
||||||
|
|
||||||
meta_cursor_tracker_get_pointer (screen->cursor_tracker,
|
meta_error_trap_push (screen->display);
|
||||||
&x, &y, NULL);
|
XIQueryPointer (screen->display->xdisplay,
|
||||||
|
META_VIRTUAL_CORE_POINTER_ID,
|
||||||
|
screen->xroot,
|
||||||
|
&root_return,
|
||||||
|
&child_return,
|
||||||
|
&root_x_return,
|
||||||
|
&root_y_return,
|
||||||
|
&win_x_return,
|
||||||
|
&win_y_return,
|
||||||
|
&buttons,
|
||||||
|
&mods,
|
||||||
|
&group);
|
||||||
|
meta_error_trap_pop (screen->display);
|
||||||
|
free (buttons.mask);
|
||||||
|
|
||||||
window = meta_stack_get_default_focus_window_at_point (screen->stack,
|
window = meta_stack_get_default_focus_window_at_point (screen->stack,
|
||||||
screen->active_workspace,
|
screen->active_workspace,
|
||||||
not_this_one,
|
not_this_one,
|
||||||
x, y);
|
root_x_return,
|
||||||
|
root_y_return);
|
||||||
|
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
@@ -1790,11 +2075,28 @@ meta_screen_get_current_monitor (MetaScreen *screen)
|
|||||||
|
|
||||||
if (screen->display->monitor_cache_invalidated)
|
if (screen->display->monitor_cache_invalidated)
|
||||||
{
|
{
|
||||||
int x, y;
|
Window root_return, child_return;
|
||||||
|
double win_x_return, win_y_return;
|
||||||
|
double root_x_return, root_y_return;
|
||||||
|
XIButtonState buttons;
|
||||||
|
XIModifierState mods;
|
||||||
|
XIGroupState group;
|
||||||
|
|
||||||
meta_cursor_tracker_get_pointer (screen->cursor_tracker,
|
XIQueryPointer (screen->display->xdisplay,
|
||||||
&x, &y, NULL);
|
META_VIRTUAL_CORE_POINTER_ID,
|
||||||
meta_screen_get_current_monitor_for_pos (screen, x, y);
|
screen->xroot,
|
||||||
|
&root_return,
|
||||||
|
&child_return,
|
||||||
|
&root_x_return,
|
||||||
|
&root_y_return,
|
||||||
|
&win_x_return,
|
||||||
|
&win_y_return,
|
||||||
|
&buttons,
|
||||||
|
&mods,
|
||||||
|
&group);
|
||||||
|
free (buttons.mask);
|
||||||
|
|
||||||
|
meta_screen_get_current_monitor_for_pos (screen, root_x_return, root_y_return);
|
||||||
}
|
}
|
||||||
|
|
||||||
return screen->last_monitor_index;
|
return screen->last_monitor_index;
|
||||||
@@ -2505,8 +2807,10 @@ on_monitors_changed (MetaMonitorManager *manager,
|
|||||||
&changes);
|
&changes);
|
||||||
}
|
}
|
||||||
|
|
||||||
meta_compositor_sync_screen_size (screen->display->compositor,
|
if (screen->display->compositor)
|
||||||
screen->rect.width, screen->rect.height);
|
meta_compositor_sync_screen_size (screen->display->compositor,
|
||||||
|
screen,
|
||||||
|
screen->rect.width, screen->rect.height);
|
||||||
|
|
||||||
/* Queue a resize on all the windows */
|
/* Queue a resize on all the windows */
|
||||||
meta_screen_foreach_window (screen, meta_screen_resize_func, 0);
|
meta_screen_foreach_window (screen, meta_screen_resize_func, 0);
|
||||||
@@ -3046,6 +3350,24 @@ meta_screen_get_size (MetaScreen *screen,
|
|||||||
*height = screen->rect.height;
|
*height = screen->rect.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* meta_screen_get_compositor_data: (skip)
|
||||||
|
* @screen: A #MetaScreen
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
gpointer
|
||||||
|
meta_screen_get_compositor_data (MetaScreen *screen)
|
||||||
|
{
|
||||||
|
return screen->compositor_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_screen_set_compositor_data (MetaScreen *screen,
|
||||||
|
gpointer compositor)
|
||||||
|
{
|
||||||
|
screen->compositor_data = compositor;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_screen_set_cm_selection (MetaScreen *screen)
|
meta_screen_set_cm_selection (MetaScreen *screen)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1816,7 +1816,7 @@ warn_about_lame_clients_and_finish_interact (gboolean shutdown)
|
|||||||
"and will have to be restarted manually next time "
|
"and will have to be restarted manually next time "
|
||||||
"you log in."),
|
"you log in."),
|
||||||
"240",
|
"240",
|
||||||
meta_get_display()->screen->screen_name,
|
meta_get_display()->active_screen->screen_name,
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
None,
|
None,
|
||||||
columns,
|
columns,
|
||||||
@@ -1245,8 +1245,10 @@ meta_stack_tracker_sync_stack (MetaStackTracker *tracker)
|
|||||||
meta_windows = g_list_prepend (meta_windows, window->wayland.meta_window);
|
meta_windows = g_list_prepend (meta_windows, window->wayland.meta_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
meta_compositor_sync_stack (tracker->screen->display->compositor,
|
if (tracker->screen->display->compositor)
|
||||||
meta_windows);
|
meta_compositor_sync_stack (tracker->screen->display->compositor,
|
||||||
|
tracker->screen,
|
||||||
|
meta_windows);
|
||||||
g_list_free (meta_windows);
|
g_list_free (meta_windows);
|
||||||
|
|
||||||
meta_screen_restacked (tracker->screen);
|
meta_screen_restacked (tracker->screen);
|
||||||
|
|||||||
@@ -36,8 +36,6 @@
|
|||||||
|
|
||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
|
|
||||||
#include "x11/group-private.h"
|
|
||||||
|
|
||||||
#define WINDOW_HAS_TRANSIENT_TYPE(w) \
|
#define WINDOW_HAS_TRANSIENT_TYPE(w) \
|
||||||
(w->type == META_WINDOW_DIALOG || \
|
(w->type == META_WINDOW_DIALOG || \
|
||||||
w->type == META_WINDOW_MODAL_DIALOG || \
|
w->type == META_WINDOW_MODAL_DIALOG || \
|
||||||
@@ -1707,8 +1705,8 @@ get_default_focus_window (MetaStack *stack,
|
|||||||
MetaWindow *topmost_in_group;
|
MetaWindow *topmost_in_group;
|
||||||
MetaWindow *topmost_overall;
|
MetaWindow *topmost_overall;
|
||||||
MetaGroup *not_this_one_group;
|
MetaGroup *not_this_one_group;
|
||||||
GList *l;
|
GList *link;
|
||||||
|
|
||||||
transient_parent = NULL;
|
transient_parent = NULL;
|
||||||
topmost_in_group = NULL;
|
topmost_in_group = NULL;
|
||||||
topmost_overall = NULL;
|
topmost_overall = NULL;
|
||||||
@@ -1720,49 +1718,49 @@ get_default_focus_window (MetaStack *stack,
|
|||||||
stack_ensure_sorted (stack);
|
stack_ensure_sorted (stack);
|
||||||
|
|
||||||
/* top of this layer is at the front of the list */
|
/* top of this layer is at the front of the list */
|
||||||
for (l = stack->sorted; l != NULL; l = l->next)
|
link = stack->sorted;
|
||||||
|
|
||||||
|
while (link)
|
||||||
{
|
{
|
||||||
MetaWindow *window = l->data;
|
MetaWindow *window = link->data;
|
||||||
|
|
||||||
if (!window)
|
if (window &&
|
||||||
continue;
|
window != not_this_one &&
|
||||||
|
(window->unmaps_pending == 0) &&
|
||||||
if (window == not_this_one)
|
!window->minimized &&
|
||||||
continue;
|
(window->input || window->take_focus) &&
|
||||||
|
(workspace == NULL ||
|
||||||
if (window->unmaps_pending > 0)
|
meta_window_located_on_workspace (window, workspace)))
|
||||||
continue;
|
|
||||||
|
|
||||||
if (window->minimized)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!(window->input || window->take_focus))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (workspace != NULL && !meta_window_located_on_workspace (window, workspace))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (must_be_at_point && !window_contains_point (window, root_x, root_y))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (not_this_one != NULL)
|
|
||||||
{
|
{
|
||||||
if (transient_parent == NULL &&
|
if (not_this_one != NULL)
|
||||||
meta_window_get_transient_for (not_this_one) == window)
|
{
|
||||||
transient_parent = window;
|
if (transient_parent == NULL &&
|
||||||
|
not_this_one->xtransient_for != None &&
|
||||||
|
not_this_one->xtransient_for == window->xwindow &&
|
||||||
|
(!must_be_at_point ||
|
||||||
|
window_contains_point (window, root_x, root_y)))
|
||||||
|
transient_parent = window;
|
||||||
|
|
||||||
if (topmost_in_group == NULL &&
|
if (topmost_in_group == NULL &&
|
||||||
not_this_one_group != NULL &&
|
not_this_one_group != NULL &&
|
||||||
not_this_one_group == meta_window_get_group (window))
|
not_this_one_group == meta_window_get_group (window) &&
|
||||||
topmost_in_group = window;
|
(!must_be_at_point ||
|
||||||
|
window_contains_point (window, root_x, root_y)))
|
||||||
|
topmost_in_group = window;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (topmost_overall == NULL &&
|
||||||
|
window->type != META_WINDOW_DOCK &&
|
||||||
|
(!must_be_at_point ||
|
||||||
|
window_contains_point (window, root_x, root_y)))
|
||||||
|
topmost_overall = window;
|
||||||
|
|
||||||
|
/* We could try to bail out early here for efficiency in
|
||||||
|
* some cases, but it's just not worth the code.
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
if (topmost_overall == NULL && window->type != META_WINDOW_DOCK)
|
link = link->next;
|
||||||
topmost_overall = window;
|
|
||||||
|
|
||||||
/* We could try to bail out early here for efficiency in
|
|
||||||
* some cases, but it's just not worth the code.
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (transient_parent)
|
if (transient_parent)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user