Compare commits

..

59 Commits

Author SHA1 Message Date
Florian Müllner
97f2de37e1 Bump version to 3.13.3
Update NEWS.
2014-06-24 23:42:06 +02:00
Florian Müllner
967b6c33df window: Add user_op parameter to update_monitor()
When workspaces-only-on-primary is set and a window is moved back to the
primary, we also move it to the active workspace to avoid the confusion
of a visible window suddenly disappearing when crossing the monitor border.
However when the window is not actually moved by the user, preserving the
workspace makes more sense - we already do this in some cases (e.g. when
moving between primary monitors), but miss others (unplugging the previous
monitor); just add an explicit user_op parameter as used elsewhere to cover
all exceptions.

https://bugzilla.gnome.org/show_bug.cgi?id=731760
2014-06-24 23:42:06 +02:00
Florian Müllner
00c7a27732 window: Keep track of preferred output
Remember the last monitor a window was moved to by user action and
try to move it back on monitor changes; this should match user
expectations much better when a monitor is unplugged temporarily.

https://bugzilla.gnome.org/show_bug.cgi?id=731760
2014-06-24 23:42:06 +02:00
Florian Müllner
048ba353c4 window: Don't make windows on non-primaries sticky on restart
When workspaces-only-on-primary is set, a window can be on all
workspaces either because it is on a non-primary workspace, or
because it was explicitly made sticky. Only the latter is reflected
in _NET_WM_STATE, but both will result in a "magic" _NET_WM_DESKTOP,
which we (and probably other WMs) use to set the initial sticky state.
So to avoid confusing other WMs (or ourselves), make sure to only
have _NET_WM_STATE_STICKY reflected in _NET_WM_DESKTOP when unmanaging.
2014-06-24 23:01:59 +02:00
Florian Müllner
555e2f6de2 Revert "window: Move placement code from the constraints path"
Window state like maximization and minimization should be preserved
over restarts - in a patch review, this would qualify as "needs-work",
so revert the cleanup until the issues are fixed.

This reverts commit dc6decefb5.
2014-06-24 22:59:06 +02:00
Jasper St. Pierre
ff8d5281f0 frames: Simplify the clip region calculation
Since GTK+ already clips to the extended region for us, there's no need
to combine the two. This does lose the fast-path, but I don't actually
expect this to fire, as when we're composited, we really won't ever get
partial exposes.
2014-06-21 13:50:44 -04:00
Jasper St. Pierre
4f9b994e73 frames: Don't bother painting the background
GDK (and also GTK+!) do this for us already.
2014-06-21 13:50:43 -04:00
Jasper St. Pierre
b8b0dc5c78 frames: Hackily adapt to GTK+ drawing changes
mutter is quite bad at using GTK+ correctly, relying on dumb things
like the single-buffering stuff. Hack up a temporary fix for the
newer GTK+ rendering changes.
2014-06-21 13:50:36 -04:00
Nikita Churaev
d0cafab836 Change shadow radiuses to match new Adwaita more or less
Exact simmilarity is not possible yet due to different blurring algorithms.

https://bugzilla.gnome.org/show_bug.cgi?id=731866
2014-06-19 11:55:24 +02:00
Jasper St. Pierre
24d7c5ebe3 compositor: Simplify meta_window_actor_set_updates_frozen
Since we always call it with the same value, just push that
value into the implementation.
2014-06-17 13:10:42 -04:00
Jasper St. Pierre
dc6decefb5 window: Move placement code from the constraints path
This way, it's implemented as a special case in move_resize_internal,
which makes it a lot easier to manage.
2014-06-17 11:40:49 -04:00
Jasper St. Pierre
25d7e48077 constraints: Clean up logical operations
The logical version of the bitwise XOR operator ^ is !=. I don't
know why XOR was even used in the first place.
2014-06-17 11:21:25 -04:00
Jasper St. Pierre
b0b8f37240 window: Save the buffer_rect internally
Rather than calculate it speculatively with the current properties
which may be too new or too out of date, make sure it always fits
with the proper definition. We update it when we update the toplevel
window for X11, and when a Wayland surface is committed with a newly
attached buffer.
2014-06-17 11:15:32 -04:00
Jasper St. Pierre
188e4e1b92 window: Rename get_input_rect to get_buffer_rect
With get_input_region existing, get_input_rect is a misnomer. Really,
it's about the geometry of the output surface, and it's only used that
way in the compositor code.

Way back when in GNOME 3.2, get_input_rect was added when we added
invisible borders. get_outer_rect was always synonymous with server-side
geometry of the toplevel. get_outer_rect was used for both user-side
policy (the "frame rect") and to get the geometry of the window.

Invisible borders were meant to extend the input region of the frame
window silently. Since most users of get_outer_rect cared about the
frame rect, we kept that the same and added a new method, get_input_rect
to get the full rect of the framed window with all invisible borders for
input kept on.

As time went on and CSD and Wayland became a reality, the relationship
between the server-side geometry and the "frame rect" became more
complicated, as can be evidenced by the recent commits. Since clients
don't tend to be framed anymore, they set their own input region.

get_buffer_rect is also sort of a poor name, since X11 doesn't really
have buffers, but we don't really have many other alternatives.

This doesn't change any of the code, nor the meaning. It will always
refer to the rectangle where the toplevel should be placed.
2014-06-17 10:33:52 -04:00
Jasper St. Pierre
9d5273bb15 window: Fix get_input_rect in a hacky way
All of the users of get_input_rect don't actually want a synthesized
input rect based off of the current margins. What they really want is
the last-configured size of the toplevel window.

Since we don't properly track this anymore in the generic MetaWindow,
use XGetWindowAttributes to fetch a server-side rectangle. This is a
bad layer violation, but since the window geometry code will have to
be rewritten anyway for the Wayland set_window_geometry, let's just
push a hacky fix for now.
2014-06-16 18:34:07 -04:00
Jasper St. Pierre
3c0fae74f1 window: Move get_toplevel_xwindow to window-x11 2014-06-16 18:29:38 -04:00
Jasper St. Pierre
86dae6d4c7 theme: Replace char array element comparisons with strncmp
https://bugzilla.gnome.org/show_bug.cgi?id=662962
2014-06-14 14:12:53 -04:00
Jasper St. Pierre
d06600aeb0 theme: Remove dead code
While the comment claims that we may want to keep this around
for optimization purposes, the operations are raw bitmap operations
that would be cleaner done in cairo.

https://bugzilla.gnome.org/show_bug.cgi?id=662962
2014-06-14 14:12:52 -04:00
Jasper St. Pierre
895a3d1f39 theme: Properly indent code
s/tabs/spaces/

https://bugzilla.gnome.org/show_bug.cgi?id=662962
2014-06-14 14:11:32 -04:00
Jasper St. Pierre
381ef5c683 theme: Consolidate unused ops
https://bugzilla.gnome.org/show_bug.cgi?id=662962
2014-06-14 14:11:00 -04:00
Jasper St. Pierre
62097897be theme: Remove unused RECTANGLE code
https://bugzilla.gnome.org/show_bug.cgi?id=662962
2014-06-14 14:04:59 -04:00
Jasper St. Pierre
2d2c47ba49 display: Remove unused variable 2014-06-12 17:46:23 -04:00
Jasper St. Pierre
89cdfc9194 display: Use G_SOURCE_CONTINUE / G_SOURCE_REMOVE 2014-06-12 17:46:23 -04:00
Jasper St. Pierre
ad60ea9e0e display: Use meta_window_has_pointer instead of XQueryPointer 2014-06-12 17:46:23 -04:00
Florian Müllner
a7350475e8 workspace: Extend builtin struts to screen edge when possible
Struts are defined in terms of screen edges, so expand the rectangles
we get via set_builtin_struts() accordingly. However we do want to
allow chrome on edges between monitors, in which case the expansion
would render an entire monitor unusable - don't expand the rectangles
in that case, which means we will only use them for constraining
windows but ignore them for the client-visible _NET_WORKAREA property.

https://bugzilla.gnome.org/show_bug.cgi?id=730527
2014-06-12 15:28:46 +02:00
Florian Müllner
f3d7c9cff9 testboxes: Update test cases
Who cares? We do now ...

https://bugzilla.gnome.org/show_bug.cgi?id=730527
2014-06-12 15:28:46 +02:00
Florian Müllner
906cbeed61 boxes: Ignore struts that don't attach to the side they claim
Like the _NET_WM_STRUT/_NET_WM_STRUT_PARTIAL client properties,
_NET_WORKAREA is defined in terms of screen geometry rather than
taking individual monitors into account. However we do want to
allow system chrome to be attached to a monitor edge rather than
a screen edges under some circumstances. As not all clients can
be assumed to deal gracefully with the resulting workarea, use
those "struts" only internally for constraining windows, but
ignore them when exporting _NET_WORKAREA.

https://bugzilla.gnome.org/show_bug.cgi?id=730527
2014-06-12 15:28:42 +02:00
Florian Müllner
0fccb0fc86 testboxes: Fix find_closest_point_to_line() test
Eeeks, testing floating points for equality ...
2014-06-12 01:39:54 +02:00
Florian Müllner
8100cefd4c screen: Split workspace initialization from meta_screen_new()
Since commit 8b2b65246a, we assume that the compositor always
exists. Alas, the assumption is wrong - the compositor is currently
initialized after the screen, but meta_screen_new() itself may
call a compositor function if initialization involves a workspace
switch (which will happen when meta_workspace_activate() is called
more than once and for different workspaces - or in other words,
when _NET_CURRENT_DESKTOP is set and not 0).
So carefully split out the offending bits and only call them after
the compositor has been initialized.

https://bugzilla.gnome.org/show_bug.cgi?id=731332
2014-06-11 23:35:34 +02:00
Florian Müllner
d7e99a3f86 prefs: Queue change notification when app menu visibility changed
Toggling the option should have an immediate effect, not only on
frame/state changes.
2014-06-11 23:34:09 +02:00
Jasper St. Pierre
6af944fe2c native: Add a warp_pointer implementation
Use the new clutter_evdev_warp_pointer method to implement it.
2014-06-11 16:42:05 -04:00
Jasper St. Pierre
12fc394b92 display: Fix the logic for moving attached dialogs
If we have a tree of a window, a non-attached dialog, and then an
attached dialog, we want to move the second window, not the attached
dialog or the topmost. In other words, we want to move the first
non-attached window, or the first "freefloating window".

This happens in Firefox, whose Preferences dialog is freefloating,
but suboptions of those are modal dialogs.
2014-06-11 16:42:05 -04:00
Jasper St. Pierre
53814fefc1 Move all X11 event processing to a new file in x11/ 2014-06-11 16:28:45 -04:00
Jasper St. Pierre
e87a01c80b wayland-touch: Rearrange header slightly 2014-06-11 16:28:45 -04:00
Jasper St. Pierre
21d7c1a850 wayland-pointer: Remove useless initialization
There is no way this value will ever be read, because we set the
cursor_surface to NULL, this is set at the same time as cursor_surface,
and it's only read if cursor_surface is non-NULL.
2014-06-11 15:15:58 -04:00
Jasper St. Pierre
e33c58297d wayland-surface: Subsurfaces start out in synchronous mode 2014-06-11 12:34:44 -04:00
Jasper St. Pierre
5350120db4 wayland-surface: Fix whitespace 2014-06-11 12:34:17 -04:00
Jasper St. Pierre
0997cf7fee Update .gitignore
These aren't generated in the data/ subdir.
2014-06-11 09:24:59 -04:00
Florian Müllner
af3aae7295 meta-window-actor: Don't add shadows to popups if the toolkit already does
GTK+ will add its own shadows client-side, so we don't need to anymore.

https://bugzilla.gnome.org/show_bug.cgi?id=731353
2014-06-10 13:40:33 +02:00
Florian Müllner
98e219da4b shadow-factory: Make sure to never use a negative spread
The smallest possible spread corresponds to an unblurred shadow, which
neither grows nor shrinks - thus the spread should be zero not negative
as returned by our current calculation.

https://bugzilla.gnome.org/show_bug.cgi?id=731353
2014-06-10 13:40:32 +02:00
Florian Müllner
fba022cc06 window-x11: Handle legacy fullscreen requests
Doing this on the actual resize requests makes more sense than
handling it as a window-manager imposed constraints, so move
the code accordingly.

https://bugzilla.gnome.org/show_bug.cgi?id=730681
2014-06-09 22:27:33 +02:00
Florian Müllner
3f6c6f1dd9 constraints: Translate frame to client rect for legacy fullscreen check
Stupid apps fullscreen themselves by resizing the client window to
monitor size. A monitor-sized frame rect on the other hand is perfectly
normal on monitors without struts - stop force-fullscreening those
and catch the real baddies instead.

https://bugzilla.gnome.org/show_bug.cgi?id=730681
2014-06-09 21:28:50 +02:00
Florian Müllner
ebc2e7221b window-x11: Fix silly regression
First we figure out the window type, then we ignore it - ouch.
2014-06-07 12:00:17 +02:00
Rico Tzschichholz
7cb30ced23 configure.ac: Modernize autoconf/libtool dependencies and macro usage 2014-06-05 18:05:19 +02:00
Rico Tzschichholz
7b449ac56c configure.ac: Group hard-dependencies together rather than split them up 2014-06-05 18:05:14 +02:00
Rico Tzschichholz
724953101d configure.ac: Drop obsolete shape/xsync confflags
In addition to 20a0eb9809
2014-06-05 18:04:59 +02:00
Rico Tzschichholz
8734477d52 meta: Add generated meta-version.h
Avoid populating *_VERSION constants through cflags in pkg-config-file
which could be overridden by the project using it. Properly prefix the
defines with META_ to make gi-scanner happy.
2014-06-05 14:05:16 +02:00
Rico Tzschichholz
ec8ba4b5f9 build: Move data files to their dedicated subfolder 2014-06-05 10:50:15 +02:00
Carlos Garnacho
2250865eb6 wayland: Implement the server side bits of wl_touch_interface
Clutter touch events are translated into events being sent down
the interface resource, with the exception of FRAME/CANCEL events,
which are handled directly via an evdev event filter.

The seat now announces invariably the WL_SEAT_CAPABILITY_TOUCH
capability, this should be eventually updated as devices come and
go.

The creation of MetaWaylandTouchSurface structs is dynamic, attached
to the lifetime of first/last touch on the client surface, and only
if the surface requests the wl_touch interface. MetaWaylandTouchInfo
structs are created to track individual touches, and are locked to
a single MetaWaylandTouchSurface (the implicit grab surface) determined
on CLUTTER_TOUCH_BEGIN.

https://bugzilla.gnome.org/show_bug.cgi?id=724442
2014-06-04 23:37:45 +02:00
Rico Tzschichholz
847a3bbee3 build: Fix some warnings and clean up a bit 2014-06-04 19:31:37 +02:00
Rico Tzschichholz
410a002ddd build: Do not distribute generated desktop-files 2014-06-04 16:13:11 +02:00
Rico Tzschichholz
8766db2593 common: Do not leak MetaResizePopup to the public api 2014-06-04 15:53:29 +02:00
Jasper St. Pierre
e362227514 window-x11: Don't ever send ConfigureNotifies for OR windows
There's a race here. If an OR window hides itself, moves, and then shows
itself, we will send a ConfigureNotify for the old size of the window
and might receive it after the client moves itself, causing us to show
the window at the wrong location.

Simply not sending the ConfigureNotify is the easiest thing to do.
2014-06-03 11:35:20 -04:00
Jasper St. Pierre
da311f266d window: Make sure to update client_rect for OR windows too
Before we unmanage, we send a ConfigureNotify to clients to let them
know if their frame is destroyed. We do this for OR windows too, even if
we really probably shouldn't.

This is based off of the client_rect. Since we listen to ConfigureNotify
on OR windows, we'll receive the event. If we don't ever update the
client_rect when moving or resizing OR windows, then we'll send
ourselves a ConfigureNotify for a 0x0 size and then think that the
client chose a new size for itself. Since our get_paint_volume is based
on that rectangle, but the TFP code inside Cogl uses XGetGeometry
itself, we get weird flickering artifacts.
2014-06-03 11:35:19 -04:00
Rico Tzschichholz
f5a4e996a8 display: Remove the screen from get_tab_list 2014-06-03 14:40:15 +02:00
Florian Müllner
a7f083897f frames: Only skip updating prelight when both control and state match
prelit_control is used for both prelight and pressed states, so the early
return in update_prelit_control() misses the case where prelit_control
already matches the control we are updating, but its state is PRESSED
rather than PRELIGHT. Fix the condition to not have pressed controls
linger around erroneously.

https://bugzilla.gnome.org/show_bug.cgi?id=731058
2014-06-02 23:49:48 +02:00
Florian Müllner
e2105dc721 frames: Fix pressed state of window menu buttons
Since window menus have been moved to the compositor, the pressed
state of the corresponding window buttons is messed up, as it is
reset immediately when getting a LeaveNotify event due to the
compositor taking a grab. Fix this by ignoring that particular
event.

https://bugzilla.gnome.org/show_bug.cgi?id=731058
2014-06-02 23:49:48 +02:00
Florian Müllner
b64548ee1f Pass button_rect when opening window menu from button
When opening the window menu without an associated control - e.g.
by right-clicking the titlebar or by keyboard - using coordinates
for the menu position is appropriate. However when the menu is
associated with a window button, the expected behavior in the
shell can be implemented much easier with the full button geometry:
the menu will point to the center of the button's bottom edge
rather than align to the left/right side of the titlebar as it
does now, and the clickable area where a release event does not
dismiss the menu will match the actual clickable area in mutter.

So add an additional show_window_menu_for_rect() function and
use it when opening the menu from a button.

https://bugzilla.gnome.org/show_bug.cgi?id=731058
2014-06-02 23:49:48 +02:00
Jasper St. Pierre
53425fa721 window: Make sure not to respond to input events on OR windows
This can happen since we select for events on the root window, and
clients themselves might not select for input, meaning the X server
will bubble up. Just do nothing and ignore the event in this case.

This should hopefully fix some of the

Window manager warning: Log level 8: meta_window_raise: assertion '!window->override_redirect' failed
Window manager warning: Log level 8: meta_window_focus: assertion '!window->override_redirect' failed

spam that people have been seeing.
2014-06-02 15:51:41 -04:00
75 changed files with 3240 additions and 3234 deletions

View File

@@ -1,35 +0,0 @@
Makefile
Makefile.in
aclocal.m4
confdefs.h
config.cache
config.guess
config.h
config.log
config.status
config.sub
configure
configure.scan
libtool
ltconfig
ltmain.sh
stamp-h
stamp-h.in
stamp-h1
stamp.h
version.h
config.h.in
install-sh
missing
mkinstalldirs
INSTALL
intl
ABOUT-NLS
COPYING
intltool-*
metacity.spec
autom4te.cache
compile
depcomp
omf.make
xmldocs.make

21
.gitignore vendored
View File

@@ -3,6 +3,7 @@ Makefile.in
Makefile.in.in
aclocal.m4
autom4te.cache
build-aux
compile
config.guess
config.h
@@ -19,11 +20,11 @@ libtool
ltmain.sh
missing
.deps
src/50-mutter-navigation.xml
src/50-mutter-system.xml
src/50-mutter-windows.xml
src/mutter.desktop
src/mutter-wayland.desktop
50-mutter-navigation.xml
50-mutter-system.xml
50-mutter-windows.xml
mutter.desktop
mutter-wayland.desktop
*.o
*.a
*.lo
@@ -32,10 +33,6 @@ src/mutter-wayland.desktop
*.swp
*.gir
*.typelib
tidy-enum-types.[ch]
tidy-marshal.[ch]
stamp-tidy-enum-types.h
stamp-tidy-marshal.h
stamp-h1
*.gmo
*.make
@@ -44,8 +41,6 @@ stamp-it
.intltool-merge-cache
POTFILES
po/*.pot
50-metacity-desktop-key.xml
50-metacity-key.xml
libmutter.pc
mutter
org.gnome.mutter.gschema.valid
@@ -66,9 +61,6 @@ test-focus
test-gravity
test-resizing
test-size-hints
# We can't say just "wm-tester" here or it will ignore the directory
# rather than the binary
src/wm-tester/wm-tester
INSTALL
mkinstalldirs
src/mutter-enum-types.[ch]
@@ -84,6 +76,7 @@ src/xdg-shell-protocol.c
src/xdg-shell-server-protocol.h
src/xserver-protocol.c
src/xserver-server-protocol.h
src/meta/meta-version.h
doc/reference/*.args
doc/reference/*.bak
doc/reference/*.hierarchy

View File

@@ -1,10 +1,13 @@
SUBDIRS=src po doc
SUBDIRS = data src po doc
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
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
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}

13
NEWS
View File

@@ -1,3 +1,16 @@
3.13.3
======
* Improve behavior of window buttons with compositor menus [Florian; #731058]
* Implement touch support on wayland [Carlos; #724442]
* Update window shadows [Nikita; #731866]
* Keep windows on the preferred output [Florian; #731760]
* Misc bug fixes [Jonas, Florian, Jasper; #729601, #730681, #731353, #731332,
#730527, #662962]
Contributors:
Jonas Ådahl, Nikita Churaev, Carlos Garnacho, Florian Müllner,
Jasper St. Pierre, Rico Tzschichholz
3.13.2
======
* Add basic HiDPI support on wayland [Adel; #728902]

View File

@@ -5,7 +5,7 @@ srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
PKG_NAME="mutter"
REQUIRED_AUTOMAKE_VERSION=1.10
REQUIRED_AUTOMAKE_VERSION=1.11
(test -f $srcdir/configure.ac \
&& test -d $srcdir/src) || {

View File

@@ -1,9 +1,8 @@
AC_PREREQ(2.50)
AC_CONFIG_MACRO_DIR([m4])
AC_PREREQ(2.62)
m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [13])
m4_define([mutter_micro_version], [2])
m4_define([mutter_micro_version], [3])
m4_define([mutter_version],
[mutter_major_version.mutter_minor_version.mutter_micro_version])
@@ -14,6 +13,7 @@ AC_INIT([mutter], [mutter_version],
[http://bugzilla.gnome.org/enter_bug.cgi?product=mutter])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_SRCDIR(src/core/display.c)
AC_CONFIG_HEADERS(config.h)
@@ -40,12 +40,14 @@ GETTEXT_PACKAGE=mutter
AC_SUBST(GETTEXT_PACKAGE)
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[Name of default gettext domain])
IT_PROG_INTLTOOL([0.34.90])
LT_PREREQ([2.2.6])
LT_INIT([disable-static])
IT_PROG_INTLTOOL([0.41])
AC_PROG_CC
AC_ISC_POSIX
AC_PROG_CC_C_O
AC_PROG_INSTALL
AC_HEADER_STDC
AC_LIBTOOL_WIN32_DLL
AM_PROG_LIBTOOL
PKG_PROG_PKG_CONFIG([0.21])
# Sets GLIB_GENMARSHAL and GLIB_MKENUMS
AM_PATH_GLIB_2_0()
@@ -75,8 +77,13 @@ MUTTER_PC_MODULES="
cairo >= 1.10.0
gsettings-desktop-schemas >= 3.7.3
xcomposite >= 0.2 xfixes xext xdamage xi >= 1.6.0
xcursor
$CLUTTER_PACKAGE >= 1.17.5
clutter-wayland-1.0
clutter-wayland-compositor-1.0
clutter-egl-1.0
cogl-1.0 >= 1.17.1
wayland-server >= 1.4.93
upower-glib >= 0.99.0
gnome-desktop-3.0
"
@@ -107,26 +114,12 @@ AC_ARG_WITH(libcanberra,
[disable the use of libcanberra for playing sounds]),,
with_libcanberra=auto)
AC_ARG_ENABLE(xsync,
AC_HELP_STRING([--disable-xsync],
[disable mutter's use of the XSync extension]),,
enable_xsync=auto)
AC_ARG_ENABLE(shape,
AC_HELP_STRING([--disable-shape],
[disable mutter's use of the shaped window extension]),,
enable_shape=auto)
AC_ARG_WITH([xwayland-path],
[AS_HELP_STRING([--with-xwayland-path], [Absolute path for an X Wayland server])],
[XWAYLAND_PATH="$withval"],
[XWAYLAND_PATH="$bindir/Xwayland"])
AM_GLIB_GNU_GETTEXT
## here we get the flags we'll actually use
# GRegex requires Glib-2.14.0
PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.14.0)
# Unconditionally use this dir to avoid a circular dep with gnomecc
GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings"
@@ -191,15 +184,12 @@ if test x$found_introspection != xno; then
AC_SUBST(META_GIR)
fi
MUTTER_PC_MODULES="$MUTTER_PC_MODULES xcursor"
AC_PATH_PROG([WAYLAND_SCANNER],[wayland-scanner],[no])
AS_IF([test "x$WAYLAND_SCANNER" = "xno"],
AC_MSG_ERROR([Could not find wayland-scanner in your PATH, required for parsing wayland extension protocols]))
AC_SUBST([WAYLAND_SCANNER])
AC_SUBST(XWAYLAND_PATH)
MUTTER_PC_MODULES="$MUTTER_PC_MODULES clutter-wayland-1.0 clutter-wayland-compositor-1.0 clutter-egl-1.0 wayland-server >= 1.4.93"
PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES)
PKG_CHECK_MODULES(MUTTER_NATIVE_BACKEND, [libdrm libsystemd], [have_native_backend=yes], [have_native_backend=no])
@@ -299,17 +289,6 @@ fi
AM_CONDITIONAL(HAVE_SM, test "$found_sm" = "yes")
HOST_ALIAS=$host_alias
AC_SUBST(HOST_ALIAS)
AC_PATH_PROG(GDK_PIXBUF_CSOURCE, gdk-pixbuf-csource, no)
if test x"$GDK_PIXBUF_CSOURCE" = xno; then
AC_MSG_ERROR([gdk-pixbuf-csource executable not found in your path - should be installed with GTK])
fi
AC_SUBST(GDK_PIXBUF_CSOURCE)
AC_PATH_PROG(ZENITY, zenity, no)
if test x"$ZENITY" = xno; then
AC_MSG_ERROR([zenity not found in your path - needed for dialogs])
@@ -324,11 +303,6 @@ fi
GTK_DOC_CHECK([1.15], [--flavour no-tmpl])
AC_CHECK_DECL([GL_EXT_x11_sync_object],
[],
[AC_MSG_ERROR([GL_EXT_x11_sync_object definition not found, please update your GL headers])],
[#include <GL/glx.h>])
#### Warnings (last since -Werror can disturb other tests)
# Stay command-line compatible with the gnome-common configure option. Here
@@ -397,6 +371,7 @@ changequote([,])dnl
AC_CONFIG_FILES([
Makefile
data/Makefile
doc/Makefile
doc/man/Makefile
doc/reference/Makefile
@@ -404,6 +379,7 @@ doc/reference/meta-docs.sgml
src/Makefile
src/libmutter.pc
src/compositor/plugins/Makefile
src/meta/meta-version.h
po/Makefile.in
])

View File

@@ -1,3 +1,36 @@
defaultcursordir = $(datadir)/mutter/cursors
desktopfiles_in_files = \
mutter.desktop.in \
mutter-wayland.desktop.in
desktopfilesdir = $(datadir)/applications
desktopfiles_DATA = $(desktopfiles_in_files:.desktop.in=.desktop)
dist_defaultcursor_DATA = left_ptr.png
@INTLTOOL_DESKTOP_RULE@
xml_in_files = \
50-mutter-navigation.xml.in \
50-mutter-system.xml.in \
50-mutter-windows.xml.in
xmldir = $(GNOME_KEYBINDINGS_KEYSDIR)
xml_DATA = $(xml_in_files:.xml.in=.xml)
gschema_in_files = \
org.gnome.mutter.gschema.xml.in \
org.gnome.mutter.wayland.gschema.xml.in
gsettings_SCHEMAS = $(gschema_in_files:.xml.in=.xml)
@INTLTOOL_XML_NOMERGE_RULE@
@GSETTINGS_RULES@
convertdir = $(datadir)/GConf/gsettings
convert_DATA = mutter-schemas.convert
CLEANFILES = \
$(desktopfiles_DATA) \
$(gsettings_SCHEMAS) \
$(xml_DATA)
EXTRA_DIST = \
$(convert_DATA) \
$(desktopfiles_in_files) \
$(gschema_in_files) \
$(xml_in_files)

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -555,7 +555,7 @@ meta_window_is_monitor_sized
meta_window_is_override_redirect
meta_window_is_skip_taskbar
meta_window_get_rect
meta_window_get_input_rect
meta_window_get_buffer_rect
meta_window_get_frame_rect
meta_window_get_outer_rect
meta_window_client_rect_to_frame_rect

View File

@@ -1,8 +1,11 @@
# List of source files containing translatable strings.
# Please keep this file sorted alphabetically.
src/50-mutter-navigation.xml.in
src/50-mutter-system.xml.in
src/50-mutter-windows.xml.in
data/50-mutter-navigation.xml.in
data/50-mutter-system.xml.in
data/50-mutter-windows.xml.in
data/mutter.desktop.in
data/org.gnome.mutter.gschema.xml.in
data/org.gnome.mutter.wayland.gschema.xml.in
src/backends/meta-monitor-manager.c
src/compositor/compositor.c
src/compositor/meta-background.c
@@ -18,9 +21,6 @@ src/core/prefs.c
src/core/screen.c
src/core/util.c
src/core/window.c
src/mutter.desktop.in
src/org.gnome.mutter.gschema.xml.in
src/org.gnome.mutter.wayland.gschema.xml.in
src/ui/frames.c
src/ui/resizepopup.c
src/ui/theme.c

View File

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

View File

@@ -5,38 +5,35 @@ lib_LTLIBRARIES = libmutter.la
SUBDIRS=compositor/plugins
INCLUDES= \
AM_CPPFLAGS = \
-DCLUTTER_ENABLE_COMPOSITOR_API \
-DCLUTTER_ENABLE_EXPERIMENTAL_API \
-DCOGL_ENABLE_EXPERIMENTAL_API \
-DCOGL_ENABLE_EXPERIMENTAL_2_0_API \
$(MUTTER_CFLAGS) \
$(MUTTER_NATIVE_BACKEND_CFLAGS) \
-I$(builddir) \
-I$(srcdir) \
-I$(srcdir)/backends \
-I$(srcdir)/core \
-I$(srcdir)/ui \
-I$(srcdir)/compositor \
-DMUTTER_LIBEXECDIR=\"$(libexecdir)\" \
-DHOST_ALIAS=\"@HOST_ALIAS@\" \
-DMUTTER_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\" \
-DMUTTER_LOCALEDIR=\"$(localedir)\" \
-DMUTTER_PKGDATADIR=\"$(pkgdatadir)\" \
-DMUTTER_DATADIR=\"$(datadir)\" \
-DG_LOG_DOMAIN=\"mutter\" \
-DSN_API_NOT_YET_FROZEN=1 \
-DMUTTER_MAJOR_VERSION=$(MUTTER_MAJOR_VERSION) \
-DMUTTER_MINOR_VERSION=$(MUTTER_MINOR_VERSION) \
-DMUTTER_MICRO_VERSION=$(MUTTER_MICRO_VERSION) \
-DMUTTER_PLUGIN_API_VERSION=$(MUTTER_PLUGIN_API_VERSION) \
-DMUTTER_PKGLIBDIR=\"$(pkglibdir)\" \
-DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\" \
-DMUTTER_PLUGIN_DIR=\"$(MUTTER_PLUGIN_DIR)\" \
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \
-DXWAYLAND_PATH='"@XWAYLAND_PATH@"'
-DXWAYLAND_PATH=\"$(XWAYLAND_PATH)\"
mutter_built_sources = \
$(dbus_idle_built_sources) \
$(dbus_display_config_built_sources) \
$(dbus_login1_built_sources) \
meta/meta-version.h \
mutter-enum-types.h \
mutter-enum-types.c \
gtk-shell-protocol.c \
@@ -118,8 +115,6 @@ libmutter_la_SOURCES = \
compositor/meta-surface-actor-wayland.h \
compositor/meta-stage.h \
compositor/meta-stage.c \
compositor/meta-sync-ring.c \
compositor/meta-sync-ring.h \
compositor/meta-texture-rectangle.c \
compositor/meta-texture-rectangle.h \
compositor/meta-texture-tower.c \
@@ -196,6 +191,8 @@ libmutter_la_SOURCES = \
x11/iconcache.h \
x11/async-getprop.c \
x11/async-getprop.h \
x11/events.c \
x11/events.h \
x11/group-private.h \
x11/group-props.c \
x11/group-props.h \
@@ -225,6 +222,8 @@ libmutter_la_SOURCES = \
wayland/meta-wayland-pointer.h \
wayland/meta-wayland-seat.c \
wayland/meta-wayland-seat.h \
wayland/meta-wayland-touch.c \
wayland/meta-wayland-touch.h \
wayland/meta-wayland-surface.c \
wayland/meta-wayland-surface.h \
wayland/meta-wayland-types.h \
@@ -258,7 +257,7 @@ libmutter_la_LIBADD = $(MUTTER_LIBS) $(MUTTER_NATIVE_BACKEND_LIBS)
# Headers installed for plugins; introspected information will
# be extracted into Mutter-<version>.gir
libmutterinclude_base_headers = \
libmutterinclude_headers = \
meta/barrier.h \
meta/boxes.h \
meta/common.h \
@@ -287,6 +286,13 @@ libmutterinclude_base_headers = \
meta/window.h \
meta/workspace.h
libmutterinclude_built_headers = \
meta/meta-version.h
libmutterinclude_base_headers = \
$(libmutterinclude_headers) \
$(libmutterinclude_built_headers)
# Excluded from scanning for introspection but installed
# atomnames.h: macros cause problems for scanning process
libmutterinclude_extra_headers = \
@@ -295,9 +301,12 @@ libmutterinclude_extra_headers = \
libmutterincludedir = $(includedir)/mutter/meta
libmutterinclude_HEADERS = \
$(libmutterinclude_base_headers) \
$(libmutterinclude_headers) \
$(libmutterinclude_extra_headers)
nodist_libmutterinclude_HEADERS = \
$(libmutterinclude_built_headers)
bin_PROGRAMS=mutter
mutter_SOURCES = core/mutter.c
@@ -326,7 +335,7 @@ INTROSPECTION_GIRS = Meta-$(api_version).gir
Meta-$(api_version).gir: libmutter.la
@META_GIR@_INCLUDES = GObject-2.0 GDesktopEnums-3.0 Gdk-3.0 Gtk-3.0 Clutter-1.0 xlib-2.0 xfixes-4.0 Cogl-1.0
@META_GIR@_EXPORT_PACKAGES = libmutter
@META_GIR@_CFLAGS = $(INCLUDES)
@META_GIR@_CFLAGS = $(AM_CPPFLAGS)
@META_GIR@_LIBS = libmutter.la
@META_GIR@_FILES = \
mutter-enum-types.h \
@@ -346,53 +355,19 @@ testboxes_LDADD = $(MUTTER_LIBS) libmutter.la
testgradient_LDADD = $(MUTTER_LIBS) libmutter.la
testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter.la
@INTLTOOL_DESKTOP_RULE@
desktopfilesdir=$(datadir)/applications
desktopfiles_in_files=mutter.desktop.in
desktopfiles_files=$(desktopfiles_in_files:.desktop.in=.desktop)
desktopfiles_DATA = $(desktopfiles_files)
xmldir = @GNOME_KEYBINDINGS_KEYSDIR@
xml_in_files = \
50-mutter-navigation.xml.in \
50-mutter-system.xml.in \
50-mutter-windows.xml.in
xml_DATA = $(xml_in_files:.xml.in=.xml)
dbus_idle_built_sources = meta-dbus-idle-monitor.c meta-dbus-idle-monitor.h
gsettings_SCHEMAS = org.gnome.mutter.gschema.xml org.gnome.mutter.wayland.gschema.xml
@INTLTOOL_XML_NOMERGE_RULE@
@GSETTINGS_RULES@
convertdir = $(datadir)/GConf/gsettings
convert_DATA = mutter-schemas.convert
CLEANFILES = \
mutter.desktop \
mutter-wm.desktop \
org.gnome.mutter.gschema.xml \
org.gnome.mutter.wayland.gschema.xml \
$(xml_DATA) \
$(mutter_built_sources) \
$(libmutterinclude_built_headers) \
$(typelib_DATA) \
$(gir_DATA)
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libmutter.pc
EXTRA_DIST=$(desktopfiles_files) \
$(wmproperties_files) \
$(IMAGES) \
$(desktopfiles_in_files) \
$(wmproperties_in_files) \
$(xml_in_files) \
EXTRA_DIST = \
$(wayland_protocols) \
org.gnome.mutter.gschema.xml.in \
org.gnome.mutter.wayland.gschema.xml.in \
mutter-schemas.convert \
libmutter.pc.in \
mutter-enum-types.h.in \
mutter-enum-types.c.in \

View File

@@ -103,14 +103,6 @@ meta_backend_real_ungrab_device (MetaBackend *backend,
return TRUE;
}
static void
meta_backend_real_warp_pointer (MetaBackend *backend,
int x,
int y)
{
/* Do nothing */
}
static void
meta_backend_class_init (MetaBackendClass *klass)
{
@@ -122,7 +114,6 @@ meta_backend_class_init (MetaBackendClass *klass)
klass->create_cursor_renderer = meta_backend_real_create_cursor_renderer;
klass->grab_device = meta_backend_real_grab_device;
klass->ungrab_device = meta_backend_real_ungrab_device;
klass->warp_pointer = meta_backend_real_warp_pointer;
}
static void

View File

@@ -174,6 +174,20 @@ meta_backend_native_create_cursor_renderer (MetaBackend *backend)
return g_object_new (META_TYPE_CURSOR_RENDERER_NATIVE, NULL);
}
static void
meta_backend_native_warp_pointer (MetaBackend *backend,
int x,
int y)
{
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
ClutterInputDevice *device = clutter_device_manager_get_core_device (manager, CLUTTER_POINTER_DEVICE);
/* XXX */
guint32 time_ = 0;
clutter_evdev_warp_pointer (device, time_, x, y);
}
static void
meta_backend_native_class_init (MetaBackendNativeClass *klass)
{
@@ -183,6 +197,8 @@ meta_backend_native_class_init (MetaBackendNativeClass *klass)
backend_class->create_idle_monitor = meta_backend_native_create_idle_monitor;
backend_class->create_monitor_manager = meta_backend_native_create_monitor_manager;
backend_class->create_cursor_renderer = meta_backend_native_create_cursor_renderer;
backend_class->warp_pointer = meta_backend_native_warp_pointer;
}
static void

View File

@@ -15,8 +15,7 @@ struct _MetaCompositor
{
MetaDisplay *display;
guint pre_paint_func_id;
guint post_paint_func_id;
guint repaint_func_id;
gint64 server_time_query_time;
gint64 server_time_offset;
@@ -39,9 +38,6 @@ struct _MetaCompositor
gint switch_workspace_in_progress;
MetaPluginManager *plugin_mgr;
gboolean frame_has_updated_xsurfaces;
gboolean have_x11_sync_object;
};
/* Wait 2ms after vblank before starting to draw next frame */

View File

@@ -79,7 +79,6 @@
#include "frame.h"
#include <X11/extensions/shape.h>
#include <X11/extensions/Xcomposite.h>
#include "meta-sync-ring.h"
#include "backends/meta-backend.h"
#include "backends/x11/meta-backend-x11.h"
@@ -137,11 +136,7 @@ meta_switch_workspace_completed (MetaCompositor *compositor)
void
meta_compositor_destroy (MetaCompositor *compositor)
{
clutter_threads_remove_repaint_func (compositor->pre_paint_func_id);
clutter_threads_remove_repaint_func (compositor->post_paint_func_id);
if (compositor->have_x11_sync_object)
meta_sync_ring_destroy ();
clutter_threads_remove_repaint_func (compositor->repaint_func_id);
}
static void
@@ -151,8 +146,6 @@ process_damage (MetaCompositor *compositor,
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
meta_window_actor_process_x11_damage (window_actor, event);
compositor->frame_has_updated_xsurfaces = TRUE;
}
static Window
@@ -576,8 +569,6 @@ meta_compositor_manage (MetaCompositor *compositor)
* contents until we show the stage.
*/
XMapWindow (xdisplay, compositor->output);
compositor->have_x11_sync_object = meta_sync_ring_init (display);
}
redirect_windows (display->screen);
@@ -700,12 +691,11 @@ meta_compositor_remove_window (MetaCompositor *compositor,
}
void
meta_compositor_set_updates_frozen (MetaCompositor *compositor,
MetaWindow *window,
gboolean updates_frozen)
meta_compositor_sync_updates_frozen (MetaCompositor *compositor,
MetaWindow *window)
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
meta_window_actor_set_updates_frozen (window_actor, updates_frozen);
meta_window_actor_sync_updates_frozen (window_actor);
}
void
@@ -789,10 +779,6 @@ meta_compositor_process_event (MetaCompositor *compositor,
if (!meta_is_wayland_compositor () && event->type == MapNotify)
clutter_x11_handle_event (event);
if (compositor->have_x11_sync_object &&
event->type == (compositor->display->xsync_event_base + XSyncAlarmNotify))
meta_sync_ring_handle_event ((XSyncAlarmNotifyEvent *) event);
/* The above handling is basically just "observing" the events, so we return
* FALSE to indicate that the event should not be filtered out; if we have
* GTK+ windows in the same process, GTK+ needs the ConfigureNotify event, for example.
@@ -1138,12 +1124,11 @@ frame_callback (CoglOnscreen *onscreen,
}
}
static gboolean
meta_pre_paint_func (gpointer data)
static void
pre_paint_windows (MetaCompositor *compositor)
{
GList *l;
MetaWindowActor *top_window;
MetaCompositor *compositor = data;
if (compositor->onscreen == NULL)
{
@@ -1155,7 +1140,7 @@ meta_pre_paint_func (gpointer data)
}
if (compositor->windows == NULL)
return TRUE;
return;
top_window = g_list_last (compositor->windows)->data;
@@ -1167,53 +1152,13 @@ meta_pre_paint_func (gpointer data)
for (l = compositor->windows; l; l = l->next)
meta_window_actor_pre_paint (l->data);
if (compositor->frame_has_updated_xsurfaces)
{
/* We need to make sure that any X drawing that happens before
* the XDamageSubtract() for each window above is visible to
* subsequent GL rendering; the standardized way to do this is
* GL_EXT_X11_sync_object. Since this isn't implemented yet in
* mesa, we also have a path that relies on the implementation
* of the open source drivers.
*
* Anything else, we just hope for the best.
*
* Xorg and open source driver specifics:
*
* The X server makes sure to flush drawing to the kernel before
* sending out damage events, but since we use
* DamageReportBoundingBox there may be drawing between the last
* damage event and the XDamageSubtract() that needs to be
* flushed as well.
*
* Xorg always makes sure that drawing is flushed to the kernel
* before writing events or responses to the client, so any
* round trip request at this point is sufficient to flush the
* GLX buffers.
*/
if (compositor->have_x11_sync_object)
compositor->have_x11_sync_object = meta_sync_ring_insert_wait ();
else
XSync (compositor->display->xdisplay, False);
}
return TRUE;
}
static gboolean
meta_post_paint_func (gpointer data)
meta_repaint_func (gpointer data)
{
MetaCompositor *compositor = data;
if (compositor->frame_has_updated_xsurfaces)
{
if (compositor->have_x11_sync_object)
compositor->have_x11_sync_object = meta_sync_ring_after_frame ();
compositor->frame_has_updated_xsurfaces = FALSE;
}
pre_paint_windows (compositor);
return TRUE;
}
@@ -1252,16 +1197,10 @@ meta_compositor_new (MetaDisplay *display)
G_CALLBACK (on_shadow_factory_changed),
compositor);
compositor->pre_paint_func_id =
clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_PRE_PAINT,
meta_pre_paint_func,
compositor,
NULL);
compositor->post_paint_func_id =
clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT,
meta_post_paint_func,
compositor,
NULL);
compositor->repaint_func_id = clutter_threads_add_repaint_func (meta_repaint_func,
compositor,
NULL);
return compositor;
}
@@ -1426,3 +1365,12 @@ meta_compositor_show_window_menu (MetaCompositor *compositor,
{
meta_plugin_manager_show_window_menu (compositor->plugin_mgr, window, menu, x, y);
}
void
meta_compositor_show_window_menu_for_rect (MetaCompositor *compositor,
MetaWindow *window,
MetaWindowMenuType menu,
MetaRectangle *rect)
{
meta_plugin_manager_show_window_menu_for_rect (compositor->plugin_mgr, window, menu, rect);
}

View File

@@ -20,6 +20,7 @@
*/
#include <meta/meta-plugin.h>
#include <meta/meta-version.h>
#include "meta-module.h"
#include <gmodule.h>
@@ -68,7 +69,7 @@ meta_module_load (GTypeModule *gmodule)
(gpointer *)(void *)&register_type) &&
info && register_type)
{
if (info->version_api != MUTTER_PLUGIN_API_VERSION)
if (info->version_api != META_PLUGIN_API_VERSION)
g_warning ("Plugin API mismatch for [%s]", priv->path);
else
{

View File

@@ -374,3 +374,20 @@ meta_plugin_manager_show_window_menu (MetaPluginManager *plugin_mgr,
if (klass->show_window_menu)
klass->show_window_menu (plugin, window, menu, x, y);
}
void
meta_plugin_manager_show_window_menu_for_rect (MetaPluginManager *plugin_mgr,
MetaWindow *window,
MetaWindowMenuType menu,
MetaRectangle *rect)
{
MetaPlugin *plugin = plugin_mgr->plugin;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
MetaDisplay *display = plugin_mgr->compositor->display;
if (display->display_opening)
return;
if (klass->show_window_menu_for_rect)
klass->show_window_menu_for_rect (plugin, window, menu, rect);
}

View File

@@ -87,5 +87,10 @@ void meta_plugin_manager_show_window_menu (MetaPluginManager *mgr,
int x,
int y);
void meta_plugin_manager_show_window_menu_for_rect (MetaPluginManager *mgr,
MetaWindow *window,
MetaWindowMenuType menu,
MetaRectangle *rect);
#endif

View File

@@ -121,17 +121,17 @@ static guint signals[LAST_SIGNAL] = { 0 };
/* The first element in this array also defines the default parameters
* for newly created classes */
MetaShadowClassInfo default_shadow_classes[] = {
{ "normal", { 6, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
{ "dialog", { 6, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
{ "modal_dialog", { 6, -1, 0, 1, 128 }, { 3, -1, 0, 3, 32 } },
{ "normal", { 3, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
{ "dialog", { 3, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
{ "modal_dialog", { 3, -1, 0, 1, 128 }, { 3, -1, 0, 3, 32 } },
{ "utility", { 3, -1, 0, 1, 128 }, { 3, -1, 0, 1, 32 } },
{ "border", { 6, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
{ "menu", { 6, -1, 0, 3, 128 }, { 3, -1, 0, 0, 32 } },
{ "border", { 3, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
{ "menu", { 3, -1, 0, 3, 128 }, { 3, -1, 0, 0, 32 } },
{ "popup-menu", { 1, -1, 0, 1, 128 }, { 1, -1, 0, 1, 128 } },
{ "popup-menu", { 1, 0, 0, 1, 128 }, { 1, -1, 0, 1, 128 } },
{ "dropdown-menu", { 1, 10, 0, 1, 128 }, { 1, 10, 0, 1, 128 } },
{ "attached", { 1, -1, 0, 1, 128 }, { 1, -1, 0, 1, 128 } }
{ "attached", { 1, 0, 0, 1, 128 }, { 1, -1, 0, 1, 128 } }
};
G_DEFINE_TYPE (MetaShadowFactory, meta_shadow_factory, G_TYPE_OBJECT);
@@ -496,7 +496,12 @@ get_box_filter_size (int radius)
static int
get_shadow_spread (int radius)
{
int d = get_box_filter_size (radius);
int d;
if (radius == 0)
return 0;
d = get_box_filter_size (radius);
if (d % 2 == 1)
return 3 * (d / 2);

View File

@@ -34,6 +34,7 @@
#include "window-private.h"
#include "meta-shaped-texture-private.h"
#include "meta-cullable.h"
#include "x11/window-x11.h"
struct _MetaSurfaceActorX11Private
{
@@ -143,7 +144,7 @@ update_pixmap (MetaSurfaceActorX11 *self)
if (priv->pixmap == None)
{
Pixmap new_pixmap;
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
Window xwindow = meta_window_x11_get_toplevel_xwindow (priv->window);
meta_error_trap_push (display);
new_pixmap = XCompositeNameWindowPixmap (xdisplay, xwindow);
@@ -238,6 +239,26 @@ meta_surface_actor_x11_pre_paint (MetaSurfaceActor *actor)
XDamageSubtract (xdisplay, priv->damage, None, None);
meta_error_trap_pop (display);
/* We need to make sure that any X drawing that happens before the
* XDamageSubtract() above is visible to subsequent GL rendering;
* the only standardized way to do this is EXT_x11_sync_object,
* which isn't yet widely available. For now, we count on details
* of Xorg and the open source drivers, and hope for the best
* otherwise.
*
* Xorg and open source driver specifics:
*
* The X server makes sure to flush drawing to the kernel before
* sending out damage events, but since we use DamageReportBoundingBox
* there may be drawing between the last damage event and the
* XDamageSubtract() that needs to be flushed as well.
*
* Xorg always makes sure that drawing is flushed to the kernel
* before writing events or responses to the client, so any round trip
* request at this point is sufficient to flush the GLX buffers.
*/
XSync (xdisplay, False);
priv->received_damage = FALSE;
}
@@ -292,7 +313,7 @@ sync_unredirected (MetaSurfaceActorX11 *self)
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
MetaDisplay *display = priv->display;
Display *xdisplay = meta_display_get_xdisplay (display);
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
Window xwindow = meta_window_x11_get_toplevel_xwindow (priv->window);
meta_error_trap_push (display);
@@ -384,7 +405,7 @@ create_damage (MetaSurfaceActorX11 *self)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
Display *xdisplay = meta_display_get_xdisplay (priv->display);
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
Window xwindow = meta_window_x11_get_toplevel_xwindow (priv->window);
priv->damage = XDamageCreate (xdisplay, xwindow, XDamageReportBoundingBox);
}

View File

@@ -1,574 +0,0 @@
/*
* This is based on an original C++ implementation for compiz that
* carries the following copyright notice:
*
*
* Copyright © 2011 NVIDIA Corporation
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
* fee, provided that the above copyright notice appear in all copies
* and that both that copyright notice and this permission notice
* appear in supporting documentation, and that the name of NVIDIA
* Corporation not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. NVIDIA Corporation makes no representations about the
* suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* NVIDIA CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*
* Authors: James Jones <jajones@nvidia.com>
*/
#include <string.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <cogl/cogl.h>
#include <meta/display.h>
#include <meta/util.h>
#include "meta-sync-ring.h"
/* Theory of operation:
*
* We use a ring of NUM_SYNCS fence objects. On each frame we advance
* to the next fence in the ring. For each fence we do:
*
* 1. fence is XSyncTriggerFence()'d and glWaitSync()'d
* 2. NUM_SYNCS / 2 frames later, fence should be triggered
* 3. fence is XSyncResetFence()'d
* 4. NUM_SYNCS / 2 frames later, fence should be reset
* 5. go back to 1 and re-use fence
*
* glClientWaitSync() and XAlarms are used in steps 2 and 4,
* respectively, to double-check the expectections.
*/
#define NUM_SYNCS 10
#define MAX_SYNC_WAIT_TIME (1 * 1000 * 1000 * 1000) /* one sec */
#define MAX_REBOOT_ATTEMPTS 2
typedef enum
{
META_SYNC_STATE_READY,
META_SYNC_STATE_WAITING,
META_SYNC_STATE_DONE,
META_SYNC_STATE_RESET_PENDING,
} MetaSyncState;
typedef struct
{
Display *xdisplay;
XSyncFence xfence;
GLsync glsync;
XSyncCounter xcounter;
XSyncAlarm xalarm;
XSyncValue next_counter_value;
MetaSyncState state;
} MetaSync;
typedef struct
{
MetaDisplay *display;
GHashTable *alarm_to_sync;
MetaSync *syncs_array[NUM_SYNCS];
guint current_sync_idx;
MetaSync *current_sync;
guint warmup_syncs;
guint reboots;
} MetaSyncRing;
static MetaSyncRing meta_sync_ring = { 0 };
static XSyncValue SYNC_VALUE_ZERO;
static XSyncValue SYNC_VALUE_ONE;
static void (*meta_gl_get_integerv) (GLenum pname,
GLint *params);
static const char* (*meta_gl_get_stringi) (GLenum name,
GLuint index);
static void (*meta_gl_delete_sync) (GLsync sync);
static GLenum (*meta_gl_client_wait_sync) (GLsync sync,
GLbitfield flags,
GLuint64 timeout);
static void (*meta_gl_wait_sync) (GLsync sync,
GLbitfield flags,
GLuint64 timeout);
static GLsync (*meta_gl_import_sync) (GLenum external_sync_type,
GLintptr external_sync,
GLbitfield flags);
static GLenum (*meta_gl_get_error) (void);
static GLboolean (*meta_gl_is_sync) (GLsync sync);
static MetaSyncRing *
meta_sync_ring_get (void)
{
if (meta_sync_ring.reboots > MAX_REBOOT_ATTEMPTS)
return NULL;
return &meta_sync_ring;
}
static gboolean
load_gl_symbol (const char *name,
void **func)
{
*func = cogl_get_proc_address (name);
if (!*func)
{
meta_verbose ("MetaSyncRing: failed to resolve required GL symbol \"%s\"\n", name);
return FALSE;
}
return TRUE;
}
static gboolean
check_gl_extensions (void)
{
int num_extensions, i;
gboolean sync = FALSE;
gboolean x11_sync_object = FALSE;
meta_gl_get_integerv (GL_NUM_EXTENSIONS, &num_extensions);
for (i = 0; i < num_extensions; ++i)
{
const char *ext = meta_gl_get_stringi (GL_EXTENSIONS, i);
if (g_strcmp0 ("GL_ARB_sync", ext) == 0)
sync = TRUE;
else if (g_strcmp0 ("GL_EXT_x11_sync_object", ext) == 0)
x11_sync_object = TRUE;
}
return sync && x11_sync_object;
}
static gboolean
load_required_symbols (void)
{
static gboolean success = FALSE;
if (success)
return TRUE;
/* We don't link against libGL directly because cogl may want to
* use something else. This assumes that cogl has been initialized
* and dynamically loaded libGL at this point.
*/
if (!load_gl_symbol ("glGetIntegerv", (void **) &meta_gl_get_integerv))
goto out;
if (!load_gl_symbol ("glGetStringi", (void **) &meta_gl_get_stringi))
goto out;
if (!check_gl_extensions ())
{
meta_verbose ("MetaSyncRing: couldn't find required GL extensions\n");
goto out;
}
if (!load_gl_symbol ("glDeleteSync", (void **) &meta_gl_delete_sync))
goto out;
if (!load_gl_symbol ("glClientWaitSync", (void **) &meta_gl_client_wait_sync))
goto out;
if (!load_gl_symbol ("glWaitSync", (void **) &meta_gl_wait_sync))
goto out;
if (!load_gl_symbol ("glImportSyncEXT", (void **) &meta_gl_import_sync))
goto out;
if (!load_gl_symbol ("glGetError", (void **) &meta_gl_get_error))
goto out;
if (!load_gl_symbol ("glIsSync", (void **) &meta_gl_is_sync))
goto out;
success = TRUE;
out:
return success;
}
static void
print_gl_error (void)
{
GLenum e;
switch (e = meta_gl_get_error ())
{
case GL_NO_ERROR:
meta_warning ("GL_NO_ERROR\n");
break;
case GL_INVALID_ENUM:
meta_warning ("GL_INVALID_ENUM\n");
break;
case GL_INVALID_VALUE:
meta_warning ("GL_INVALID_VALUE\n");
break;
case GL_INVALID_OPERATION:
meta_warning ("GL_INVALID_OPERATION\n");
break;
case GL_INVALID_FRAMEBUFFER_OPERATION:
meta_warning ("GL_INVALID_FRAMEBUFFER_OPERATION\n");
break;
case GL_OUT_OF_MEMORY:
meta_warning ("GL_OUT_OF_MEMORY\n");
break;
case GL_STACK_OVERFLOW:
meta_warning ("GL_STACK_OVERFLOW\n");
break;
case GL_STACK_UNDERFLOW:
meta_warning ("GL_STACK_UNDERFLOW\n");
break;
default:
meta_warning ("GL error 0x%x\n", e);
break;
}
}
static void
meta_sync_insert (MetaSync *self)
{
g_return_if_fail (self->state == META_SYNC_STATE_READY);
XSyncTriggerFence (self->xdisplay, self->xfence);
XFlush (self->xdisplay);
meta_gl_wait_sync (self->glsync, 0, GL_TIMEOUT_IGNORED);
self->state = META_SYNC_STATE_WAITING;
}
static GLenum
meta_sync_check_update_finished (MetaSync *self,
GLuint64 timeout)
{
GLenum status = GL_WAIT_FAILED;
switch (self->state)
{
case META_SYNC_STATE_DONE:
status = GL_ALREADY_SIGNALED;
break;
case META_SYNC_STATE_WAITING:
status = meta_gl_client_wait_sync (self->glsync, 0, timeout);
if (status == GL_ALREADY_SIGNALED || status == GL_CONDITION_SATISFIED)
self->state = META_SYNC_STATE_DONE;
break;
default:
break;
}
g_warn_if_fail (status != GL_WAIT_FAILED);
return status;
}
static void
meta_sync_reset (MetaSync *self)
{
XSyncAlarmAttributes attrs;
int overflow;
g_return_if_fail (self->state == META_SYNC_STATE_DONE);
XSyncResetFence (self->xdisplay, self->xfence);
attrs.trigger.wait_value = self->next_counter_value;
XSyncChangeAlarm (self->xdisplay, self->xalarm, XSyncCAValue, &attrs);
XSyncSetCounter (self->xdisplay, self->xcounter, self->next_counter_value);
XSyncValueAdd (&self->next_counter_value,
self->next_counter_value,
SYNC_VALUE_ONE,
&overflow);
self->state = META_SYNC_STATE_RESET_PENDING;
}
static void
meta_sync_handle_event (MetaSync *self,
XSyncAlarmNotifyEvent *event)
{
g_return_if_fail (event->alarm == self->xalarm);
g_return_if_fail (self->state == META_SYNC_STATE_RESET_PENDING);
self->state = META_SYNC_STATE_READY;
}
static MetaSync *
meta_sync_new (Display *xdisplay)
{
MetaSync *self;
XSyncAlarmAttributes attrs;
self = g_malloc0 (sizeof (MetaSync));
self->xdisplay = xdisplay;
self->xfence = XSyncCreateFence (xdisplay, DefaultRootWindow (xdisplay), FALSE);
meta_warning ("created X fence 0x%x\n", self->xfence);
self->glsync = meta_gl_import_sync (GL_SYNC_X11_FENCE_EXT, self->xfence, 0);
print_gl_error ();
self->xcounter = XSyncCreateCounter (xdisplay, SYNC_VALUE_ZERO);
attrs.trigger.counter = self->xcounter;
attrs.trigger.value_type = XSyncAbsolute;
attrs.trigger.wait_value = SYNC_VALUE_ONE;
attrs.trigger.test_type = XSyncPositiveTransition;
attrs.events = TRUE;
self->xalarm = XSyncCreateAlarm (xdisplay,
XSyncCACounter |
XSyncCAValueType |
XSyncCAValue |
XSyncCATestType |
XSyncCAEvents,
&attrs);
XSyncIntToValue (&self->next_counter_value, 1);
self->state = META_SYNC_STATE_READY;
return self;
}
static Bool
alarm_event_predicate (Display *dpy,
XEvent *event,
XPointer data)
{
int xsync_event_base;
MetaSyncRing *ring = meta_sync_ring_get ();
if (!ring)
return False;
xsync_event_base = meta_display_get_sync_event_base (ring->display);
if (event->type == xsync_event_base + XSyncAlarmNotify)
{
if (((MetaSync *) data)->xalarm == ((XSyncAlarmNotifyEvent *) event)->alarm)
return True;
}
return False;
}
static void
meta_sync_free (MetaSync *self)
{
/* When our assumptions don't hold, something has gone wrong but we
* don't know what, so we reboot the ring. While doing that, we
* trigger fences before deleting them to try to get ourselves out
* of a potentially stuck GPU state.
*/
switch (self->state)
{
case META_SYNC_STATE_WAITING:
case META_SYNC_STATE_DONE:
/* nothing to do */
break;
case META_SYNC_STATE_RESET_PENDING:
{
XEvent event;
XIfEvent (self->xdisplay, &event, alarm_event_predicate, (XPointer) self);
meta_sync_handle_event (self, (XSyncAlarmNotifyEvent *) &event);
}
/* fall through */
case META_SYNC_STATE_READY:
XSyncTriggerFence (self->xdisplay, self->xfence);
XFlush (self->xdisplay);
break;
default:
break;
}
meta_gl_delete_sync (self->glsync);
XSyncDestroyFence (self->xdisplay, self->xfence);
XSyncDestroyCounter (self->xdisplay, self->xcounter);
XSyncDestroyAlarm (self->xdisplay, self->xalarm);
g_free (self);
}
gboolean
meta_sync_ring_init (MetaDisplay *display)
{
guint i;
MetaSyncRing *ring = meta_sync_ring_get ();
if (!ring)
return FALSE;
g_return_val_if_fail (display != NULL, FALSE);
g_return_val_if_fail (ring->display == NULL, FALSE);
if (!load_required_symbols ())
return FALSE;
if (!meta_display_has_sync (display))
return FALSE;
print_gl_error ();
XSyncIntToValue (&SYNC_VALUE_ZERO, 0);
XSyncIntToValue (&SYNC_VALUE_ONE, 1);
ring->display = display;
ring->alarm_to_sync = g_hash_table_new (NULL, NULL);
for (i = 0; i < NUM_SYNCS; ++i)
{
MetaSync *sync = meta_sync_new (meta_display_get_xdisplay (display));
ring->syncs_array[i] = sync;
g_hash_table_replace (ring->alarm_to_sync, (gpointer) sync->xalarm, sync);
}
ring->current_sync_idx = 0;
ring->current_sync = ring->syncs_array[0];
ring->warmup_syncs = 0;
return TRUE;
}
void
meta_sync_ring_destroy (void)
{
guint i;
MetaSyncRing *ring = meta_sync_ring_get ();
if (!ring)
return;
g_return_if_fail (ring->display != NULL);
ring->current_sync_idx = 0;
ring->current_sync = NULL;
ring->warmup_syncs = 0;
for (i = 0; i < NUM_SYNCS; ++i)
meta_sync_free (ring->syncs_array[i]);
g_hash_table_destroy (ring->alarm_to_sync);
ring->display = NULL;
}
static gboolean
meta_sync_ring_reboot (MetaDisplay *display)
{
MetaSyncRing *ring = meta_sync_ring_get ();
if (!ring)
return FALSE;
meta_sync_ring_destroy ();
ring->reboots += 1;
if (!meta_sync_ring_get ())
{
meta_warning ("MetaSyncRing: Too many reboots -- disabling\n");
return FALSE;
}
return meta_sync_ring_init (display);
}
gboolean
meta_sync_ring_after_frame (void)
{
MetaSyncRing *ring = meta_sync_ring_get ();
if (!ring)
return FALSE;
g_return_if_fail (ring->display != NULL);
if (ring->warmup_syncs >= NUM_SYNCS / 2)
{
guint reset_sync_idx = (ring->current_sync_idx + NUM_SYNCS - (NUM_SYNCS / 2)) % NUM_SYNCS;
MetaSync *sync_to_reset = ring->syncs_array[reset_sync_idx];
GLenum status = meta_sync_check_update_finished (sync_to_reset, 0);
if (status == GL_TIMEOUT_EXPIRED)
{
meta_warning ("MetaSyncRing: We should never wait for a sync -- add more syncs?\n");
status = meta_sync_check_update_finished (sync_to_reset, MAX_SYNC_WAIT_TIME);
}
if (status != GL_ALREADY_SIGNALED && status != GL_CONDITION_SATISFIED)
{
meta_warning ("MetaSyncRing: Timed out waiting for sync object.\n");
return meta_sync_ring_reboot (ring->display);
}
meta_sync_reset (sync_to_reset);
}
else
{
ring->warmup_syncs += 1;
}
ring->current_sync_idx += 1;
ring->current_sync_idx %= NUM_SYNCS;
ring->current_sync = ring->syncs_array[ring->current_sync_idx];
return TRUE;
}
gboolean
meta_sync_ring_insert_wait (void)
{
MetaSyncRing *ring = meta_sync_ring_get ();
if (!ring)
return FALSE;
g_return_if_fail (ring->display != NULL);
if (ring->current_sync->state != META_SYNC_STATE_READY)
{
meta_warning ("MetaSyncRing: Sync object is not ready -- were events handled properly?\n");
if (!meta_sync_ring_reboot (ring->display))
return FALSE;
}
meta_sync_insert (ring->current_sync);
return TRUE;
}
void
meta_sync_ring_handle_event (XSyncAlarmNotifyEvent *event)
{
MetaSync *sync;
MetaSyncRing *ring = meta_sync_ring_get ();
if (!ring)
return;
g_return_if_fail (ring->display != NULL);
sync = g_hash_table_lookup (ring->alarm_to_sync, (gpointer) event->alarm);
if (sync)
meta_sync_handle_event (sync, event);
}

View File

@@ -1,17 +0,0 @@
#ifndef _META_SYNC_RING_H_
#define _META_SYNC_RING_H_
#include <glib.h>
#include <X11/Xlib.h>
#include <X11/extensions/sync.h>
#include <meta/display.h>
gboolean meta_sync_ring_init (MetaDisplay *dpy);
void meta_sync_ring_destroy (void);
gboolean meta_sync_ring_after_frame (void);
gboolean meta_sync_ring_insert_wait (void);
void meta_sync_ring_handle_event (XSyncAlarmNotifyEvent *event);
#endif /* _META_SYNC_RING_H_ */

View File

@@ -51,8 +51,7 @@ void meta_window_actor_update_shape (MetaWindowActor *self);
void meta_window_actor_update_opacity (MetaWindowActor *self);
void meta_window_actor_mapped (MetaWindowActor *self);
void meta_window_actor_unmapped (MetaWindowActor *self);
void meta_window_actor_set_updates_frozen (MetaWindowActor *self,
gboolean updates_frozen);
void meta_window_actor_sync_updates_frozen (MetaWindowActor *self);
void meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
gboolean no_delay_frame);

View File

@@ -746,9 +746,11 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
return FALSE;
/*
* Add shadows to override redirect windows (e.g., Gtk menus).
* Add shadows to override redirect windows on X11 unless the toolkit
* indicates that it is handling shadows itself (e.g., Gtk menus).
*/
if (priv->window->override_redirect)
if (priv->window->override_redirect &&
!priv->window->has_custom_frame_extents)
return TRUE;
return FALSE;
@@ -1150,7 +1152,7 @@ meta_window_actor_sync_actor_geometry (MetaWindowActor *self,
MetaWindowActorPrivate *priv = self->priv;
MetaRectangle window_rect;
meta_window_get_input_rect (priv->window, &window_rect);
meta_window_get_buffer_rect (priv->window, &window_rect);
/* When running as a Wayland compositor we catch size changes when new
* buffers are attached */
@@ -1324,7 +1326,7 @@ meta_window_actor_new (MetaWindow *window)
priv = self->priv;
meta_window_actor_set_updates_frozen (self, meta_window_updates_are_frozen (priv->window));
meta_window_actor_sync_updates_frozen (self);
/* If a window doesn't start off with updates frozen, we should
* we should send a _NET_WM_FRAME_DRAWN immediately after the first drawn.
@@ -2020,7 +2022,7 @@ meta_window_actor_update_opacity (MetaWindowActor *self)
clutter_actor_set_opacity (CLUTTER_ACTOR (priv->surface), window->opacity);
}
void
static void
meta_window_actor_set_updates_frozen (MetaWindowActor *self,
gboolean updates_frozen)
{
@@ -2037,3 +2039,12 @@ meta_window_actor_set_updates_frozen (MetaWindowActor *self,
meta_window_actor_thaw (self);
}
}
void
meta_window_actor_sync_updates_frozen (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
MetaWindow *window = priv->window;
meta_window_actor_set_updates_frozen (self, meta_window_updates_are_frozen (window));
}

View File

@@ -1,12 +1,22 @@
pkglibdir=@MUTTER_PLUGIN_DIR@
pkglibdir = $(MUTTER_PLUGIN_DIR)
INCLUDES=@MUTTER_CFLAGS@ -I $(top_srcdir)/src -DMUTTER_LIBEXECDIR=\"$(libexecdir)\" -DHOST_ALIAS=\"@HOST_ALIAS@\" -DMUTTER_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\" -DMUTTER_PKGDATADIR=\"$(pkgdatadir)\" -DMUTTER_DATADIR=\"$(datadir)\" -DG_LOG_DOMAIN=\"mutter\" -DSN_API_NOT_YET_FROZEN=1 -DMUTTER_MAJOR_VERSION=$(MUTTER_MAJOR_VERSION) -DMUTTER_MINOR_VERSION=$(MUTTER_MINOR_VERSION) -DMUTTER_MICRO_VERSION=$(MUTTER_MICRO_VERSION) -DMUTTER_PLUGIN_API_VERSION=$(MUTTER_PLUGIN_API_VERSION) -DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\"
AM_CPPFLAGS = \
$(MUTTER_CFLAGS) \
-I$(top_builddir)/src \
-I$(top_srcdir)/src \
-DMUTTER_LIBEXECDIR=\"$(libexecdir)\" \
-DMUTTER_LOCALEDIR=\"$(localedir)\" \
-DMUTTER_PKGDATADIR=\"$(pkgdatadir)\" \
-DMUTTER_DATADIR=\"$(datadir)\" \
-DG_LOG_DOMAIN=\"mutter\" \
-DSN_API_NOT_YET_FROZEN=1 \
-DMUTTER_PLUGIN_DIR=\"$(MUTTER_PLUGIN_DIR)\"
default_la_CFLAGS = -fPIC
default_la_SOURCES = default.c
default_la_LDFLAGS = -module -avoid-version -no-undefined
default_la_LIBADD = @CLUTTER_LIBS@
default_la_LIBADD = $(CLUTTER_LIBS)
pkglib_LTLIBRARIES = default.la

View File

@@ -546,6 +546,26 @@ compare_rect_areas (gconstpointer a, gconstpointer b)
return b_area - a_area; /* positive ret value denotes b > a, ... */
}
/* ... and another helper for get_minimal_spanning_set_for_region()... */
static gboolean
check_strut_align (MetaStrut *strut, const MetaRectangle *rect)
{
/* Check whether @strut actually aligns to the side of @rect it claims */
switch (strut->side)
{
case META_SIDE_TOP:
return BOX_TOP (strut->rect) <= BOX_TOP (*rect);
case META_SIDE_BOTTOM:
return BOX_BOTTOM (strut->rect) >= BOX_BOTTOM (*rect);
case META_SIDE_LEFT:
return BOX_LEFT (strut->rect) <= BOX_LEFT (*rect);
case META_SIDE_RIGHT:
return BOX_RIGHT (strut->rect) >= BOX_RIGHT (*rect);
default:
return FALSE;
}
}
/**
* meta_rectangle_get_minimal_spanning_set_for_region:
* @basic_rect: Input rectangle
@@ -630,7 +650,8 @@ meta_rectangle_get_minimal_spanning_set_for_region (
for (strut_iter = all_struts; strut_iter; strut_iter = strut_iter->next)
{
GList *rect_iter;
MetaRectangle *strut_rect = &((MetaStrut*)strut_iter->data)->rect;
MetaStrut *strut = (MetaStrut*)strut_iter->data;
MetaRectangle *strut_rect = &strut->rect;
tmp_list = ret;
ret = NULL;
@@ -638,7 +659,9 @@ meta_rectangle_get_minimal_spanning_set_for_region (
while (rect_iter)
{
MetaRectangle *rect = (MetaRectangle*) rect_iter->data;
if (!meta_rectangle_overlap (rect, strut_rect))
if (!meta_rectangle_overlap (strut_rect, rect) ||
!check_strut_align (strut, basic_rect))
ret = g_list_prepend (ret, rect);
else
{

View File

@@ -404,31 +404,6 @@ setup_constraint_info (ConstraintInfo *info,
meta_workspace_get_onmonitor_region (cur_workspace,
monitor_info->number);
/* Workaround braindead legacy apps that don't know how to
* fullscreen themselves properly - don't get fooled by
* windows which hide their titlebar when maximized or which are
* client decorated; that's not the same as fullscreen, even
* if there are no struts making the workarea smaller than
* the monitor.
*/
if (meta_prefs_get_force_fullscreen() &&
window->client_type != META_WINDOW_CLIENT_TYPE_WAYLAND &&
!window->hide_titlebar_when_maximized &&
(window->decorated || !meta_window_is_client_decorated (window)) &&
meta_rectangle_equal (new, &monitor_info->rect) &&
window->has_fullscreen_func &&
!window->fullscreen)
{
/*
meta_topic (META_DEBUG_GEOMETRY,
*/
meta_warning (
"Treating resize request of legacy application %s as a "
"fullscreen request\n",
window->desc);
meta_window_make_fullscreen_internal (window);
}
/* Log all this information for debugging */
meta_topic (META_DEBUG_GEOMETRY,
"Setting up constraint info:\n"
@@ -613,7 +588,7 @@ update_onscreen_requirements (MetaWindow *window,
window->require_fully_onscreen =
meta_rectangle_contained_in_region (info->usable_screen_region,
&info->current);
if (old ^ window->require_fully_onscreen)
if (old != window->require_fully_onscreen)
meta_topic (META_DEBUG_GEOMETRY,
"require_fully_onscreen for %s toggled to %s\n",
window->desc,
@@ -626,7 +601,7 @@ update_onscreen_requirements (MetaWindow *window,
window->require_on_single_monitor =
meta_rectangle_contained_in_region (info->usable_monitor_region,
&info->current);
if (old ^ window->require_on_single_monitor)
if (old != window->require_on_single_monitor)
meta_topic (META_DEBUG_GEOMETRY,
"require_on_single_monitor for %s toggled to %s\n",
window->desc,
@@ -645,7 +620,7 @@ update_onscreen_requirements (MetaWindow *window,
window->require_titlebar_visible =
meta_rectangle_overlaps_with_region (info->usable_screen_region,
&titlebar_rect);
if (old ^ window->require_titlebar_visible)
if (old != window->require_titlebar_visible)
meta_topic (META_DEBUG_GEOMETRY,
"require_titlebar_visible for %s toggled to %s\n",
window->desc,

View File

@@ -392,6 +392,22 @@ meta_core_show_window_menu (Display *xdisplay,
meta_window_show_menu (window, menu, root_x, root_y);
}
void
meta_core_show_window_menu_for_rect (Display *xdisplay,
Window frame_xwindow,
MetaWindowMenuType menu,
MetaRectangle *rect,
guint32 timestamp)
{
MetaWindow *window = get_window (xdisplay, frame_xwindow);
if (meta_prefs_get_raise_on_click ())
meta_window_raise (window);
meta_window_focus (window, timestamp);
meta_window_show_menu_for_rect (window, menu, rect);
}
const char*
meta_core_get_workspace_name_with_index (Display *xdisplay,
Window xroot,

View File

@@ -26,6 +26,7 @@
/* Don't include core headers here */
#include <gdk/gdkx.h>
#include <meta/common.h>
#include <meta/boxes.h>
typedef enum
{
@@ -138,6 +139,12 @@ void meta_core_show_window_menu (Display *xdisplay,
int root_y,
guint32 timestamp);
void meta_core_show_window_menu_for_rect (Display *xdisplay,
Window frame_xwindow,
MetaWindowMenuType menu,
MetaRectangle *rect,
guint32 timestamp);
gboolean meta_core_begin_grab_op (Display *xdisplay,
Window frame_xwindow,
MetaGrabOp op,

View File

@@ -181,7 +181,6 @@ struct _MetaDisplay
/* current window operation */
MetaGrabOp grab_op;
MetaWindow *grab_window;
Window grab_xwindow;
int grab_button;
int grab_anchor_root_x;
int grab_anchor_root_y;

View File

@@ -805,6 +805,7 @@ meta_display_open (void)
enable_compositor (the_display);
meta_screen_init_workspaces (screen);
meta_screen_create_guard_window (screen);
/* We know that if mutter is running as a Wayland compositor,
@@ -1343,23 +1344,7 @@ window_raise_with_delay_callback (void *data)
*/
if (meta_stack_get_top (window->screen->stack) != window)
{
int x, y, root_x, root_y;
Window root, child;
MetaRectangle frame_rect;
unsigned int mask;
gboolean same_screen;
gboolean point_in_window;
meta_error_trap_push (window->display);
same_screen = XQueryPointer (window->display->xdisplay,
window->xwindow,
&root, &child,
&root_x, &root_y, &x, &y, &mask);
meta_error_trap_pop (window->display);
meta_window_get_frame_rect (window, &frame_rect);
point_in_window = POINT_IN_RECT (root_x, root_y, frame_rect);
if (same_screen && point_in_window)
if (meta_window_has_pointer (window))
meta_window_raise (window);
else
meta_topic (META_DEBUG_FOCUS,
@@ -1367,7 +1352,7 @@ window_raise_with_delay_callback (void *data)
window->desc);
}
return FALSE;
return G_SOURCE_REMOVE;
}
void
@@ -1696,15 +1681,15 @@ meta_display_update_cursor (MetaDisplay *display)
}
static MetaWindow *
get_toplevel_transient_for (MetaWindow *window)
get_first_freefloating_window (MetaWindow *window)
{
while (TRUE)
{
MetaWindow *parent = meta_window_get_transient_for (window);
if (parent == NULL)
return window;
window = parent;
}
while (meta_window_is_attached_dialog (window))
window = meta_window_get_transient_for (window);
/* Attached dialogs should always have a non-NULL transient-for */
g_assert (window != NULL);
return window;
}
gboolean
@@ -1752,11 +1737,11 @@ meta_display_begin_grab_op (MetaDisplay *display,
grab_window = window;
/* If window is a modal dialog attached to its parent,
* grab the parent instead for moving.
/* If we're trying to move a window, move the first
* non-attached dialog instead.
*/
if (meta_window_is_attached_dialog (window) && meta_grab_op_is_moving (op))
grab_window = get_toplevel_transient_for (window);
if (meta_grab_op_is_moving (op))
grab_window = get_first_freefloating_window (window);
g_assert (grab_window != NULL);
g_assert (op != META_GRAB_OP_NONE);
@@ -2525,21 +2510,19 @@ mru_cmp (gconstpointer a,
* meta_display_get_tab_list:
* @display: a #MetaDisplay
* @type: type of tab list
* @screen: a #MetaScreen
* @workspace: (nullable): origin workspace
*
* Determine the list of windows that should be displayed for Alt-TAB
* functionality. The windows are returned in most recently used order.
* If @workspace is not %NULL, the list only conains windows that are on
* @workspace or have the demands-attention hint set; otherwise it contains
* all windows on @screen.
* all windows.
*
* Returns: (transfer container) (element-type Meta.Window): List of windows
*/
GList*
meta_display_get_tab_list (MetaDisplay *display,
MetaTabList type,
MetaScreen *screen,
MetaWorkspace *workspace)
{
GList *tab_list = NULL;
@@ -2614,7 +2597,7 @@ meta_display_get_tab_next (MetaDisplay *display,
gboolean skip;
GList *tab_list;
MetaWindow *ret;
tab_list = meta_display_get_tab_list (display, type, NULL, workspace);
tab_list = meta_display_get_tab_list (display, type, workspace);
if (tab_list == NULL)
return NULL;
@@ -3120,12 +3103,6 @@ meta_display_has_shape (MetaDisplay *display)
return META_DISPLAY_HAS_SHAPE (display);
}
gboolean
meta_display_has_sync (MetaDisplay *display)
{
return META_DISPLAY_HAS_XSYNC (display);
}
/**
* meta_display_get_focus_window:
* @display: a #MetaDisplay
@@ -3154,12 +3131,6 @@ meta_display_get_shape_event_base (MetaDisplay *display)
return display->shape_event_base;
}
int
meta_display_get_sync_event_base (MetaDisplay *display)
{
return display->xsync_event_base;
}
/**
* meta_display_clear_mouse_mode:
* @display: a #MetaDisplay

File diff suppressed because it is too large Load Diff

View File

@@ -29,4 +29,3 @@ void meta_display_init_events (MetaDisplay *display);
void meta_display_free_events (MetaDisplay *display);
#endif

View File

@@ -57,6 +57,7 @@
#include "wayland/meta-wayland.h"
#include "backends/x11/meta-backend-x11.h"
#include "x11/window-x11.h"
#ifdef HAVE_NATIVE_BACKEND
#include "backends/native/meta-backend-native.h"
@@ -1223,7 +1224,7 @@ meta_window_grab_keys (MetaWindow *window)
}
meta_window_change_keygrabs (window,
meta_window_get_toplevel_xwindow (window),
meta_window_x11_get_toplevel_xwindow (window),
TRUE);
window->keys_grabbed = TRUE;
@@ -1437,7 +1438,7 @@ meta_window_grab_all_keys (MetaWindow *window,
window->desc);
meta_window_focus (window, timestamp);
grabwindow = meta_window_get_toplevel_xwindow (window);
grabwindow = meta_window_x11_get_toplevel_xwindow (window);
meta_topic (META_DEBUG_KEYBINDINGS,
"Grabbing all keys on window %s\n", window->desc);

View File

@@ -1234,6 +1234,7 @@ xsettings_overrides_changed (GSettings *settings,
GVariant *value;
GVariantDict overrides;
int shell_shows_app_menu = 1;
gboolean changed = FALSE;
if (!g_settings_get_boolean (settings, "active"))
goto out;
@@ -1247,8 +1248,13 @@ xsettings_overrides_changed (GSettings *settings,
"Gtk/ShellShowsAppMenu", "i", &shell_shows_app_menu);
g_variant_dict_clear (&overrides);
changed = (show_fallback_app_menu == !!shell_shows_app_menu);
out:
show_fallback_app_menu = !shell_shows_app_menu;
if (changed)
queue_changed (META_PREF_BUTTON_LAYOUT);
}
/**

View File

@@ -135,6 +135,7 @@ MetaScreen* meta_screen_new (MetaDisplay *displ
guint32 timestamp);
void meta_screen_free (MetaScreen *screen,
guint32 timestamp);
void meta_screen_init_workspaces (MetaScreen *screen);
void meta_screen_manage_all_windows (MetaScreen *screen);
void meta_screen_foreach_window (MetaScreen *screen,
MetaScreenWindowFunc func,

View File

@@ -506,7 +506,6 @@ meta_screen_new (MetaDisplay *display,
Atom wm_sn_atom;
char buf[128];
guint32 manager_timestamp;
gulong current_workspace;
MetaMonitorManager *manager;
replace_current_wm = meta_get_replace_current_wm ();
@@ -721,24 +720,10 @@ meta_screen_new (MetaDisplay *display,
meta_screen_update_workspace_layout (screen);
/* Get current workspace */
current_workspace = 0;
if (meta_prop_get_cardinal (screen->display,
screen->xroot,
screen->display->atom__NET_CURRENT_DESKTOP,
&current_workspace))
meta_verbose ("Read existing _NET_CURRENT_DESKTOP = %d\n",
(int) current_workspace);
else
meta_verbose ("No _NET_CURRENT_DESKTOP present\n");
/* Screens must have at least one workspace at all times,
* so create that required workspace.
*/
meta_workspace_activate (meta_workspace_new (screen), timestamp);
update_num_workspaces (screen, timestamp);
set_workspace_names (screen);
meta_workspace_new (screen);
screen->keys_grabbed = FALSE;
meta_screen_grab_keys (screen);
@@ -764,23 +749,46 @@ meta_screen_new (MetaDisplay *display,
screen->startup_sequence_timeout = 0;
#endif
/* Switch to the _NET_CURRENT_DESKTOP workspace */
{
MetaWorkspace *space;
space = meta_screen_get_workspace_by_index (screen,
current_workspace);
if (space != NULL)
meta_workspace_activate (space, timestamp);
}
meta_verbose ("Added screen %d ('%s') root 0x%lx\n",
screen->number, screen->screen_name, screen->xroot);
return screen;
}
void
meta_screen_init_workspaces (MetaScreen *screen)
{
MetaWorkspace *current_workspace;
gulong current_workspace_index = 0;
guint32 timestamp;
g_return_if_fail (META_IS_SCREEN (screen));
timestamp = screen->wm_sn_timestamp;
/* Get current workspace */
if (meta_prop_get_cardinal (screen->display,
screen->xroot,
screen->display->atom__NET_CURRENT_DESKTOP,
&current_workspace_index))
meta_verbose ("Read existing _NET_CURRENT_DESKTOP = %d\n",
(int) current_workspace_index);
else
meta_verbose ("No _NET_CURRENT_DESKTOP present\n");
meta_workspace_activate (screen->workspaces->data, timestamp);
update_num_workspaces (screen, timestamp);
set_workspace_names (screen);
/* Switch to the _NET_CURRENT_DESKTOP workspace */
current_workspace = meta_screen_get_workspace_by_index (screen,
current_workspace_index);
if (current_workspace != NULL)
meta_workspace_activate (current_workspace, timestamp);
}
void
meta_screen_free (MetaScreen *screen,
guint32 timestamp)

View File

@@ -25,6 +25,7 @@
#include <stdio.h>
#include <X11/Xutil.h> /* Just for the definition of the various gravities */
#include <time.h> /* To initialize random seed */
#include <math.h>
#define NUM_RANDOM_RUNS 10000
@@ -238,7 +239,7 @@ static GSList*
get_strut_list (int which)
{
GSList *ans;
MetaDirection wc = 0; /* wc == who cares? ;-) */
MetaSide wc = 0; /* wc == who cares? ;-) */
ans = NULL;
@@ -248,32 +249,32 @@ get_strut_list (int which)
case 0:
break;
case 1:
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 400, 1160, 1600, 40, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, META_SIDE_TOP));
ans = g_slist_prepend (ans, new_meta_strut ( 400, 1160, 1600, 40, META_SIDE_BOTTOM));
break;
case 2:
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 800, 1100, 400, 100, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 300, 1150, 150, 50, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, META_SIDE_TOP));
ans = g_slist_prepend (ans, new_meta_strut ( 800, 1100, 400, 100, META_SIDE_BOTTOM));
ans = g_slist_prepend (ans, new_meta_strut ( 300, 1150, 150, 50, META_SIDE_BOTTOM));
break;
case 3:
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 800, 1100, 400, 100, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 300, 1150, 80, 50, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, META_SIDE_TOP));
ans = g_slist_prepend (ans, new_meta_strut ( 800, 1100, 400, 100, META_SIDE_LEFT));
ans = g_slist_prepend (ans, new_meta_strut ( 300, 1150, 80, 50, META_SIDE_BOTTOM));
ans = g_slist_prepend (ans, new_meta_strut ( 700, 525, 200, 150, wc));
break;
case 4:
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 800, 1200, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 800, 0, 1600, 20, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 800, 1200, META_SIDE_LEFT));
ans = g_slist_prepend (ans, new_meta_strut ( 800, 0, 1600, 20, META_SIDE_TOP));
break;
case 5:
ans = g_slist_prepend (ans, new_meta_strut ( 800, 0, 1600, 20, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 800, 1200, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 800, 10, 800, 1200, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 800, 0, 1600, 20, META_SIDE_TOP));
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 800, 1200, META_SIDE_LEFT));
ans = g_slist_prepend (ans, new_meta_strut ( 800, 10, 800, 1200, META_SIDE_RIGHT));
break;
case 6:
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 40, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, wc));
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 40, META_SIDE_TOP));
ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, META_SIDE_TOP));
break;
}
@@ -623,15 +624,9 @@ test_regions_okay ()
/*************************************************************/
region = get_screen_region (3);
tmp = NULL;
tmp = g_list_prepend (tmp, new_meta_rect ( 380, 675, 420, 525)); /* 220500 */
tmp = g_list_prepend (tmp, new_meta_rect ( 0, 20, 300, 1180)); /* 354000 */
tmp = g_list_prepend (tmp, new_meta_rect ( 380, 20, 320, 1180)); /* 377600 */
tmp = g_list_prepend (tmp, new_meta_rect ( 0, 675, 800, 475)); /* 380000 */
tmp = g_list_prepend (tmp, new_meta_rect (1200, 20, 400, 1180)); /* 472000 */
tmp = g_list_prepend (tmp, new_meta_rect ( 0, 675, 1600, 425)); /* 680000 */
tmp = g_list_prepend (tmp, new_meta_rect ( 900, 20, 700, 1080)); /* 756000 */
tmp = g_list_prepend (tmp, new_meta_rect ( 0, 20, 700, 1130)); /* 791000 */
tmp = g_list_prepend (tmp, new_meta_rect ( 0, 20, 1600, 505)); /* 808000 */
tmp = g_list_prepend (tmp, new_meta_rect ( 380, 20, 1220, 1180)); /* 377600 */
tmp = g_list_prepend (tmp, new_meta_rect ( 0, 20, 1600, 1130)); /* 791000 */
#if 0
printf ("Got to here...\n");
char region_list[(RECT_LENGTH+2) * g_list_length (region)];
@@ -1332,6 +1327,7 @@ test_gravity_resize ()
printf ("%s passed.\n", G_STRFUNC);
}
#define EPSILON 0.000000001
static void
test_find_closest_point_to_line ()
{
@@ -1346,7 +1342,7 @@ test_find_closest_point_to_line ()
x2, y2,
px, py,
&rx, &ry);
g_assert (rx == answer_x && ry == answer_y);
g_assert (fabs (rx - answer_x) < EPSILON && fabs (ry - answer_y) < EPSILON);
/* Special test for x1 == x2, so that slop of line is infinite */
x1 = 3.0; y1 = 49.0;
@@ -1357,7 +1353,7 @@ test_find_closest_point_to_line ()
x2, y2,
px, py,
&rx, &ry);
g_assert (rx == answer_x && ry == answer_y);
g_assert (fabs (rx - answer_x) < EPSILON && fabs (ry - answer_y) < EPSILON);
/* Special test for y1 == y2, so perp line has slope of infinity */
x1 = 3.14; y1 = 7.0;
@@ -1368,7 +1364,7 @@ test_find_closest_point_to_line ()
x2, y2,
px, py,
&rx, &ry);
g_assert (rx == answer_x && ry == answer_y);
g_assert (fabs (rx - answer_x) < EPSILON && fabs (ry - answer_y) < EPSILON);
/* Test when we the point we want to be closest to is actually on the line */
x1 = 3.0; y1 = 49.0;
@@ -1379,7 +1375,7 @@ test_find_closest_point_to_line ()
x2, y2,
px, py,
&rx, &ry);
g_assert (rx == answer_x && ry == answer_y);
g_assert (fabs (rx - answer_x) < EPSILON && fabs (ry - answer_y) < EPSILON);
printf ("%s passed.\n", G_STRFUNC);
}

View File

@@ -166,6 +166,7 @@ struct _MetaWindow
* that to toggle between normal/tiled or maximized/tiled states. */
guint saved_maximize : 1;
int tile_monitor_number;
int preferred_output_id;
/* Whether we're shaded */
guint shaded : 1;
@@ -421,6 +422,15 @@ struct _MetaWindow
*/
MetaRectangle unconstrained_rect;
/* The rectangle of the "server-side" geometry of the buffer,
* in root coordinates.
*
* For X11 windows, this matches XGetGeometry of the toplevel.
*
* For Wayland windows, this matches the buffer size and where
* the surface actor is positioned. */
MetaRectangle buffer_rect;
/* Cached net_wm_icon_geometry */
MetaRectangle icon_geometry;
@@ -575,6 +585,10 @@ void meta_window_show_menu (MetaWindow *window,
int x,
int y);
void meta_window_show_menu_for_rect (MetaWindow *window,
MetaWindowMenuType menu,
MetaRectangle *rect);
gboolean meta_window_handle_mouse_grab_op_event (MetaWindow *window,
const ClutterEvent *event);
@@ -664,8 +678,6 @@ gboolean meta_window_handle_ungrabbed_event (MetaWindow *window,
void meta_window_set_surface_mapped (MetaWindow *window,
gboolean surface_mapped);
Window meta_window_get_toplevel_xwindow (MetaWindow *window);
void meta_window_get_client_area_rect (const MetaWindow *window,
cairo_rectangle_int_t *rect);
void meta_window_get_titlebar_rect (MetaWindow *window,
@@ -678,7 +690,8 @@ void meta_window_activate_full (MetaWindow *window,
gboolean meta_window_is_client_decorated (MetaWindow *window);
void meta_window_update_monitor (MetaWindow *window);
void meta_window_update_monitor (MetaWindow *window,
gboolean user_op);
void meta_window_set_urgent (MetaWindow *window,
gboolean urgent);
@@ -698,4 +711,6 @@ void meta_window_grab_op_ended (MetaWindow *window, MetaGrabOp op);
void meta_window_set_alive (MetaWindow *window, gboolean is_alive);
gboolean meta_window_has_pointer (MetaWindow *window);
#endif

View File

@@ -965,6 +965,7 @@ _meta_window_shared_new (MetaDisplay *display,
window->compositor_private = NULL;
window->monitor = meta_screen_get_monitor_for_window (window->screen, window);
window->preferred_output_id = window->monitor->output_id;
window->tile_match = NULL;
@@ -1275,6 +1276,12 @@ meta_window_unmanage (MetaWindow *window,
g_list_free (attached_children);
}
/* Make sure to only show window on all workspaces if requested, to
* not confuse other window managers that may take over
*/
if (window->screen->closing && meta_prefs_get_workspaces_only_on_primary ())
meta_window_update_on_all_workspaces (window);
if (window->fullscreen)
{
MetaGroup *group;
@@ -1405,6 +1412,7 @@ should_be_on_all_workspaces (MetaWindow *window)
window->on_all_workspaces_requested ||
window->override_redirect ||
(meta_prefs_get_workspaces_only_on_primary () &&
!window->unmanaging &&
!meta_window_is_on_primary_monitor (window));
}
@@ -3542,40 +3550,51 @@ meta_window_get_monitor (MetaWindow *window)
return window->monitor->number;
}
static MetaMonitorInfo *
find_monitor_by_id (MetaWindow *window,
guint id)
{
int i;
for (i = 0; i < window->screen->n_monitor_infos; i++)
{
MetaMonitorInfo *info = &window->screen->monitor_infos[i];
if (info->output_id != 0 && info->output_id == id)
return info;
}
return NULL;
}
/* This is called when the monitor setup has changed. The window->monitor
* reference is still "valid", but refer to the previous monitor setup */
void
meta_window_update_for_monitors_changed (MetaWindow *window)
{
const MetaMonitorInfo *old, *new;
int i;
if (window->type == META_WINDOW_DESKTOP)
return;
if (window->override_redirect)
{
meta_window_update_monitor (window);
meta_window_update_monitor (window, FALSE);
return;
}
old = window->monitor;
/* Start on primary */
new = &window->screen->monitor_infos[window->screen->primary_monitor_index];
/* Try the preferred output first */
new = find_monitor_by_id (window, window->preferred_output_id);
/* But, if we can find the old output on a new monitor, use that */
for (i = 0; i < window->screen->n_monitor_infos; i++)
{
MetaMonitorInfo *info = &window->screen->monitor_infos[i];
/* Otherwise, try to find the old output on a new monitor */
if (!new)
new = find_monitor_by_id (window, old->output_id);
if (info->output_id != 0 &&
info->output_id == old->output_id)
{
new = info;
break;
}
}
/* Fall back to primary if everything else failed */
if (!new)
new = &window->screen->monitor_infos[window->screen->primary_monitor_index];
if (window->tile_mode != META_TILE_NONE)
window->tile_monitor_number = new->number;
@@ -3593,7 +3612,8 @@ meta_window_update_for_monitors_changed (MetaWindow *window)
}
void
meta_window_update_monitor (MetaWindow *window)
meta_window_update_monitor (MetaWindow *window,
gboolean user_op)
{
const MetaMonitorInfo *old;
@@ -3603,22 +3623,17 @@ meta_window_update_monitor (MetaWindow *window)
{
meta_window_update_on_all_workspaces (window);
/* If workspaces only on primary and we moved back to primary, ensure that the
* window is now in that workspace. We do this because while the window is on a
* non-primary monitor it is always visible, so it would be very jarring if it
* disappeared when it crossed the monitor border.
/* If workspaces only on primary and we moved back to primary due to a user action,
* ensure that the window is now in that workspace. We do this because while
* the window is on a non-primary monitor it is always visible, so it would be
* very jarring if it disappeared when it crossed the monitor border.
* The one time we want it to both change to the primary monitor and a non-active
* workspace is when dropping the window on some other workspace thumbnail directly.
* That should be handled by explicitly moving the window before changing the
* workspace
* Don't do this if old == NULL, because thats what happens when starting up, and
* we don't want to move all windows around from a previous WM instance. Nor do
* we want it when moving from one primary monitor to another (can happen during
* screen reconfiguration.
* workspace.
*/
if (meta_prefs_get_workspaces_only_on_primary () &&
if (meta_prefs_get_workspaces_only_on_primary () && user_op &&
meta_window_is_on_primary_monitor (window) &&
old != NULL && !old->is_primary &&
window->screen->active_workspace != window->workspace)
meta_window_change_workspace (window, window->screen->active_workspace);
@@ -3629,6 +3644,7 @@ meta_window_update_monitor (MetaWindow *window)
/* If we're changing monitors, we need to update the has_maximize_func flag,
* as the working area has changed. */
meta_window_recalc_features (window);
meta_window_queue (window, META_QUEUE_CALC_SHOWING);
}
}
@@ -3658,6 +3674,7 @@ meta_window_move_resize_internal (MetaWindow *window,
*/
gboolean did_placement;
guint old_output_id;
MetaRectangle unconstrained_rect;
MetaRectangle constrained_rect;
MetaMoveResizeResultFlags result = 0;
@@ -3742,7 +3759,13 @@ meta_window_move_resize_internal (MetaWindow *window,
did_placement);
}
meta_window_update_monitor (window);
old_output_id = window->monitor->output_id;
meta_window_update_monitor (window, flags & META_IS_USER_ACTION);
if (old_output_id != window->monitor->output_id &&
flags & META_IS_MOVE_ACTION && flags & META_IS_USER_ACTION)
window->preferred_output_id = window->monitor->output_id;
if ((result & META_MOVE_RESIZE_RESULT_FRAME_SHAPE_CHANGED) && window->frame_bounds)
{
@@ -3862,6 +3885,7 @@ meta_window_move_to_monitor (MetaWindow *window,
window->tile_monitor_number = monitor;
meta_window_move_between_rects (window, &old_area, &new_area);
window->preferred_output_id = window->monitor->output_id;
if (window->fullscreen || window->override_redirect)
meta_screen_queue_check_fullscreen (window->screen);
@@ -4036,26 +4060,23 @@ meta_window_get_session_geometry (MetaWindow *window,
}
/**
* meta_window_get_input_rect:
* meta_window_get_buffer_rect:
* @window: a #MetaWindow
* @rect: (out): pointer to an allocated #MetaRectangle
*
* Gets the rectangle that bounds @window that is responsive to mouse events.
* This includes decorations - the visible portion of its border - and (if
* present) any invisible area that we make make responsive to mouse clicks in
* order to allow convenient border dragging.
* Gets the rectangle that the pixmap or buffer of @window occupies.
*
* For X11 windows, this is the server-side geometry of the toplevel
* window.
*
* For Wayland windows, this is the bounding rectangle of the attached
* buffer.
*/
void
meta_window_get_input_rect (const MetaWindow *window,
MetaRectangle *rect)
meta_window_get_buffer_rect (const MetaWindow *window,
MetaRectangle *rect)
{
if (window->frame)
*rect = window->frame->rect;
else
{
*rect = window->rect;
meta_window_frame_rect_to_client_rect ((MetaWindow *) window, rect, rect);
}
*rect = window->buffer_rect;
}
/**
@@ -5251,6 +5272,15 @@ meta_window_show_menu (MetaWindow *window,
meta_compositor_show_window_menu (window->display->compositor, window, menu, x, y);
}
void
meta_window_show_menu_for_rect (MetaWindow *window,
MetaWindowMenuType menu,
MetaRectangle *rect)
{
g_return_if_fail (!window->override_redirect);
meta_compositor_show_window_menu_for_rect (window->display->compositor, window, menu, rect);
}
void
meta_window_shove_titlebar_onscreen (MetaWindow *window)
{
@@ -7654,8 +7684,8 @@ window_has_pointer_x11 (MetaWindow *window)
return meta_display_lookup_x_window (display, child) == window;
}
static gboolean
window_has_pointer (MetaWindow *window)
gboolean
meta_window_has_pointer (MetaWindow *window)
{
if (meta_is_wayland_compositor ())
return window_has_pointer_wayland (window);
@@ -7684,10 +7714,10 @@ window_focus_on_pointer_rest_callback (gpointer data)
{
focus_data->pointer_x = root_x;
focus_data->pointer_y = root_y;
return TRUE;
return G_SOURCE_CONTINUE;
}
if (!window_has_pointer (window))
if (!meta_window_has_pointer (window))
goto out;
timestamp = meta_display_get_current_time_roundtrip (display);
@@ -7695,7 +7725,7 @@ window_focus_on_pointer_rest_callback (gpointer data)
out:
display->focus_timeout_id = 0;
return FALSE;
return G_SOURCE_REMOVE;
}
/* The interval, in milliseconds, we use in focus-follows-mouse
@@ -7784,6 +7814,15 @@ meta_window_handle_ungrabbed_event (MetaWindow *window,
if (display->grab_op != META_GRAB_OP_NONE)
return FALSE;
/* Some windows might not ask for input, in which case we might be here
* because we selected for ButtonPress on the root window. In that case,
* we have to take special care not to act for an override-redirect window.
*
* Consume the event in this case, though, since we don't want it passed
* to the compositor or UI. */
if (window->override_redirect)
return TRUE;
/* We have three passive button grabs:
* - on any button, without modifiers => focuses and maybe raises the window
* - on resize button, with modifiers => start an interactive resizing
@@ -7932,12 +7971,6 @@ meta_window_set_surface_mapped (MetaWindow *window,
meta_window_queue (window, META_QUEUE_CALC_SHOWING);
}
Window
meta_window_get_toplevel_xwindow (MetaWindow *window)
{
return window->frame ? window->frame->xwindow : window->xwindow;
}
void
meta_window_set_custom_frame_extents (MetaWindow *window,
GtkBorder *extents)

View File

@@ -1040,6 +1040,45 @@ void
meta_workspace_set_builtin_struts (MetaWorkspace *workspace,
GSList *struts)
{
MetaScreen *screen = workspace->screen;
GSList *l;
for (l = struts; l; l = l->next)
{
MetaStrut *strut = l->data;
int idx = meta_screen_get_monitor_index_for_rect (screen, &strut->rect);
switch (strut->side)
{
case META_SIDE_TOP:
if (meta_screen_get_monitor_neighbor (screen, idx, META_SCREEN_UP))
continue;
strut->rect.height += strut->rect.y;
strut->rect.y = 0;
break;
case META_SIDE_BOTTOM:
if (meta_screen_get_monitor_neighbor (screen, idx, META_SCREEN_DOWN))
continue;
strut->rect.height = screen->rect.height - strut->rect.y;
break;
case META_SIDE_LEFT:
if (meta_screen_get_monitor_neighbor (screen, idx, META_SCREEN_LEFT))
continue;
strut->rect.width += strut->rect.x;
strut->rect.x = 0;
break;
case META_SIDE_RIGHT:
if (meta_screen_get_monitor_neighbor (screen, idx, META_SCREEN_RIGHT))
continue;
strut->rect.width = screen->rect.width - strut->rect.x;
break;
}
}
/* Reordering doesn't actually matter, so we don't catch all
* no-impact changes, but this is just a (possibly unnecessary
* anyways) optimization */

View File

@@ -5,14 +5,9 @@ includedir=@includedir@
girdir=@libdir@/mutter
typelibdir=@libdir@/mutter
mutter_major_version=@MUTTER_MAJOR_VERSION@
mutter_minor_version=@MUTTER_MINOR_VERSION@
mutter_micro_version=@MUTTER_MICRO_VERSION@
mutter_plugin_api_version=@MUTTER_PLUGIN_API_VERSION@
Name: libmutter
Description: Mutter window manager library
Requires: gsettings-desktop-schemas gtk+-3.0 @CLUTTER_PACKAGE@ x11
Version: @VERSION@
Libs: -L${libdir} -lmutter
Cflags: -I${includedir}/mutter -DMUTTER_MAJOR_VERSION=${mutter_major_version} -DMUTTER_MINOR_VERSION=${mutter_minor_version} -DMUTTER_MICRO_VERSION=${mutter_micro_version} -DMUTTER_PLUGIN_API_VERSION=${mutter_plugin_api_version}
Cflags: -I${includedir}/mutter

View File

@@ -43,8 +43,6 @@
#define META_VIRTUAL_CORE_POINTER_ID 2
#define META_VIRTUAL_CORE_KEYBOARD_ID 3
typedef struct _MetaResizePopup MetaResizePopup;
/**
* MetaFrameFlags:
* @META_FRAME_ALLOWS_DELETE: frame allows delete

View File

@@ -101,9 +101,8 @@ void meta_compositor_unmaximize_window (MetaCompositor *compositor,
void meta_compositor_sync_window_geometry (MetaCompositor *compositor,
MetaWindow *window,
gboolean did_placement);
void meta_compositor_set_updates_frozen (MetaCompositor *compositor,
MetaWindow *window,
gboolean updates_frozen);
void meta_compositor_sync_updates_frozen (MetaCompositor *compositor,
MetaWindow *window);
void meta_compositor_queue_frame_drawn (MetaCompositor *compositor,
MetaWindow *window,
gboolean no_delay_frame);
@@ -127,5 +126,9 @@ void meta_compositor_show_window_menu (MetaCompositor *compositor,
MetaWindowMenuType menu,
int x,
int y);
void meta_compositor_show_window_menu_for_rect (MetaCompositor *compositor,
MetaWindow *window,
MetaWindowMenuType menu,
MetaRectangle *rect);
#endif /* META_COMPOSITOR_H */

View File

@@ -75,7 +75,6 @@ Display *meta_display_get_xdisplay (MetaDisplay *display);
MetaCompositor *meta_display_get_compositor (MetaDisplay *display);
gboolean meta_display_has_shape (MetaDisplay *display);
gboolean meta_display_has_sync (MetaDisplay *display);
MetaWindow *meta_display_get_focus_window (MetaDisplay *display);
@@ -84,7 +83,6 @@ gboolean meta_display_xwindow_is_a_no_focus_window (MetaDisplay *display,
int meta_display_get_damage_event_base (MetaDisplay *display);
int meta_display_get_shape_event_base (MetaDisplay *display);
int meta_display_get_sync_event_base (MetaDisplay *display);
gboolean meta_display_xserver_time_is_before (MetaDisplay *display,
guint32 time1,
@@ -96,7 +94,6 @@ guint32 meta_display_get_current_time_roundtrip (MetaDisplay *display);
GList* meta_display_get_tab_list (MetaDisplay *display,
MetaTabList type,
MetaScreen *screen,
MetaWorkspace *workspace);
MetaWindow* meta_display_get_tab_next (MetaDisplay *display,

View File

@@ -25,6 +25,7 @@
#include <meta/types.h>
#include <meta/compositor.h>
#include <meta/compositor-mutter.h>
#include <meta/meta-version.h>
#include <clutter/clutter.h>
#include <X11/extensions/Xfixes.h>
@@ -170,6 +171,11 @@ struct _MetaPluginClass
int x,
int y);
void (*show_window_menu_for_rect) (MetaPlugin *plugin,
MetaWindow *window,
MetaWindowMenuType menu,
MetaRectangle *rect);
/**
* MetaPluginClass::kill_window_effects:
* @actor: a #MetaWindowActor
@@ -294,10 +300,10 @@ struct _MetaPluginVersion
#define META_PLUGIN_DECLARE(ObjectName, object_name) \
G_MODULE_EXPORT MetaPluginVersion meta_plugin_version = \
{ \
MUTTER_MAJOR_VERSION, \
MUTTER_MINOR_VERSION, \
MUTTER_MICRO_VERSION, \
MUTTER_PLUGIN_API_VERSION \
META_MAJOR_VERSION, \
META_MINOR_VERSION, \
META_MICRO_VERSION, \
META_PLUGIN_API_VERSION \
}; \
\
static GType g_define_type_id = 0; \

View File

@@ -0,0 +1,28 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Rico Tzschichholz
*
* 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_VERSION_H
#define META_VERSION_H
#define META_MAJOR_VERSION @MUTTER_MAJOR_VERSION@
#define META_MINOR_VERSION @MUTTER_MINOR_VERSION@
#define META_MICRO_VERSION @MUTTER_MICRO_VERSION@
#define META_PLUGIN_API_VERSION @MUTTER_PLUGIN_API_VERSION@
#endif

View File

@@ -108,7 +108,7 @@ gboolean meta_window_appears_focused (MetaWindow *window);
gboolean meta_window_is_shaded (MetaWindow *window);
gboolean meta_window_is_override_redirect (MetaWindow *window);
gboolean meta_window_is_skip_taskbar (MetaWindow *window);
void meta_window_get_input_rect (const MetaWindow *window, MetaRectangle *rect);
void meta_window_get_buffer_rect (const MetaWindow *window, MetaRectangle *rect);
void meta_window_get_frame_rect (const MetaWindow *window, MetaRectangle *rect);
void meta_window_get_outer_rect (const MetaWindow *window, MetaRectangle *rect) G_GNUC_DEPRECATED;

View File

@@ -224,8 +224,6 @@ meta_frames_init (MetaFrames *frames)
update_style_contexts (frames);
gtk_widget_set_double_buffered (GTK_WIDGET (frames), FALSE);
meta_prefs_add_listener (prefs_changed_callback, frames);
}
@@ -1218,30 +1216,36 @@ meta_frames_button_press_event (GtkWidget *widget,
{
MetaFrameGeometry fgeom;
GdkRectangle *rect;
MetaRectangle root_rect;
MetaWindowMenuType menu;
int dx, dy;
int win_x, win_y;
meta_frames_calc_geometry (frames, frame, &fgeom);
rect = control_rect (control, &fgeom);
/* get delta to convert to root coords */
dx = event->x_root - event->x;
dy = event->y_root - event->y;
/* convert to root coords */
win_x = event->x_root - event->x;
win_y = event->y_root - event->y;
/* Align to the right end of the menu rectangle if RTL */
if (meta_ui_get_direction() == META_UI_DIRECTION_RTL)
dx += rect->width;
root_rect.x = win_x + rect->x;
root_rect.y = win_y + rect->y;
root_rect.width = rect->width;
root_rect.height = rect->height;
menu = control == META_FRAME_CONTROL_MENU ? META_WINDOW_MENU_WM
: META_WINDOW_MENU_APP;
meta_core_show_window_menu (display,
frame->xwindow,
menu,
rect->x + dx,
rect->y + rect->height + dy,
event->time);
/* if the compositor takes a grab for showing the menu, we will
* get a LeaveNotify event we want to ignore, to keep the pressed
* button state while the menu is open
*/
frame->maybe_ignore_leave_notify = TRUE;
meta_core_show_window_menu_for_rect (display,
frame->xwindow,
menu,
&root_rect,
event->time);
}
}
else if (event->button == 1 &&
@@ -1506,7 +1510,8 @@ meta_frames_update_prelit_control (MetaFrames *frames,
break;
}
if (control == frame->prelit_control)
if (control == frame->prelit_control &&
frame->button_state == META_BUTTON_STATE_PRELIGHT)
return;
/* Save the old control so we can unprelight it */
@@ -1575,31 +1580,8 @@ meta_frames_destroy_event (GtkWidget *widget,
}
static void
setup_bg_cr (cairo_t *cr, GdkWindow *window, int x_offset, int y_offset)
{
GdkWindow *parent = gdk_window_get_parent (window);
cairo_pattern_t *bg_pattern;
bg_pattern = gdk_window_get_background_pattern (window);
if (bg_pattern == NULL && parent)
{
gint window_x, window_y;
gdk_window_get_position (window, &window_x, &window_y);
setup_bg_cr (cr, parent, x_offset + window_x, y_offset + window_y);
}
else if (bg_pattern)
{
cairo_translate (cr, - x_offset, - y_offset);
cairo_set_source (cr, bg_pattern);
cairo_translate (cr, x_offset, y_offset);
}
}
static void
clip_region_to_visible_frame_border (cairo_region_t *region,
MetaUIFrame *frame)
static cairo_region_t *
get_visible_frame_border_region (MetaUIFrame *frame)
{
MetaRectangle frame_rect;
cairo_rectangle_int_t area;
@@ -1637,9 +1619,7 @@ clip_region_to_visible_frame_border (cairo_region_t *region,
/* Visible frame border */
cairo_region_subtract_rectangle (frame_border, &area);
cairo_region_intersect (region, frame_border);
cairo_region_destroy (frame_border);
return frame_border;
}
#define TAU (2*M_PI)
@@ -1738,42 +1718,42 @@ meta_frames_get_mask (MetaFrames *frames,
cairo_restore (cr);
}
/* XXX -- this is disgusting. Find a better approach here.
* Use multiple widgets? */
static MetaUIFrame *
find_frame_to_draw (MetaFrames *frames,
cairo_t *cr)
{
GHashTableIter iter;
MetaUIFrame *frame;
g_hash_table_iter_init (&iter, frames->frames);
while (g_hash_table_iter_next (&iter, (gpointer *) &frame, NULL))
if (gtk_cairo_should_draw_window (cr, frame->window))
return frame;
return NULL;
}
static gboolean
meta_frames_draw (GtkWidget *widget,
cairo_t *cr)
{
MetaUIFrame *frame;
MetaFrames *frames;
cairo_rectangle_int_t clip;
cairo_region_t *region;
cairo_surface_t *target;
frames = META_FRAMES (widget);
target = cairo_get_target (cr);
gdk_cairo_get_clip_rectangle (cr, &clip);
g_assert (cairo_surface_get_type (target) == CAIRO_SURFACE_TYPE_XLIB);
frame = meta_frames_lookup_window (frames, cairo_xlib_surface_get_drawable (target));
frame = find_frame_to_draw (frames, cr);
if (frame == NULL)
return FALSE;
region = cairo_region_create_rectangle (&clip);
clip_region_to_visible_frame_border (region, frame);
if (cairo_region_is_empty (region))
goto out;
region = get_visible_frame_border_region (frame);
gdk_cairo_region (cr, region);
cairo_clip (cr);
cairo_save (cr);
setup_bg_cr (cr, frame->window, 0, 0);
cairo_paint (cr);
cairo_restore (cr);
meta_frames_paint (frames, frame, cr);
out:
cairo_region_destroy (region);
return TRUE;
@@ -1932,6 +1912,8 @@ meta_frames_enter_notify_event (GtkWidget *widget,
if (frame == NULL)
return FALSE;
frame->maybe_ignore_leave_notify = FALSE;
control = get_control (frames, frame, event->x, event->y);
meta_frames_update_prelit_control (frames, frame, control);
@@ -1944,6 +1926,8 @@ meta_frames_leave_notify_event (GtkWidget *widget,
{
MetaUIFrame *frame;
MetaFrames *frames;
Display *display;
MetaGrabOp grab_op;
frames = META_FRAMES (widget);
@@ -1951,6 +1935,18 @@ meta_frames_leave_notify_event (GtkWidget *widget,
if (frame == NULL)
return FALSE;
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
grab_op = meta_core_get_grab_op (display);
/* ignore the first LeaveNotify event after opening a window menu
* if it is the result of a compositor grab
*/
frame->maybe_ignore_leave_notify = frame->maybe_ignore_leave_notify &&
grab_op == META_GRAB_OP_COMPOSITOR;
if (frame->maybe_ignore_leave_notify)
return FALSE;
meta_frames_update_prelit_control (frames, frame, META_FRAME_CONTROL_NONE);
return TRUE;

View File

@@ -80,6 +80,7 @@ struct _MetaUIFrame
int text_height;
char *title; /* NULL once we have a layout */
guint shape_applied : 1;
guint maybe_ignore_leave_notify : 1;
/* FIXME get rid of this, it can just be in the MetaFrames struct */
MetaFrameControl prelit_control;

View File

@@ -29,6 +29,8 @@
#include <glib.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
typedef struct _MetaResizePopup MetaResizePopup;
MetaResizePopup* meta_ui_resize_popup_new (Display *display,
int screen_number);
void meta_ui_resize_popup_free (MetaResizePopup *popup);

View File

@@ -56,8 +56,6 @@
((int)((color).green * 255) << 8) | \
((int)((color).blue * 255))))
#define ALPHA_TO_UCHAR(d) ((unsigned char) ((d) * 255))
#define DEBUG_FILL_STRUCT(s) memset ((s), 0xef, sizeof (*(s)))
#define CLAMP_UCHAR(v) ((guchar) (CLAMP (((int)v), (int)0, (int)255)))
#define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
@@ -94,8 +92,8 @@ colorize_pixbuf (GdkPixbuf *orig,
guchar *dest_pixels;
pixbuf = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (orig), gdk_pixbuf_get_has_alpha (orig),
gdk_pixbuf_get_bits_per_sample (orig),
gdk_pixbuf_get_width (orig), gdk_pixbuf_get_height (orig));
gdk_pixbuf_get_bits_per_sample (orig),
gdk_pixbuf_get_width (orig), gdk_pixbuf_get_height (orig));
if (pixbuf == NULL)
return NULL;
@@ -795,19 +793,19 @@ meta_frame_layout_calc_geometry (const MetaFrameLayout *layout,
&n_right, &fgeom->above_rect))
continue;
else if (strip_button (left_func_rects, left_bg_rects,
&n_left, &fgeom->stick_rect))
&n_left, &fgeom->stick_rect))
continue;
else if (strip_button (right_func_rects, right_bg_rects,
&n_right, &fgeom->stick_rect))
continue;
else if (strip_button (left_func_rects, left_bg_rects,
&n_left, &fgeom->shade_rect))
&n_left, &fgeom->shade_rect))
continue;
else if (strip_button (right_func_rects, right_bg_rects,
&n_right, &fgeom->shade_rect))
continue;
else if (strip_button (left_func_rects, left_bg_rects,
&n_left, &fgeom->min_rect))
&n_left, &fgeom->min_rect))
continue;
else if (strip_button (right_func_rects, right_bg_rects,
&n_right, &fgeom->min_rect))
@@ -926,12 +924,11 @@ meta_frame_layout_calc_geometry (const MetaFrameLayout *layout,
rect->clickable.width = button_width;
}
rect->clickable.y = 0;
rect->clickable.height = button_height + button_y;
}
else
g_memmove (&(rect->clickable), &(rect->visible), sizeof(rect->clickable));
rect->clickable.y = 0;
rect->clickable.height = button_height + button_y;
}
else
g_memmove (&(rect->clickable), &(rect->visible), sizeof(rect->clickable));
x = rect->visible.x + rect->visible.width + layout->button_border.right;
if (left_buttons_has_spacer[i])
@@ -1192,10 +1189,8 @@ meta_color_spec_new_from_string (const char *str,
MetaColorSpec *spec;
spec = NULL;
if (str[0] == 'g' && str[1] == 't' && str[2] == 'k' && str[3] == ':' &&
str[4] == 'c' && str[5] == 'u' && str[6] == 's' && str[7] == 't' &&
str[8] == 'o' && str[9] == 'm')
if (strncmp (str, "gtk:custom", 10) == 0)
{
const char *color_name_start, *fallback_str_start, *end;
char *color_name;
@@ -1270,7 +1265,7 @@ meta_color_spec_new_from_string (const char *str,
spec->data.gtkcustom.color_name = color_name;
spec->data.gtkcustom.fallback = fallback;
}
else if (str[0] == 'g' && str[1] == 't' && str[2] == 'k' && str[3] == ':')
else if (strncmp (str, "gtk:", 4) == 0)
{
/* GTK color */
const char *bracket;
@@ -1337,8 +1332,7 @@ meta_color_spec_new_from_string (const char *str,
spec->data.gtk.component = component;
g_assert (spec->data.gtk.component < META_GTK_COLOR_LAST);
}
else if (str[0] == 'b' && str[1] == 'l' && str[2] == 'e' && str[3] == 'n' &&
str[4] == 'd' && str[5] == '/')
else if (strncmp (str, "blend/", 6) == 0)
{
/* blend */
char **split;
@@ -1406,8 +1400,7 @@ meta_color_spec_new_from_string (const char *str,
spec->data.blend.background = bg;
spec->data.blend.foreground = fg;
}
else if (str[0] == 's' && str[1] == 'h' && str[2] == 'a' && str[3] == 'd' &&
str[4] == 'e' && str[5] == '/')
else if (strncmp (str, "shade/", 6) == 0)
{
/* shade */
char **split;
@@ -1704,20 +1697,12 @@ op_from_string (const char *p,
return POS_OP_MOD;
case '`':
if (p[0] == '`' &&
p[1] == 'm' &&
p[2] == 'a' &&
p[3] == 'x' &&
p[4] == '`')
if (strncmp (p, "`max`", 5) == 0)
{
*len = 5;
return POS_OP_MAX;
}
else if (p[0] == '`' &&
p[1] == 'm' &&
p[2] == 'i' &&
p[3] == 'n' &&
p[4] == '`')
else if (strncmp (p, "`min`", 5) == 0)
{
*len = 5;
return POS_OP_MIN;
@@ -3067,7 +3052,7 @@ meta_draw_op_free (MetaDrawOp *op)
g_object_unref (G_OBJECT (op->data.image.pixbuf));
if (op->data.image.colorize_spec)
meta_color_spec_free (op->data.image.colorize_spec);
meta_color_spec_free (op->data.image.colorize_spec);
if (op->data.image.colorize_cache_pixbuf)
g_object_unref (G_OBJECT (op->data.image.colorize_cache_pixbuf));
@@ -3418,32 +3403,6 @@ draw_op_as_pixbuf (const MetaDrawOp *op,
switch (op->type)
{
case META_DRAW_LINE:
break;
case META_DRAW_RECTANGLE:
if (op->data.rectangle.filled)
{
GdkRGBA color;
meta_color_spec_render (op->data.rectangle.color_spec,
context,
&color);
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
FALSE,
8, width, height);
gdk_pixbuf_fill (pixbuf, GDK_COLOR_RGBA (color));
}
break;
case META_DRAW_ARC:
break;
case META_DRAW_CLIP:
break;
case META_DRAW_TINT:
{
GdkRGBA color;
@@ -3502,12 +3461,11 @@ draw_op_as_pixbuf (const MetaDrawOp *op,
}
break;
case META_DRAW_IMAGE:
{
if (op->data.image.colorize_spec)
{
GdkRGBA color;
if (op->data.image.colorize_spec)
{
GdkRGBA color;
meta_color_spec_render (op->data.image.colorize_spec,
context, &color);
@@ -3535,24 +3493,18 @@ draw_op_as_pixbuf (const MetaDrawOp *op,
op->data.image.vertical_stripes,
op->data.image.horizontal_stripes);
}
}
else
{
pixbuf = scale_and_alpha_pixbuf (op->data.image.pixbuf,
}
else
{
pixbuf = scale_and_alpha_pixbuf (op->data.image.pixbuf,
op->data.image.alpha_spec,
op->data.image.fill_type,
width, height,
op->data.image.vertical_stripes,
op->data.image.horizontal_stripes);
}
}
break;
}
case META_DRAW_GTK_ARROW:
case META_DRAW_GTK_BOX:
case META_DRAW_GTK_VLINE:
break;
case META_DRAW_ICON:
if (info->mini_icon &&
width <= gdk_pixbuf_get_width (info->mini_icon) &&
@@ -3570,12 +3522,15 @@ draw_op_as_pixbuf (const MetaDrawOp *op,
FALSE, FALSE);
break;
case META_DRAW_LINE:
case META_DRAW_RECTANGLE:
case META_DRAW_ARC:
case META_DRAW_CLIP:
case META_DRAW_GTK_ARROW:
case META_DRAW_GTK_BOX:
case META_DRAW_GTK_VLINE:
case META_DRAW_TITLE:
break;
case META_DRAW_OP_LIST:
break;
case META_DRAW_TILE:
break;
}
@@ -4046,8 +4001,7 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op,
d_rect.height = parse_size_unchecked (op->data.op_list.height, env);
meta_draw_op_list_draw_with_style (op->data.op_list.op_list,
style_gtk, cr, info,
d_rect);
style_gtk, cr, info, d_rect);
}
break;
@@ -4084,8 +4038,7 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op,
while (tile.y < (ry + rheight))
{
meta_draw_op_list_draw_with_style (op->data.tile.op_list,
style_gtk, cr, info,
tile);
style_gtk, cr, info, tile);
tile.y += tile.height;
}
@@ -6569,216 +6522,6 @@ hls_to_rgb (gdouble *h,
}
}
#if 0
/* These are some functions I'm saving to use in optimizing
* MetaDrawOpList, namely to pre-composite pixbufs on client side
* prior to rendering to the server
*/
static void
draw_bg_solid_composite (const MetaTextureSpec *bg,
const MetaTextureSpec *fg,
double alpha,
GtkWidget *widget,
GdkDrawable *drawable,
const GdkRectangle *clip,
MetaTextureDrawMode mode,
double xalign,
double yalign,
int x,
int y,
int width,
int height)
{
GdkRGBA bg_color;
g_assert (bg->type == META_TEXTURE_SOLID);
g_assert (fg->type != META_TEXTURE_COMPOSITE);
g_assert (fg->type != META_TEXTURE_SHAPE_LIST);
meta_color_spec_render (bg->data.solid.color_spec,
widget,
&bg_color);
switch (fg->type)
{
case META_TEXTURE_SOLID:
{
GdkRGBA fg_color;
meta_color_spec_render (fg->data.solid.color_spec,
widget,
&fg_color);
color_composite (&bg_color, &fg_color,
alpha, &fg_color);
draw_color_rectangle (widget, drawable, &fg_color, clip,
x, y, width, height);
}
break;
case META_TEXTURE_GRADIENT:
/* FIXME I think we could just composite all the colors in
* the gradient prior to generating the gradient?
*/
/* FALL THRU */
case META_TEXTURE_IMAGE:
{
GdkPixbuf *pixbuf;
GdkPixbuf *composited;
pixbuf = meta_texture_spec_render (fg, widget, mode, 255,
width, height);
if (pixbuf == NULL)
return;
composited = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
gdk_pixbuf_get_has_alpha (pixbuf), 8,
gdk_pixbuf_get_width (pixbuf),
gdk_pixbuf_get_height (pixbuf));
if (composited == NULL)
{
g_object_unref (G_OBJECT (pixbuf));
return;
}
gdk_pixbuf_composite_color (pixbuf,
composited,
0, 0,
gdk_pixbuf_get_width (pixbuf),
gdk_pixbuf_get_height (pixbuf),
0.0, 0.0, /* offsets */
1.0, 1.0, /* scale */
GDK_INTERP_BILINEAR,
255 * alpha,
0, 0, /* check offsets */
0, /* check size */
GDK_COLOR_RGB (bg_color),
GDK_COLOR_RGB (bg_color));
/* Need to draw background since pixbuf is not
* necessarily covering the whole thing
*/
draw_color_rectangle (widget, drawable, &bg_color, clip,
x, y, width, height);
render_pixbuf_aligned (drawable, clip, composited,
xalign, yalign,
x, y, width, height);
g_object_unref (G_OBJECT (pixbuf));
g_object_unref (G_OBJECT (composited));
}
break;
case META_TEXTURE_BLANK:
case META_TEXTURE_COMPOSITE:
case META_TEXTURE_SHAPE_LIST:
g_assert_not_reached ();
break;
}
}
static void
draw_bg_gradient_composite (const MetaTextureSpec *bg,
const MetaTextureSpec *fg,
double alpha,
GtkWidget *widget,
GdkDrawable *drawable,
const GdkRectangle *clip,
MetaTextureDrawMode mode,
double xalign,
double yalign,
int x,
int y,
int width,
int height)
{
g_assert (bg->type == META_TEXTURE_GRADIENT);
g_assert (fg->type != META_TEXTURE_COMPOSITE);
g_assert (fg->type != META_TEXTURE_SHAPE_LIST);
switch (fg->type)
{
case META_TEXTURE_SOLID:
case META_TEXTURE_GRADIENT:
case META_TEXTURE_IMAGE:
{
GdkPixbuf *bg_pixbuf;
GdkPixbuf *fg_pixbuf;
GdkPixbuf *composited;
int fg_width, fg_height;
bg_pixbuf = meta_texture_spec_render (bg, widget, mode, 255,
width, height);
if (bg_pixbuf == NULL)
return;
fg_pixbuf = meta_texture_spec_render (fg, widget, mode, 255,
width, height);
if (fg_pixbuf == NULL)
{
g_object_unref (G_OBJECT (bg_pixbuf));
return;
}
/* gradients always fill the entire target area */
g_assert (gdk_pixbuf_get_width (bg_pixbuf) == width);
g_assert (gdk_pixbuf_get_height (bg_pixbuf) == height);
composited = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
gdk_pixbuf_get_has_alpha (bg_pixbuf), 8,
gdk_pixbuf_get_width (bg_pixbuf),
gdk_pixbuf_get_height (bg_pixbuf));
if (composited == NULL)
{
g_object_unref (G_OBJECT (bg_pixbuf));
g_object_unref (G_OBJECT (fg_pixbuf));
return;
}
fg_width = gdk_pixbuf_get_width (fg_pixbuf);
fg_height = gdk_pixbuf_get_height (fg_pixbuf);
/* If we wanted to be all cool we could deal with the
* offsets and try to composite only in the clip rectangle,
* but I just don't care enough to figure it out.
*/
gdk_pixbuf_composite (fg_pixbuf,
composited,
x + (width - fg_width) * xalign,
y + (height - fg_height) * yalign,
gdk_pixbuf_get_width (fg_pixbuf),
gdk_pixbuf_get_height (fg_pixbuf),
0.0, 0.0, /* offsets */
1.0, 1.0, /* scale */
GDK_INTERP_BILINEAR,
255 * alpha);
gdk_cairo_set_source_pixbuf (cr, composited, x, y);
cairo_paint (cr);
g_object_unref (G_OBJECT (bg_pixbuf));
g_object_unref (G_OBJECT (fg_pixbuf));
g_object_unref (G_OBJECT (composited));
}
break;
case META_TEXTURE_BLANK:
case META_TEXTURE_SHAPE_LIST:
case META_TEXTURE_COMPOSITE:
g_assert_not_reached ();
break;
}
}
#endif
/**
* meta_theme_earliest_version_with_button:
* @type: the button type

View File

@@ -200,8 +200,6 @@ meta_wayland_pointer_init (MetaWaylandPointer *pointer,
pointer->cursor_surface = NULL;
pointer->cursor_surface_destroy_listener.notify = pointer_handle_cursor_surface_destroy;
pointer->hotspot_x = 16;
pointer->hotspot_y = 16;
pointer->default_grab.interface = &default_pointer_grab_interface;
pointer->default_grab.pointer = pointer;

View File

@@ -59,7 +59,10 @@ seat_get_touch (struct wl_client *client,
struct wl_resource *resource,
uint32_t id)
{
/* Touch not supported */
MetaWaylandSeat *seat = wl_resource_get_user_data (resource);
MetaWaylandTouch *touch = &seat->touch;
meta_wayland_touch_create_new_resource (touch, client, resource, id);
}
static const struct wl_seat_interface seat_interface = {
@@ -84,7 +87,8 @@ bind_seat (struct wl_client *client,
wl_seat_send_capabilities (resource,
WL_SEAT_CAPABILITY_POINTER |
WL_SEAT_CAPABILITY_KEYBOARD);
WL_SEAT_CAPABILITY_KEYBOARD |
WL_SEAT_CAPABILITY_TOUCH);
if (version >= WL_SEAT_NAME_SINCE_VERSION)
wl_seat_send_name (resource, "seat0");
@@ -101,6 +105,7 @@ meta_wayland_seat_new (struct wl_display *display)
meta_wayland_pointer_init (&seat->pointer, display);
meta_wayland_keyboard_init (&seat->keyboard, display);
meta_wayland_touch_init (&seat->touch, display);
seat->display = display;
@@ -120,6 +125,7 @@ meta_wayland_seat_free (MetaWaylandSeat *seat)
{
meta_wayland_pointer_release (&seat->pointer);
meta_wayland_keyboard_release (&seat->keyboard);
meta_wayland_touch_release (&seat->touch);
g_slice_free (MetaWaylandSeat, seat);
}
@@ -142,6 +148,12 @@ meta_wayland_seat_update (MetaWaylandSeat *seat,
meta_wayland_keyboard_update (&seat->keyboard, (const ClutterKeyEvent *) event);
break;
case CLUTTER_TOUCH_BEGIN:
case CLUTTER_TOUCH_UPDATE:
case CLUTTER_TOUCH_END:
meta_wayland_touch_update (&seat->touch, event);
break;
default:
break;
}
@@ -163,6 +175,10 @@ meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
case CLUTTER_KEY_RELEASE:
return meta_wayland_keyboard_handle_event (&seat->keyboard,
(const ClutterKeyEvent *) event);
case CLUTTER_TOUCH_BEGIN:
case CLUTTER_TOUCH_UPDATE:
case CLUTTER_TOUCH_END:
return meta_wayland_touch_handle_event (&seat->touch, event);
default:
break;

View File

@@ -28,6 +28,7 @@
#include "meta-wayland-types.h"
#include "meta-wayland-keyboard.h"
#include "meta-wayland-pointer.h"
#include "meta-wayland-touch.h"
struct _MetaWaylandDataOffer
{
@@ -53,6 +54,7 @@ struct _MetaWaylandSeat
struct wl_list data_device_resource_list;
MetaWaylandPointer pointer;
MetaWaylandKeyboard keyboard;
MetaWaylandTouch touch;
struct wl_display *display;
};

View File

@@ -1677,11 +1677,10 @@ wl_subcompositor_get_subsurface (struct wl_client *client,
}
pending_state_init (&surface->sub.pending);
surface->sub.synchronous = TRUE;
surface->sub.parent = parent;
surface->sub.parent_destroy_listener.notify =
surface_handle_parent_surface_destroyed;
wl_resource_add_destroy_listener (parent->resource,
&surface->sub.parent_destroy_listener);
surface->sub.parent_destroy_listener.notify = surface_handle_parent_surface_destroyed;
wl_resource_add_destroy_listener (parent->resource, &surface->sub.parent_destroy_listener);
parent->subsurfaces = g_list_append (parent->subsurfaces, surface);
clutter_actor_add_child (CLUTTER_ACTOR (parent->surface_actor),

View File

@@ -0,0 +1,548 @@
/*
* Wayland Support
*
* 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.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#define _GNU_SOURCE
#include "config.h"
#include <glib.h>
#include <string.h>
#include <clutter/evdev/clutter-evdev.h>
#include "meta-surface-actor-wayland.h"
#include "meta-wayland-private.h"
struct _MetaWaylandTouchSurface
{
MetaWaylandSurface *surface;
MetaWaylandTouch *touch;
struct wl_listener surface_destroy_listener;
struct wl_list resource_list;
gint touch_count;
};
struct _MetaWaylandTouchInfo
{
MetaWaylandTouchSurface *touch_surface;
guint32 slot_serial;
gint32 slot;
gfloat x;
gfloat y;
guint updated : 1;
};
static void
move_resources (struct wl_list *destination, struct wl_list *source)
{
wl_list_insert_list (destination, source);
wl_list_init (source);
}
static void
move_resources_for_client (struct wl_list *destination,
struct wl_list *source,
struct wl_client *client)
{
struct wl_resource *resource, *tmp;
wl_resource_for_each_safe (resource, tmp, source)
{
if (wl_resource_get_client (resource) == client)
{
wl_list_remove (wl_resource_get_link (resource));
wl_list_insert (destination, wl_resource_get_link (resource));
}
}
}
static void
touch_surface_free (gpointer data)
{
MetaWaylandTouchSurface *touch_surface = data;
MetaWaylandTouch *touch = touch_surface->touch;
move_resources (&touch->resource_list,
&touch_surface->resource_list);
wl_list_remove (&touch_surface->surface_destroy_listener.link);
g_free (touch_surface);
}
static MetaWaylandTouchSurface *
touch_surface_increment_touch (MetaWaylandTouchSurface *surface)
{
surface->touch_count++;
return surface;
}
static void
touch_surface_decrement_touch (MetaWaylandTouchSurface *touch_surface)
{
touch_surface->touch_count--;
if (touch_surface->touch_count == 0)
{
/* Now that there are no touches on the surface, free the
* MetaWaylandTouchSurface, the memory is actually owned by
* the touch_surface->touch_surfaces hashtable, so remove the
* item from there.
*/
MetaWaylandTouch *touch = touch_surface->touch;
g_hash_table_remove (touch->touch_surfaces, touch_surface->surface);
}
}
static void
touch_handle_surface_destroy (struct wl_listener *listener, void *data)
{
MetaWaylandTouchSurface *touch_surface = wl_container_of (listener, touch_surface, surface_destroy_listener);
MetaWaylandSurface *surface = touch_surface->surface;
MetaWaylandTouch *touch = touch_surface->touch;
MetaWaylandTouchInfo *touch_info;
GHashTableIter iter;
g_hash_table_iter_init (&iter, touch->touches);
/* Destroy all touches on the surface, this indirectly drops touch_count
* on the touch_surface to 0, also freeing touch_surface and removing
* from the touch_surfaces hashtable.
*/
while (g_hash_table_iter_next (&iter, NULL, (gpointer*) &touch_info))
{
if (touch_info->touch_surface == touch_surface)
g_hash_table_iter_remove (&iter);
}
/* Ensure the surface no longer exists */
g_assert (g_hash_table_remove (touch->touch_surfaces, surface) == FALSE);
}
static MetaWaylandTouchSurface *
touch_surface_get (MetaWaylandTouch *touch,
MetaWaylandSurface *surface)
{
MetaWaylandTouchSurface *touch_surface;
touch_surface = g_hash_table_lookup (touch->touch_surfaces, surface);
if (touch_surface)
return touch_surface_increment_touch (touch_surface);
/* Create a new one for this surface */
touch_surface = g_new0 (MetaWaylandTouchSurface, 1);
touch_surface->touch = touch;
touch_surface->surface = surface;
touch_surface->touch_count = 1;
touch_surface->surface_destroy_listener.notify = touch_handle_surface_destroy;
wl_resource_add_destroy_listener (touch_surface->surface->resource,
&touch_surface->surface_destroy_listener);
wl_list_init (&touch_surface->resource_list);
move_resources_for_client (&touch_surface->resource_list,
&touch->resource_list,
wl_resource_get_client (touch_surface->surface->resource));
g_hash_table_insert (touch->touch_surfaces, surface, touch_surface);
return touch_surface;
}
static MetaWaylandTouchInfo *
touch_get_info (MetaWaylandTouch *touch,
ClutterEventSequence *sequence,
gboolean create)
{
MetaWaylandTouchInfo *touch_info;
touch_info = g_hash_table_lookup (touch->touches, sequence);
if (!touch_info && create)
{
touch_info = g_new0 (MetaWaylandTouchInfo, 1);
touch_info->slot = clutter_evdev_event_sequence_get_slot (sequence);
g_hash_table_insert (touch->touches, sequence, touch_info);
}
return touch_info;
}
static void
touch_get_relative_coordinates (MetaWaylandTouch *touch,
MetaWaylandSurface *surface,
const ClutterEvent *event,
gfloat *x,
gfloat *y)
{
gfloat event_x, event_y;
clutter_event_get_coords (event, &event_x, &event_y);
if (surface->surface_actor)
{
clutter_actor_transform_stage_point (CLUTTER_ACTOR (surface->surface_actor),
event_x, event_y,
&event_x, &event_y);
}
*x = event_x;
*y = event_y;
}
void
meta_wayland_touch_update (MetaWaylandTouch *touch,
const ClutterEvent *event)
{
MetaWaylandTouchInfo *touch_info;
ClutterEventSequence *sequence;
sequence = clutter_event_get_event_sequence (event);
if (event->type == CLUTTER_TOUCH_BEGIN)
{
MetaWaylandSurface *surface = NULL;
ClutterActor *actor;
actor = clutter_event_get_source (event);
if (META_IS_SURFACE_ACTOR_WAYLAND (actor))
surface = meta_surface_actor_wayland_get_surface (META_SURFACE_ACTOR_WAYLAND (actor));
if (!surface)
return;
touch_info = touch_get_info (touch, sequence, TRUE);
touch_info->touch_surface = touch_surface_get (touch, surface);
}
else
touch_info = touch_get_info (touch, sequence, FALSE);
if (!touch_info)
return;
if (event->type == CLUTTER_TOUCH_BEGIN ||
event->type == CLUTTER_TOUCH_END)
{
MetaWaylandSurface *surface = touch_info->touch_surface->surface;
struct wl_client *client = wl_resource_get_client (surface->resource);
struct wl_display *display = wl_client_get_display (client);
touch_info->slot_serial = wl_display_next_serial (display);
}
touch_get_relative_coordinates (touch, touch_info->touch_surface->surface,
event, &touch_info->x, &touch_info->y);
touch_info->updated = TRUE;
}
static void
handle_touch_begin (MetaWaylandTouch *touch,
const ClutterEvent *event)
{
MetaWaylandTouchInfo *touch_info;
ClutterEventSequence *sequence;
struct wl_resource *resource;
struct wl_list *l;
sequence = clutter_event_get_event_sequence (event);
touch_info = touch_get_info (touch, sequence, FALSE);
if (!touch_info)
return;
l = &touch_info->touch_surface->resource_list;
wl_resource_for_each(resource, l)
{
wl_touch_send_down (resource, touch_info->slot_serial,
clutter_event_get_time (event),
touch_info->touch_surface->surface->resource,
touch_info->slot,
wl_fixed_from_double (touch_info->x),
wl_fixed_from_double (touch_info->y));
}
}
static void
handle_touch_update (MetaWaylandTouch *touch,
const ClutterEvent *event)
{
MetaWaylandTouchInfo *touch_info;
ClutterEventSequence *sequence;
struct wl_resource *resource;
struct wl_list *l;
sequence = clutter_event_get_event_sequence (event);
touch_info = touch_get_info (touch, sequence, FALSE);
if (!touch_info)
return;
l = &touch_info->touch_surface->resource_list;
wl_resource_for_each(resource, l)
{
wl_touch_send_motion (resource,
clutter_event_get_time (event),
touch_info->slot,
wl_fixed_from_double (touch_info->x),
wl_fixed_from_double (touch_info->y));
}
}
static void
handle_touch_end (MetaWaylandTouch *touch,
const ClutterEvent *event)
{
MetaWaylandTouchInfo *touch_info;
ClutterEventSequence *sequence;
struct wl_resource *resource;
struct wl_list *l;
sequence = clutter_event_get_event_sequence (event);
touch_info = touch_get_info (touch, sequence, FALSE);
if (!touch_info)
return;
l = &touch_info->touch_surface->resource_list;
wl_resource_for_each(resource, l)
{
wl_touch_send_up (resource, touch_info->slot_serial,
clutter_event_get_time (event),
touch_info->slot);
}
g_hash_table_remove (touch->touches, sequence);
}
static GList *
touch_get_surfaces (MetaWaylandTouch *touch,
gboolean only_updated)
{
MetaWaylandTouchInfo *touch_info;
GList *surfaces = NULL;
GHashTableIter iter;
g_hash_table_iter_init (&iter, touch->touches);
while (g_hash_table_iter_next (&iter, NULL, (gpointer*) &touch_info))
{
if (only_updated && !touch_info->updated)
continue;
if (g_list_find (surfaces, touch_info->touch_surface))
continue;
surfaces = g_list_prepend (surfaces, touch_info->touch_surface);
touch_info->updated = FALSE;
}
return g_list_reverse (surfaces);
}
static void
touch_send_frame_event (MetaWaylandTouch *touch)
{
GList *surfaces, *s;
surfaces = s = touch_get_surfaces (touch, TRUE);
for (s = surfaces; s; s = s->next)
{
MetaWaylandTouchSurface *touch_surface = s->data;
struct wl_resource *resource;
struct wl_list *l;
l = &touch_surface->resource_list;
wl_resource_for_each(resource, l)
{
wl_touch_send_frame (resource);
}
}
g_list_free (surfaces);
}
static void
check_send_frame_event (MetaWaylandTouch *touch,
const ClutterEvent *event)
{
ClutterEventSequence *sequence;
gint32 slot;
sequence = clutter_event_get_event_sequence (event);
slot = clutter_evdev_event_sequence_get_slot (sequence);
touch->frame_slots &= ~(1 << slot);
if (touch->frame_slots == 0)
touch_send_frame_event (touch);
}
gboolean
meta_wayland_touch_handle_event (MetaWaylandTouch *touch,
const ClutterEvent *event)
{
switch (event->type)
{
case CLUTTER_TOUCH_BEGIN:
handle_touch_begin (touch, event);
break;
case CLUTTER_TOUCH_UPDATE:
handle_touch_update (touch, event);
break;
case CLUTTER_TOUCH_END:
handle_touch_end (touch, event);
break;
default:
return FALSE;
}
check_send_frame_event (touch, event);
return FALSE;
}
static void
unbind_resource (struct wl_resource *resource)
{
wl_list_remove (wl_resource_get_link (resource));
}
static void
touch_release (struct wl_client *client,
struct wl_resource *resource)
{
wl_resource_destroy (resource);
}
static const struct wl_touch_interface touch_interface = {
touch_release,
};
static void
touch_info_free (MetaWaylandTouchInfo *touch_info)
{
touch_surface_decrement_touch (touch_info->touch_surface);
g_free (touch_info);
}
static void
touch_handle_cancel_event (MetaWaylandTouch *touch,
struct libinput_event *event)
{
GList *surfaces, *s;
surfaces = s = touch_get_surfaces (touch, FALSE);
while (s)
{
MetaWaylandTouchSurface *touch_surface = s->data;
struct wl_resource *resource;
struct wl_list *l;
l = &touch_surface->resource_list;
wl_resource_for_each(resource, l)
wl_touch_send_cancel (resource);
}
g_hash_table_remove_all (touch->touches);
g_list_free (surfaces);
}
static gboolean
evdev_filter_func (struct libinput_event *event,
gpointer data)
{
MetaWaylandTouch *touch = data;
switch (libinput_event_get_type (event))
{
case LIBINPUT_EVENT_TOUCH_DOWN:
case LIBINPUT_EVENT_TOUCH_UP:
case LIBINPUT_EVENT_TOUCH_MOTION: {
struct libinput_event_touch *touch_event;
int32_t slot;
touch_event = libinput_event_get_touch_event (event);
slot = libinput_event_touch_get_slot (touch_event);
/* XXX: Could theoretically overflow, 64 slots should be
* enough for most hw/usecases though.
*/
touch->frame_slots |= (1 << slot);
break;
}
case LIBINPUT_EVENT_TOUCH_CANCEL:
/* Clutter translates this into individual CLUTTER_TOUCH_CANCEL events,
* which are not so useful when sending a global signal as the protocol
* requires.
*/
touch_handle_cancel_event (touch, event);
break;
default:
break;
}
return CLUTTER_EVENT_PROPAGATE;
}
void
meta_wayland_touch_init (MetaWaylandTouch *touch,
struct wl_display *display)
{
ClutterDeviceManager *manager;
memset (touch, 0, sizeof *touch);
touch->display = display;
touch->touch_surfaces = g_hash_table_new_full (NULL, NULL, NULL,
(GDestroyNotify) touch_surface_free);
touch->touches = g_hash_table_new_full (NULL, NULL, NULL,
(GDestroyNotify) touch_info_free);
wl_list_init (&touch->resource_list);
manager = clutter_device_manager_get_default ();
touch->device = clutter_device_manager_get_core_device (manager, CLUTTER_TOUCHSCREEN_DEVICE);
clutter_evdev_add_filter (evdev_filter_func, touch, NULL);
}
void
meta_wayland_touch_release (MetaWaylandTouch *touch)
{
clutter_evdev_remove_filter (evdev_filter_func, touch);
g_hash_table_unref (touch->touch_surfaces);
g_hash_table_unref (touch->touches);
}
void
meta_wayland_touch_create_new_resource (MetaWaylandTouch *touch,
struct wl_client *client,
struct wl_resource *seat_resource,
uint32_t id)
{
struct wl_resource *cr;
cr = wl_resource_create (client, &wl_touch_interface,
MIN (META_WL_TOUCH_VERSION, wl_resource_get_version (seat_resource)), id);
wl_resource_set_implementation (cr, NULL, touch, unbind_resource);
wl_list_insert (&touch->resource_list, wl_resource_get_link (cr));
}

View File

@@ -0,0 +1,62 @@
/*
* Wayland Support
*
* Copyright (C) 2014 Red Hat
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#ifndef META_WAYLAND_TOUCH_H
#define META_WAYLAND_TOUCH_H
#include <wayland-server.h>
#include <glib.h>
#include "meta-wayland-types.h"
typedef struct _MetaWaylandTouchSurface MetaWaylandTouchSurface;
typedef struct _MetaWaylandTouchInfo MetaWaylandTouchInfo;
struct _MetaWaylandTouch
{
struct wl_display *display;
struct wl_list resource_list;
GHashTable *touch_surfaces; /* HT of MetaWaylandSurface->MetaWaylandTouchSurface */
GHashTable *touches; /* HT of sequence->MetaWaylandTouchInfo */
ClutterInputDevice *device;
guint64 frame_slots;
};
void meta_wayland_touch_init (MetaWaylandTouch *touch,
struct wl_display *display);
void meta_wayland_touch_release (MetaWaylandTouch *touch);
void meta_wayland_touch_update (MetaWaylandTouch *touch,
const ClutterEvent *event);
gboolean meta_wayland_touch_handle_event (MetaWaylandTouch *touch,
const ClutterEvent *event);
void meta_wayland_touch_create_new_resource (MetaWaylandTouch *touch,
struct wl_client *client,
struct wl_resource *seat_resource,
uint32_t id);
#endif /* META_WAYLAND_TOUCH_H */

View File

@@ -29,6 +29,7 @@ typedef struct _MetaWaylandPointerGrabInterface MetaWaylandPointerGrabInterface;
typedef struct _MetaWaylandKeyboard MetaWaylandKeyboard;
typedef struct _MetaWaylandDataOffer MetaWaylandDataOffer;
typedef struct _MetaWaylandDataSource MetaWaylandDataSource;
typedef struct _MetaWaylandTouch MetaWaylandTouch;
typedef struct _MetaWaylandBuffer MetaWaylandBuffer;
typedef struct _MetaWaylandBufferReference MetaWaylandBufferReference;

View File

@@ -51,7 +51,7 @@
#define META_WL_SURFACE_VERSION 3 /* from wl_compositor */
#define META_WL_POINTER_VERSION 3 /* from wl_seat */
#define META_WL_KEYBOARD_VERSION 3 /* from wl_seat */
#define META_WL_TOUCH_VERSION 0 /* from wl_seat; wl_touch not supported */
#define META_WL_TOUCH_VERSION 3 /* from wl_seat */
#define META_WL_REGION_VERSION 1 /* from wl_compositor */
#define META_XDG_SURFACE_VERSION 1 /* from xdg_shell */
#define META_XDG_POPUP_VERSION 1 /* from xdg_shell */

View File

@@ -361,6 +361,8 @@ meta_window_wayland_move_resize (MetaWindow *window,
rect.width = width;
rect.height = height;
window->buffer_rect = rect;
if (rect.width != window->rect.width || rect.height != window->rect.height)
flags |= META_IS_RESIZE_ACTION;

1821
src/x11/events.c Normal file

File diff suppressed because it is too large Load Diff

31
src/x11/events.h Normal file
View File

@@ -0,0 +1,31 @@
/* -*- 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_X11_H
#define META_EVENTS_X11_H
void meta_display_init_events_x11 (MetaDisplay *display);
void meta_display_free_events_x11 (MetaDisplay *display);
#endif

View File

@@ -20,11 +20,12 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "window-private.h"
#ifndef META_WINDOW_X11_PRIVATE_H
#define META_WINDOW_X11_PRIVATE_H
#include "window-private.h"
#include "ui/resizepopup.h"
G_BEGIN_DECLS
typedef struct _MetaWindowX11Private MetaWindowX11Private;

View File

@@ -204,6 +204,8 @@ send_configure_notify (MetaWindow *window)
MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
XEvent event;
g_assert (!window->override_redirect);
/* from twm */
event.type = ConfigureNotify;
@@ -534,11 +536,23 @@ meta_window_x11_manage (MetaWindow *window)
}
}
/* Put our state back where it should be,
* passing TRUE for is_configure_request, ICCCM says
* initial map is handled same as configure request
/* For override-redirect windows, save the client rect
* directly. window->rect was assigned from the XWindowAttributes
* in the main meta_window_shared_new.
*
* For normal windows, do a full ConfigureRequest based on the
* window hints, as that's what the ICCCM says to do.
*/
if (!window->override_redirect)
if (window->override_redirect)
{
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
priv->client_rect = window->rect;
window->buffer_rect = window->rect;
}
else
{
MetaRectangle rect;
MetaMoveResizeFlags flags;
@@ -639,12 +653,6 @@ meta_window_x11_unmanage (MetaWindow *window)
if (META_DISPLAY_HAS_SHAPE (window->display))
XShapeSelectInput (window->display->xdisplay, window->xwindow, NoEventMask);
/* The XReparentWindow call in meta_window_destroy_frame() moves the
* window so we need to send a configure notify; see bug 399552. (We
* also do this just in case a window got unmaximized.)
*/
send_configure_notify (window);
meta_window_ungrab_keys (window);
meta_display_ungrab_window_buttons (window->display, window->xwindow);
meta_display_ungrab_focus_window_button (window->display, window);
@@ -652,7 +660,15 @@ meta_window_x11_unmanage (MetaWindow *window)
meta_error_trap_pop (window->display);
if (window->frame)
meta_window_destroy_frame (window);
{
/* The XReparentWindow call in meta_window_destroy_frame() moves the
* window so we need to send a configure notify; see bug 399552. (We
* also do this just in case a window got unmaximized.)
*/
send_configure_notify (window);
meta_window_destroy_frame (window);
}
}
static void
@@ -913,8 +929,7 @@ sync_request_timeout (gpointer data)
* window updates
*/
window->sync_request_wait_serial = 0;
meta_compositor_set_updates_frozen (window->display->compositor, window,
meta_window_updates_are_frozen (window));
meta_compositor_sync_updates_frozen (window->display->compositor, window);
if (window == window->display->grab_window &&
meta_grab_op_is_resizing (window->display->grab_op))
@@ -977,8 +992,7 @@ send_sync_request (MetaWindow *window)
g_source_set_name_by_id (window->sync_request_timeout_id,
"[mutter] sync_request_timeout");
meta_compositor_set_updates_frozen (window->display->compositor, window,
meta_window_updates_are_frozen (window));
meta_compositor_sync_updates_frozen (window->display->compositor, window);
}
static unsigned long
@@ -1242,6 +1256,11 @@ meta_window_x11_move_resize_internal (MetaWindow *window,
gravity,
need_move_frame, need_resize_frame);
if (window->frame)
window->buffer_rect = window->frame->rect;
else
window->buffer_rect = client_rect;
if (need_configure_notify)
send_configure_notify (window);
@@ -2092,13 +2111,39 @@ meta_window_move_resize_request (MetaWindow *window,
if (flags & (META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION))
{
MetaRectangle rect;
MetaRectangle rect, monitor_rect;
rect.x = x;
rect.y = y;
rect.width = width;
rect.height = height;
meta_screen_get_monitor_geometry (window->screen, window->monitor->number, &monitor_rect);
/* Workaround braindead legacy apps that don't know how to
* fullscreen themselves properly - don't get fooled by
* windows which hide their titlebar when maximized or which are
* client decorated; that's not the same as fullscreen, even
* if there are no struts making the workarea smaller than
* the monitor.
*/
if (meta_prefs_get_force_fullscreen() &&
!window->hide_titlebar_when_maximized &&
(window->decorated || !meta_window_is_client_decorated (window)) &&
meta_rectangle_equal (&rect, &monitor_rect) &&
window->has_fullscreen_func &&
!window->fullscreen)
{
/*
meta_topic (META_DEBUG_GEOMETRY,
*/
meta_warning (
"Treating resize request of legacy application %s as a "
"fullscreen request\n",
window->desc);
meta_window_make_fullscreen_internal (window);
}
adjust_for_gravity (window, TRUE, gravity, &rect);
meta_window_client_rect_to_frame_rect (window, &rect, &rect);
meta_window_move_resize_internal (window, flags, gravity, rect);
@@ -3167,7 +3212,7 @@ meta_window_x11_recalc_window_type (MetaWindow *window)
*/
if (window->override_redirect)
{
switch (window->type)
switch (type)
{
/* Decorated types */
case META_WINDOW_NORMAL:
@@ -3212,6 +3257,9 @@ void
meta_window_x11_configure_notify (MetaWindow *window,
XConfigureEvent *event)
{
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
g_assert (window->override_redirect);
g_assert (window->frame == NULL);
@@ -3219,7 +3267,11 @@ meta_window_x11_configure_notify (MetaWindow *window,
window->rect.y = event->y;
window->rect.width = event->width;
window->rect.height = event->height;
meta_window_update_monitor (window);
priv->client_rect = window->rect;
window->buffer_rect = window->rect;
meta_window_update_monitor (window, FALSE);
/* Whether an override-redirect window is considered fullscreen depends
* on its geometry.
@@ -3401,8 +3453,7 @@ meta_window_x11_update_sync_request_counter (MetaWindow *window,
}
window->sync_request_serial = new_counter_value;
meta_compositor_set_updates_frozen (window->display->compositor, window,
meta_window_updates_are_frozen (window));
meta_compositor_sync_updates_frozen (window->display->compositor, window);
if (window == window->display->grab_window &&
meta_grab_op_is_resizing (window->display->grab_op) &&
@@ -3437,3 +3488,9 @@ meta_window_x11_update_sync_request_counter (MetaWindow *window,
meta_compositor_queue_frame_drawn (window->display->compositor, window,
no_delay_frame);
}
Window
meta_window_x11_get_toplevel_xwindow (MetaWindow *window)
{
return window->frame ? window->frame->xwindow : window->xwindow;
}

View File

@@ -73,4 +73,6 @@ gboolean meta_window_x11_client_message (MetaWindow *window,
void meta_window_x11_configure_notify (MetaWindow *window,
XConfigureEvent *event);
Window meta_window_x11_get_toplevel_xwindow (MetaWindow *window);
#endif