Compare commits

..

5 Commits

Author SHA1 Message Date
Rui Matos
3ac563307e debug output 2014-06-04 10:52:56 +02:00
Rui Matos
24956fadcc MetaSyncRing: disable after a number of reboot attempts
If we have had to reboot this number of times, something is definitely
wrong and we're likely to just make things worse by continuing to try.

Let's err on the side of caution, disable ourselves and fallback to
the XSync() path in the compositor.

https://bugzilla.gnome.org/show_bug.cgi?id=728464
2014-06-02 16:27:28 +02:00
Rui Matos
fc5de438b5 compositor: Add support for GL_EXT_x11_sync_object
If GL advertises this extension we'll use it to synchronize X with GL
rendering instead of relying on the XSync() behavior with open source
drivers.

https://bugzilla.gnome.org/show_bug.cgi?id=728464
2014-06-02 16:27:28 +02:00
Rui Matos
94cee3ef09 display: Add public getters for sync extension presence and event base
https://bugzilla.gnome.org/show_bug.cgi?id=728464
2014-06-02 16:27:28 +02:00
Rui Matos
1e6b042778 compositor: Sync X drawing only once per frame
We only need to call XSync() once per frame to synchronize X with GL
drawing.

https://bugzilla.gnome.org/show_bug.cgi?id=728464
2014-06-02 16:27:28 +02:00
115 changed files with 9255 additions and 9731 deletions

35
.cvsignore Normal file
View File

@@ -0,0 +1,35 @@
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

32
.gitignore vendored
View File

@@ -3,7 +3,6 @@ Makefile.in
Makefile.in.in
aclocal.m4
autom4te.cache
build-aux
compile
config.guess
config.h
@@ -20,11 +19,11 @@ libtool
ltmain.sh
missing
.deps
50-mutter-navigation.xml
50-mutter-system.xml
50-mutter-windows.xml
mutter.desktop
mutter-wayland.desktop
src/50-mutter-navigation.xml
src/50-mutter-system.xml
src/50-mutter-windows.xml
src/mutter.desktop
src/mutter-wayland.desktop
*.o
*.a
*.lo
@@ -33,6 +32,10 @@ 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
@@ -41,9 +44,10 @@ stamp-it
.intltool-merge-cache
POTFILES
po/*.pot
50-metacity-desktop-key.xml
50-metacity-key.xml
libmutter.pc
mutter
mutter-restart-helper
org.gnome.mutter.gschema.valid
org.gnome.mutter.gschema.xml
org.gnome.mutter.wayland.gschema.valid
@@ -52,6 +56,19 @@ testasyncgetprop
testboxes
testgradient
m4/*
mutter-grayscale
mutter-mag
mutter-message
mutter-window-demo
focus-window
test-attached
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]
@@ -67,7 +84,6 @@ 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,13 +1,10 @@
SUBDIRS = data src po doc
SUBDIRS=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}

34
NEWS
View File

@@ -1,37 +1,3 @@
3.13.4
======
* Fix move/resize operations for wayland clients [Marek; #731237]
* Add ::first-frame signal to MetaWindowActor [Owen; #732343]
* Handle keysyms without the XF86 prefix [Owen; #727993]
* Add touch gesture support [Carlos]
* Fix a deadlock when exiting [Owen; #733068]
* Add framework for restarting the compositor with nice visuals
[Owen; #733026]
* Toggle seat capabilities on VT switch [Carlos; #733563]
* Misc bug fixes [Florian, Owen; #732695, #732350]
Contributors:
Tom Beckmann, Giovanni Campagna, Marek Chalupa, Adel Gadllah,
Carlos Garnacho, Florian Müllner, Jasper St. Pierre, Rico Tzschichholz,
Owen W. Taylor
Translations:
Yuri Myasoedov [ru], Fran Diéguez [gl], Aurimas Černius [lt], MarMav [el],
Enrico Nicoletto [pt_BR]
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.11
REQUIRED_AUTOMAKE_VERSION=1.10
(test -f $srcdir/configure.ac \
&& test -d $srcdir/src) || {

View File

@@ -1,8 +1,9 @@
AC_PREREQ(2.62)
AC_PREREQ(2.50)
AC_CONFIG_MACRO_DIR([m4])
m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [13])
m4_define([mutter_micro_version], [4])
m4_define([mutter_micro_version], [2])
m4_define([mutter_version],
[mutter_major_version.mutter_minor_version.mutter_micro_version])
@@ -13,7 +14,6 @@ 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,14 +40,12 @@ GETTEXT_PACKAGE=mutter
AC_SUBST(GETTEXT_PACKAGE)
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[Name of default gettext domain])
LT_PREREQ([2.2.6])
LT_INIT([disable-static])
IT_PROG_INTLTOOL([0.41])
IT_PROG_INTLTOOL([0.34.90])
AC_PROG_CC
AC_PROG_CC_C_O
AC_PROG_INSTALL
AC_ISC_POSIX
AC_HEADER_STDC
PKG_PROG_PKG_CONFIG([0.21])
AC_LIBTOOL_WIN32_DLL
AM_PROG_LIBTOOL
# Sets GLIB_GENMARSHAL and GLIB_MKENUMS
AM_PATH_GLIB_2_0()
@@ -72,19 +70,13 @@ CLUTTER_PACKAGE=clutter-1.0
MUTTER_PC_MODULES="
gtk+-3.0 >= 3.9.11
gio-unix-2.0 >= 2.25.10
gio-2.0 >= 2.25.10
pango >= 1.2.0
cairo >= 1.10.0
gsettings-desktop-schemas >= 3.7.3
xcomposite >= 0.2 xfixes xext xdamage xi >= 1.6.0
xcursor
$CLUTTER_PACKAGE >= 1.19.5
clutter-wayland-1.0
clutter-wayland-compositor-1.0
clutter-egl-1.0
$CLUTTER_PACKAGE >= 1.17.5
cogl-1.0 >= 1.17.1
libinput
wayland-server >= 1.4.93
upower-glib >= 0.99.0
gnome-desktop-3.0
"
@@ -115,12 +107,26 @@ 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"
@@ -185,12 +191,15 @@ 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])
@@ -290,6 +299,17 @@ 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])
@@ -304,6 +324,11 @@ 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
@@ -372,7 +397,6 @@ changequote([,])dnl
AC_CONFIG_FILES([
Makefile
data/Makefile
doc/Makefile
doc/man/Makefile
doc/reference/Makefile
@@ -380,7 +404,6 @@ 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,36 +1,3 @@
desktopfiles_in_files = \
mutter.desktop.in \
mutter-wayland.desktop.in
desktopfilesdir = $(datadir)/applications
desktopfiles_DATA = $(desktopfiles_in_files:.desktop.in=.desktop)
defaultcursordir = $(datadir)/mutter/cursors
@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)
dist_defaultcursor_DATA = left_ptr.png

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_buffer_rect
meta_window_get_input_rect
meta_window_get_frame_rect
meta_window_get_outer_rect
meta_window_client_rect_to_frame_rect

View File

@@ -1,11 +1,8 @@
# List of source files containing translatable strings.
# Please keep this file sorted alphabetically.
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/50-mutter-navigation.xml.in
src/50-mutter-system.xml.in
src/50-mutter-windows.xml.in
src/backends/meta-monitor-manager.c
src/compositor/compositor.c
src/compositor/meta-background.c
@@ -21,6 +18,9 @@ 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 +1,2 @@
data/mutter-wayland.desktop.in
src/metacity.schemas.in
src/mutter-wayland.desktop.in

3456
po/el.po

File diff suppressed because it is too large Load Diff

888
po/gl.po

File diff suppressed because it is too large Load Diff

1010
po/lt.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1291
po/ru.po

File diff suppressed because it is too large Load Diff

View File

@@ -5,37 +5,38 @@ lib_LTLIBRARIES = libmutter.la
SUBDIRS=compositor/plugins
AM_CPPFLAGS = \
INCLUDES= \
-DCLUTTER_ENABLE_COMPOSITOR_API \
-DCLUTTER_ENABLE_EXPERIMENTAL_API \
-DCOGL_ENABLE_EXPERIMENTAL_API \
-DCOGL_ENABLE_EXPERIMENTAL_2_0_API \
-DCLUTTER_DISABLE_DEPRECATION_WARNINGS \
-DCOGL_DISABLE_DEPRECATION_WARNINGS \
$(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)\" \
-DMUTTER_LOCALEDIR=\"$(localedir)\" \
-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_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 \
@@ -117,6 +118,8 @@ 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 \
@@ -154,8 +157,6 @@ libmutter_la_SOURCES = \
core/frame.h \
ui/gradient.c \
meta/gradient.h \
core/meta-gesture-tracker.c \
core/meta-gesture-tracker-private.h \
core/keybindings.c \
core/keybindings-private.h \
core/main.c \
@@ -167,7 +168,6 @@ libmutter_la_SOURCES = \
core/screen-private.h \
meta/screen.h \
meta/types.h \
core/restart.c \
core/stack.c \
core/stack.h \
core/stack-tracker.c \
@@ -196,8 +196,6 @@ 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 \
@@ -227,8 +225,6 @@ 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 \
@@ -262,7 +258,7 @@ libmutter_la_LIBADD = $(MUTTER_LIBS) $(MUTTER_NATIVE_BACKEND_LIBS)
# Headers installed for plugins; introspected information will
# be extracted into Mutter-<version>.gir
libmutterinclude_headers = \
libmutterinclude_base_headers = \
meta/barrier.h \
meta/boxes.h \
meta/common.h \
@@ -291,13 +287,6 @@ libmutterinclude_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 = \
@@ -306,21 +295,14 @@ libmutterinclude_extra_headers = \
libmutterincludedir = $(includedir)/mutter/meta
libmutterinclude_HEADERS = \
$(libmutterinclude_headers) \
$(libmutterinclude_base_headers) \
$(libmutterinclude_extra_headers)
nodist_libmutterinclude_HEADERS = \
$(libmutterinclude_built_headers)
bin_PROGRAMS=mutter
mutter_SOURCES = core/mutter.c
mutter_LDADD = $(MUTTER_LIBS) libmutter.la
libexec_PROGRAMS = mutter-restart-helper
mutter_restart_helper_SOURCES = core/restart-helper.c
mutter_restart_helper_LDADD = $(MUTTER_LIBS)
if HAVE_INTROSPECTION
include $(INTROSPECTION_MAKEFILE)
@@ -344,7 +326,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 = $(AM_CPPFLAGS)
@META_GIR@_CFLAGS = $(INCLUDES)
@META_GIR@_LIBS = libmutter.la
@META_GIR@_FILES = \
mutter-enum-types.h \
@@ -364,19 +346,53 @@ 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 = \
EXTRA_DIST=$(desktopfiles_files) \
$(wmproperties_files) \
$(IMAGES) \
$(desktopfiles_in_files) \
$(wmproperties_in_files) \
$(xml_in_files) \
$(wayland_protocols) \
org.gnome.mutter.gschema.xml.in \
org.gnome.mutter.wayland.gschema.xml.in \
mutter-schemas.convert \
libmutter.pc.in \
mutter-enum-types.h.in \
mutter-enum-types.c.in \

View File

@@ -103,6 +103,14 @@ 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)
{
@@ -114,6 +122,7 @@ 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

@@ -23,6 +23,8 @@
#define META_CURSOR_TRACKER_PRIVATE_H
#include <meta/meta-cursor-tracker.h>
#include <wayland-server.h>
#include <gbm.h>
#include "meta-cursor.h"
#include "meta-cursor-renderer.h"
@@ -30,6 +32,7 @@
struct _MetaCursorTracker {
GObject parent_instance;
MetaScreen *screen;
MetaCursorRenderer *renderer;
gboolean is_showing;

View File

@@ -44,6 +44,9 @@
#include "meta-cursor-private.h"
#include "meta-cursor-tracker-private.h"
#include "screen-private.h"
#include "wayland/meta-wayland-private.h"
G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT);
@@ -57,12 +60,10 @@ static guint signals[LAST_SIGNAL];
static MetaCursorReference *
get_displayed_cursor (MetaCursorTracker *tracker)
{
MetaDisplay *display = meta_get_display ();
if (!tracker->is_showing)
return NULL;
if (display->grab_op == META_GRAB_OP_NONE)
if (tracker->screen->display->grab_op == META_GRAB_OP_NONE)
{
if (tracker->has_window_cursor)
return tracker->window_cursor;
@@ -96,9 +97,6 @@ sync_cursor (MetaCursorTracker *tracker)
static void
meta_cursor_tracker_init (MetaCursorTracker *self)
{
MetaBackend *backend = meta_get_backend ();
self->renderer = meta_backend_get_cursor_renderer (backend);
self->is_showing = TRUE;
}
@@ -131,9 +129,47 @@ meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass)
}
static MetaCursorTracker *
meta_cursor_tracker_new (void)
make_wayland_cursor_tracker (MetaScreen *screen)
{
return g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
MetaBackend *backend = meta_get_backend ();
MetaWaylandCompositor *compositor;
MetaCursorTracker *self;
self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
self->screen = screen;
self->renderer = meta_backend_get_cursor_renderer (backend);
compositor = meta_wayland_compositor_get_default ();
compositor->seat->pointer.cursor_tracker = self;
meta_cursor_tracker_update_position (self, 0, 0);
return self;
}
static MetaCursorTracker *
make_x11_cursor_tracker (MetaScreen *screen)
{
MetaBackend *backend = meta_get_backend ();
MetaCursorTracker *self;
self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
self->screen = screen;
self->renderer = meta_backend_get_cursor_renderer (backend);
XFixesSelectCursorInput (screen->display->xdisplay,
screen->xroot,
XFixesDisplayCursorNotifyMask);
return self;
}
static MetaCursorTracker *
meta_cursor_tracker_new (MetaScreen *screen)
{
if (meta_is_wayland_compositor ())
return make_wayland_cursor_tracker (screen);
else
return make_x11_cursor_tracker (screen);
}
static MetaCursorTracker *_cursor_tracker;
@@ -150,7 +186,7 @@ MetaCursorTracker *
meta_cursor_tracker_get_for_screen (MetaScreen *screen)
{
if (!_cursor_tracker)
_cursor_tracker = meta_cursor_tracker_new ();
_cursor_tracker = meta_cursor_tracker_new (screen);
return _cursor_tracker;
}
@@ -171,13 +207,12 @@ gboolean
meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
XEvent *xevent)
{
MetaDisplay *display = meta_get_display ();
XFixesCursorNotifyEvent *notify_event;
if (meta_is_wayland_compositor ())
return FALSE;
if (xevent->xany.type != display->xfixes_event_base + XFixesCursorNotify)
if (xevent->xany.type != tracker->screen->display->xfixes_event_base + XFixesCursorNotify)
return FALSE;
notify_event = (XFixesCursorNotifyEvent *)xevent;
@@ -208,7 +243,6 @@ meta_cursor_reference_take_texture (CoglTexture2D *texture,
static void
ensure_xfixes_cursor (MetaCursorTracker *tracker)
{
MetaDisplay *display = meta_get_display ();
XFixesCursorImage *cursor_image;
CoglTexture2D *sprite;
guint8 *cursor_data;
@@ -218,7 +252,7 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
if (tracker->xfixes_cursor)
return;
cursor_image = XFixesGetCursorImage (display->xdisplay);
cursor_image = XFixesGetCursorImage (tracker->screen->display->xdisplay);
if (!cursor_image)
return;

View File

@@ -60,7 +60,7 @@ typedef struct {
gboolean enabled;
MetaRectangle rect;
float refresh_rate;
MetaMonitorTransform transform;
enum wl_output_transform transform;
gboolean is_primary;
gboolean is_presentation;
@@ -656,20 +656,20 @@ handle_text (GMarkupParseContext *context,
else if (strcmp (parser->output_field, "rotation") == 0)
{
if (strncmp (text, "normal", text_len) == 0)
parser->output.transform = META_MONITOR_TRANSFORM_NORMAL;
parser->output.transform = WL_OUTPUT_TRANSFORM_NORMAL;
else if (strncmp (text, "left", text_len) == 0)
parser->output.transform = META_MONITOR_TRANSFORM_90;
parser->output.transform = WL_OUTPUT_TRANSFORM_90;
else if (strncmp (text, "upside_down", text_len) == 0)
parser->output.transform = META_MONITOR_TRANSFORM_180;
parser->output.transform = WL_OUTPUT_TRANSFORM_180;
else if (strncmp (text, "right", text_len) == 0)
parser->output.transform = META_MONITOR_TRANSFORM_270;
parser->output.transform = WL_OUTPUT_TRANSFORM_270;
else
g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
"Invalid rotation type %.*s", (int)text_len, text);
}
else if (strcmp (parser->output_field, "reflect_x") == 0)
parser->output.transform += read_bool (text, text_len, error) ?
META_MONITOR_TRANSFORM_FLIPPED : 0;
WL_OUTPUT_TRANSFORM_FLIPPED : 0;
else if (strcmp (parser->output_field, "reflect_y") == 0)
{
/* FIXME (look at the rotation map in monitor.c) */
@@ -1115,7 +1115,7 @@ make_default_config (MetaMonitorConfig *self,
ret->outputs[0].rect.width = outputs[0].preferred_mode->width;
ret->outputs[0].rect.height = outputs[0].preferred_mode->height;
ret->outputs[0].refresh_rate = outputs[0].preferred_mode->refresh_rate;
ret->outputs[0].transform = META_MONITOR_TRANSFORM_NORMAL;
ret->outputs[0].transform = WL_OUTPUT_TRANSFORM_NORMAL;
ret->outputs[0].is_primary = TRUE;
return ret;
@@ -1167,7 +1167,7 @@ make_default_config (MetaMonitorConfig *self,
ret->outputs[j].rect.width = outputs[0].preferred_mode->width;
ret->outputs[j].rect.height = outputs[0].preferred_mode->height;
ret->outputs[j].refresh_rate = outputs[0].preferred_mode->refresh_rate;
ret->outputs[j].transform = META_MONITOR_TRANSFORM_NORMAL;
ret->outputs[j].transform = WL_OUTPUT_TRANSFORM_NORMAL;
ret->outputs[j].is_primary = FALSE;
ret->outputs[j].is_presentation = FALSE;
}
@@ -1202,7 +1202,7 @@ make_default_config (MetaMonitorConfig *self,
ret->outputs[i].rect.width = output->preferred_mode->width;
ret->outputs[i].rect.height = output->preferred_mode->height;
ret->outputs[i].refresh_rate = output->preferred_mode->refresh_rate;
ret->outputs[i].transform = META_MONITOR_TRANSFORM_NORMAL;
ret->outputs[i].transform = WL_OUTPUT_TRANSFORM_NORMAL;
ret->outputs[i].is_primary = (output == primary);
/* Disable outputs that would go beyond framebuffer limits */
@@ -1250,7 +1250,7 @@ ensure_at_least_one_output (MetaMonitorConfig *self,
ret->outputs[i].rect.width = output->preferred_mode->width;
ret->outputs[i].rect.height = output->preferred_mode->height;
ret->outputs[i].refresh_rate = output->preferred_mode->refresh_rate;
ret->outputs[i].transform = META_MONITOR_TRANSFORM_NORMAL;
ret->outputs[i].transform = WL_OUTPUT_TRANSFORM_NORMAL;
ret->outputs[i].is_primary = TRUE;
}
else
@@ -1512,7 +1512,7 @@ meta_monitor_config_save (MetaMonitorConfig *self)
output->rect.x,
output->rect.y,
rotation_map[output->transform & 0x3],
output->transform >= META_MONITOR_TRANSFORM_FLIPPED ? "yes" : "no",
output->transform >= WL_OUTPUT_TRANSFORM_FLIPPED ? "yes" : "no",
output->is_primary ? "yes" : "no",
output->is_presentation ? "yes" : "no");
}
@@ -1621,13 +1621,13 @@ output_supports_mode (MetaOutput *output,
}
static gboolean
crtc_assignment_assign (CrtcAssignment *assign,
MetaCRTC *crtc,
MetaMonitorMode *mode,
int x,
int y,
MetaMonitorTransform transform,
MetaOutput *output)
crtc_assignment_assign (CrtcAssignment *assign,
MetaCRTC *crtc,
MetaMonitorMode *mode,
int x,
int y,
enum wl_output_transform transform,
MetaOutput *output)
{
MetaCRTCInfo *info = g_hash_table_lookup (assign->info, crtc);

View File

@@ -27,7 +27,7 @@
#include "meta-monitor-manager-dummy.h"
#define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1)
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
struct _MetaMonitorManagerDummy
{
@@ -66,8 +66,8 @@ meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
manager->crtcs[0].rect.width = manager->modes[0].width;
manager->crtcs[0].rect.height = manager->modes[0].height;
manager->crtcs[0].current_mode = &manager->modes[0];
manager->crtcs[0].transform = META_MONITOR_TRANSFORM_NORMAL;
manager->crtcs[0].all_transforms = ALL_TRANSFORMS;
manager->crtcs[0].transform = WL_OUTPUT_TRANSFORM_NORMAL;
manager->crtcs[0].all_transforms = ALL_WL_TRANSFORMS;
manager->crtcs[0].is_dirty = FALSE;
manager->crtcs[0].logical_monitor = NULL;
@@ -75,7 +75,7 @@ meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
manager->n_outputs = 1;
manager->outputs[0].crtc = &manager->crtcs[0];
manager->outputs[0].winsys_id = 1;
manager->outputs[0].output_id = 1;
manager->outputs[0].name = g_strdup ("LVDS");
manager->outputs[0].vendor = g_strdup ("MetaProducts Inc.");
manager->outputs[0].product = g_strdup ("unknown");

View File

@@ -125,7 +125,7 @@ make_logical_config (MetaMonitorManager *manager)
*/
info.is_presentation = TRUE;
info.in_fullscreen = -1;
info.winsys_id = 0;
info.output_id = 0;
g_array_append_val (monitor_infos, info);
@@ -156,8 +156,8 @@ make_logical_config (MetaMonitorManager *manager)
info->is_primary = info->is_primary || output->is_primary;
info->is_presentation = info->is_presentation && output->is_presentation;
if (output->is_primary || info->winsys_id == 0)
info->winsys_id = output->winsys_id;
if (output->is_primary || info->output_id == 0)
info->output_id = output->output_id;
if (info->is_primary)
manager->primary_monitor_index = info->number;
@@ -477,7 +477,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
GVariantBuilder transforms;
g_variant_builder_init (&transforms, G_VARIANT_TYPE ("au"));
for (j = 0; j <= META_MONITOR_TRANSFORM_FLIPPED_270; j++)
for (j = 0; j <= WL_OUTPUT_TRANSFORM_FLIPPED_270; j++)
if (crtc->all_transforms & (1 << j))
g_variant_builder_add (&transforms, "u", j);
@@ -560,7 +560,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
g_variant_builder_add (&output_builder, "(uxiausauaua{sv})",
i, /* ID */
(gint64)output->winsys_id,
(gint64)output->output_id,
(int)(output->crtc ? output->crtc - manager->crtcs : -1),
&crtcs,
output->name,
@@ -667,7 +667,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
int new_mode, x, y;
int new_screen_width, new_screen_height;
guint transform;
guint output_index;
guint output_id;
GPtrArray *crtc_infos, *output_infos;
if (serial != manager->serial)
@@ -694,6 +694,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
MetaOutput *first_output;
MetaCRTC *crtc;
MetaMonitorMode *mode;
guint output_id;
crtc_info = g_slice_new (MetaCRTCInfo);
crtc_info->outputs = g_ptr_array_new ();
@@ -755,8 +756,8 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
crtc_info->y = 0;
}
if (transform < META_MONITOR_TRANSFORM_NORMAL ||
transform > META_MONITOR_TRANSFORM_FLIPPED_270 ||
if (transform < WL_OUTPUT_TRANSFORM_NORMAL ||
transform > WL_OUTPUT_TRANSFORM_FLIPPED_270 ||
((crtc->all_transforms & (1 << transform)) == 0))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
@@ -767,18 +768,18 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
crtc_info->transform = transform;
first_output = NULL;
while (g_variant_iter_loop (nested_outputs, "u", &output_index))
while (g_variant_iter_loop (nested_outputs, "u", &output_id))
{
MetaOutput *output;
if (output_index >= manager->n_outputs)
if (output_id >= manager->n_outputs)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_INVALID_ARGS,
"Invalid output id");
return TRUE;
}
output = &manager->outputs[output_index];
output = &manager->outputs[output_id];
if (!output_can_config (output, crtc, mode))
{
@@ -823,12 +824,12 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
}
g_variant_iter_init (&output_iter, outputs);
while (g_variant_iter_loop (&output_iter, "(u@a{sv})", &output_index, &properties))
while (g_variant_iter_loop (&output_iter, "(u@a{sv})", &output_id, &properties))
{
MetaOutputInfo *output_info;
gboolean primary, presentation;
if (output_index >= manager->n_outputs)
if (output_id >= manager->n_outputs)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_INVALID_ARGS,
@@ -837,7 +838,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
}
output_info = g_slice_new0 (MetaOutputInfo);
output_info->output = &manager->outputs[output_index];
output_info->output = &manager->outputs[output_id];
if (g_variant_lookup (properties, "primary", "b", &primary))
output_info->is_primary = primary;
@@ -908,7 +909,7 @@ static gboolean
meta_monitor_manager_handle_change_backlight (MetaDBusDisplayConfig *skeleton,
GDBusMethodInvocation *invocation,
guint serial,
guint output_index,
guint output_id,
gint value)
{
MetaMonitorManager *manager = META_MONITOR_MANAGER (skeleton);
@@ -922,14 +923,14 @@ meta_monitor_manager_handle_change_backlight (MetaDBusDisplayConfig *skeleton,
return TRUE;
}
if (output_index >= manager->n_outputs)
if (output_id >= manager->n_outputs)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_INVALID_ARGS,
"Invalid output id");
return TRUE;
}
output = &manager->outputs[output_index];
output = &manager->outputs[output_id];
if (value < 0 || value > 100)
{

View File

@@ -42,6 +42,7 @@
#include <meta/screen.h>
#include "stack-tracker.h"
#include "ui.h"
#include <wayland-server.h>
#include "meta-display-config-shared.h"
#include "meta-dbus-display-config.h"
@@ -59,23 +60,12 @@ typedef struct _MetaMonitorInfo MetaMonitorInfo;
typedef struct _MetaCRTCInfo MetaCRTCInfo;
typedef struct _MetaOutputInfo MetaOutputInfo;
typedef enum {
META_MONITOR_TRANSFORM_NORMAL,
META_MONITOR_TRANSFORM_90,
META_MONITOR_TRANSFORM_180,
META_MONITOR_TRANSFORM_270,
META_MONITOR_TRANSFORM_FLIPPED,
META_MONITOR_TRANSFORM_FLIPPED_90,
META_MONITOR_TRANSFORM_FLIPPED_180,
META_MONITOR_TRANSFORM_FLIPPED_270,
} MetaMonitorTransform;
struct _MetaOutput
{
/* The CRTC driving this output, NULL if the output is not enabled */
MetaCRTC *crtc;
/* The low-level ID of this output, used to apply back configuration */
glong winsys_id;
glong output_id;
char *name;
char *vendor;
char *product;
@@ -124,7 +114,7 @@ struct _MetaCRTC
glong crtc_id;
MetaRectangle rect;
MetaMonitorMode *current_mode;
MetaMonitorTransform transform;
enum wl_output_transform transform;
unsigned int all_transforms;
/* Only used to build the logical configuration
@@ -172,14 +162,14 @@ struct _MetaMonitorInfo
gboolean in_fullscreen;
/* The primary or first output for this monitor, 0 if we can't figure out.
It can be matched to a winsys_id of a MetaOutput.
It can be matched to an output_id of a MetaOutput.
This is used as an opaque token on reconfiguration when switching from
clone to extened, to decide on what output the windows should go next
(it's an attempt to keep windows on the same monitor, and preferably on
the primary one).
*/
glong winsys_id;
glong output_id;
};
/*
@@ -195,7 +185,7 @@ struct _MetaCRTCInfo {
MetaMonitorMode *mode;
int x;
int y;
MetaMonitorTransform transform;
enum wl_output_transform transform;
GPtrArray *outputs;
};
@@ -349,7 +339,7 @@ gboolean meta_monitor_manager_has_hotplug_mode_update (MetaMonitorMana
/* Returns true if transform causes width and height to be inverted
This is true for the odd transforms in the enum */
static inline gboolean
meta_monitor_transform_is_rotated (MetaMonitorTransform transform)
meta_monitor_transform_is_rotated (enum wl_output_transform transform)
{
return (transform % 2);
}

View File

@@ -174,20 +174,6 @@ 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)
{
@@ -197,8 +183,6 @@ 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

@@ -40,6 +40,8 @@
#include <meta/errors.h>
#include "edid.h"
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
typedef struct {
drmModeConnector *connector;
@@ -257,7 +259,7 @@ find_output_by_id (MetaOutput *outputs,
unsigned i;
for (i = 0; i < n_outputs; i++)
if (outputs[i].winsys_id == id)
if (outputs[i].output_id == id)
return &outputs[i];
return NULL;
@@ -361,9 +363,9 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
meta_crtc->rect.width = crtc->width;
meta_crtc->rect.height = crtc->height;
meta_crtc->is_dirty = FALSE;
meta_crtc->transform = META_MONITOR_TRANSFORM_NORMAL;
meta_crtc->transform = WL_OUTPUT_TRANSFORM_NORMAL;
/* FIXME: implement! */
meta_crtc->all_transforms = 1 << META_MONITOR_TRANSFORM_NORMAL;
meta_crtc->all_transforms = 1 << WL_OUTPUT_TRANSFORM_NORMAL;
if (crtc->mode_valid)
{
@@ -406,7 +408,7 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
meta_output->driver_private = output_kms = g_slice_new0 (MetaOutputKms);
meta_output->driver_notify = (GDestroyNotify)meta_output_destroy_notify;
meta_output->winsys_id = connector->connector_id;
meta_output->output_id = connector->connector_id;
meta_output->name = make_output_name (connector);
meta_output->width_mm = connector->mmWidth;
meta_output->height_mm = connector->mmHeight;
@@ -489,7 +491,7 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
meta_output->crtc = NULL;
old_output = find_output_by_id (old_outputs, n_old_outputs,
meta_output->winsys_id);
meta_output->output_id);
if (old_output)
{
meta_output->is_primary = old_output->is_primary;
@@ -665,7 +667,7 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
if (output_kms->dpms_prop_id != 0)
{
int ok = drmModeConnectorSetProperty(manager_kms->fd, meta_output->winsys_id,
int ok = drmModeConnectorSetProperty(manager_kms->fd, meta_output->output_id,
output_kms->dpms_prop_id, state);
if (ok < 0)
@@ -746,7 +748,7 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
{
MetaOutput *output = g_ptr_array_index (crtc_info->outputs, j);
connectors[j] = output->winsys_id;
connectors[j] = output->output_id;
output->is_dirty = TRUE;
output->crtc = crtc;

View File

@@ -51,7 +51,6 @@ struct _MetaBackendX11Private
int xinput_opcode;
int xinput_event_base;
int xinput_error_base;
Time latest_evtime;
};
typedef struct _MetaBackendX11Private MetaBackendX11Private;
@@ -72,7 +71,6 @@ static void
translate_device_event (MetaBackendX11 *x11,
XIDeviceEvent *device_event)
{
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
Window stage_window = meta_backend_x11_get_xwindow (x11);
if (device_event->event != stage_window)
@@ -90,21 +88,6 @@ translate_device_event (MetaBackendX11 *x11,
device_event->event_x = device_event->root_x;
device_event->event_y = device_event->root_y;
}
if (!device_event->send_event && device_event->time != CurrentTime)
{
if (device_event->time < priv->latest_evtime)
{
/* Emulated pointer events received after XIRejectTouch is received
* on a passive touch grab will contain older timestamps, update those
* so we dont get InvalidTime at grabs.
*/
device_event->time = priv->latest_evtime;
}
/* Update the internal latest evtime, for any possible later use */
priv->latest_evtime = device_event->time;
}
}
/* Clutter makes the assumption that there is only one X window
@@ -134,9 +117,6 @@ maybe_spoof_event_as_stage_event (MetaBackendX11 *x11,
case XI_ButtonRelease:
case XI_KeyPress:
case XI_KeyRelease:
case XI_TouchBegin:
case XI_TouchUpdate:
case XI_TouchEnd:
translate_device_event (x11, (XIDeviceEvent *) input_event);
break;
default:
@@ -151,15 +131,10 @@ handle_host_xevent (MetaBackend *backend,
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
MetaDisplay *display = meta_get_display ();
MetaCompositor *compositor = display->compositor;
gboolean bypass_clutter = FALSE;
XGetEventData (priv->xdisplay, &event->xcookie);
if (meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event))
bypass_clutter = TRUE;
if (event->type == (priv->xsync_event_base + XSyncAlarmNotify))
handle_alarm_notify (backend, event);
@@ -167,14 +142,17 @@ handle_host_xevent (MetaBackend *backend,
MetaMonitorManager *manager = meta_backend_get_monitor_manager (backend);
if (META_IS_MONITOR_MANAGER_XRANDR (manager) &&
meta_monitor_manager_xrandr_handle_xevent (META_MONITOR_MANAGER_XRANDR (manager), event))
bypass_clutter = TRUE;
{
bypass_clutter = TRUE;
goto out;
}
}
maybe_spoof_event_as_stage_event (x11, event);
out:
if (!bypass_clutter)
{
maybe_spoof_event_as_stage_event (x11, event);
clutter_x11_handle_event (event);
}
clutter_x11_handle_event (event);
XFreeEventData (priv->xdisplay, &event->xcookie);
}
@@ -257,24 +235,6 @@ x_event_source_new (MetaBackend *backend)
return source;
}
static void
take_touch_grab (MetaBackend *backend)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { META_VIRTUAL_CORE_POINTER_ID, sizeof (mask_bits), mask_bits };
XIGrabModifiers mods = { XIAnyModifier, 0 };
XISetMask (mask.mask, XI_TouchBegin);
XISetMask (mask.mask, XI_TouchUpdate);
XISetMask (mask.mask, XI_TouchEnd);
XIGrabTouchBegin (priv->xdisplay, META_VIRTUAL_CORE_POINTER_ID,
DefaultRootWindow (priv->xdisplay),
False, &mask, 1, &mods);
}
static void
meta_backend_x11_post_init (MetaBackend *backend)
{
@@ -312,8 +272,6 @@ meta_backend_x11_post_init (MetaBackend *backend)
meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer\n");
}
take_touch_grab (backend);
META_BACKEND_CLASS (meta_backend_x11_parent_class)->post_init (backend);
}
@@ -355,9 +313,6 @@ meta_backend_x11_grab_device (MetaBackend *backend,
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
int ret;
if (timestamp != CurrentTime)
timestamp = MAX (timestamp, priv->latest_evtime);
XISetMask (mask.mask, XI_ButtonPress);
XISetMask (mask.mask, XI_ButtonRelease);
XISetMask (mask.mask, XI_Enter);

View File

@@ -42,7 +42,7 @@
#include "edid.h"
#include "meta-monitor-config.h"
#define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1)
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
/* Look for DPI_FALLBACK in:
* http://git.gnome.org/browse/gnome-settings-daemon/tree/plugins/xsettings/gsd-xsettings-manager.c
@@ -67,31 +67,31 @@ struct _MetaMonitorManagerXrandrClass
G_DEFINE_TYPE (MetaMonitorManagerXrandr, meta_monitor_manager_xrandr, META_TYPE_MONITOR_MANAGER);
static MetaMonitorTransform
meta_monitor_transform_from_xrandr (Rotation rotation)
static enum wl_output_transform
wl_transform_from_xrandr (Rotation rotation)
{
static const MetaMonitorTransform y_reflected_map[4] = {
META_MONITOR_TRANSFORM_FLIPPED_180,
META_MONITOR_TRANSFORM_FLIPPED_90,
META_MONITOR_TRANSFORM_FLIPPED,
META_MONITOR_TRANSFORM_FLIPPED_270
static const enum wl_output_transform y_reflected_map[4] = {
WL_OUTPUT_TRANSFORM_FLIPPED_180,
WL_OUTPUT_TRANSFORM_FLIPPED_90,
WL_OUTPUT_TRANSFORM_FLIPPED,
WL_OUTPUT_TRANSFORM_FLIPPED_270
};
MetaMonitorTransform ret;
enum wl_output_transform ret;
switch (rotation & 0x7F)
{
default:
case RR_Rotate_0:
ret = META_MONITOR_TRANSFORM_NORMAL;
ret = WL_OUTPUT_TRANSFORM_NORMAL;
break;
case RR_Rotate_90:
ret = META_MONITOR_TRANSFORM_90;
ret = WL_OUTPUT_TRANSFORM_90;
break;
case RR_Rotate_180:
ret = META_MONITOR_TRANSFORM_180;
ret = WL_OUTPUT_TRANSFORM_180;
break;
case RR_Rotate_270:
ret = META_MONITOR_TRANSFORM_270;
ret = WL_OUTPUT_TRANSFORM_270;
break;
}
@@ -105,35 +105,35 @@ meta_monitor_transform_from_xrandr (Rotation rotation)
#define ALL_ROTATIONS (RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270)
static MetaMonitorTransform
meta_monitor_transform_from_xrandr_all (Rotation rotation)
static unsigned int
wl_transform_from_xrandr_all (Rotation rotation)
{
unsigned ret;
/* Handle the common cases first (none or all) */
if (rotation == 0 || rotation == RR_Rotate_0)
return (1 << META_MONITOR_TRANSFORM_NORMAL);
return (1 << WL_OUTPUT_TRANSFORM_NORMAL);
/* All rotations and one reflection -> all of them by composition */
if ((rotation & ALL_ROTATIONS) &&
((rotation & RR_Reflect_X) || (rotation & RR_Reflect_Y)))
return ALL_TRANSFORMS;
return ALL_WL_TRANSFORMS;
ret = 1 << META_MONITOR_TRANSFORM_NORMAL;
ret = 1 << WL_OUTPUT_TRANSFORM_NORMAL;
if (rotation & RR_Rotate_90)
ret |= 1 << META_MONITOR_TRANSFORM_90;
ret |= 1 << WL_OUTPUT_TRANSFORM_90;
if (rotation & RR_Rotate_180)
ret |= 1 << META_MONITOR_TRANSFORM_180;
ret |= 1 << WL_OUTPUT_TRANSFORM_180;
if (rotation & RR_Rotate_270)
ret |= 1 << META_MONITOR_TRANSFORM_270;
ret |= 1 << WL_OUTPUT_TRANSFORM_270;
if (rotation & (RR_Rotate_0 | RR_Reflect_X))
ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED;
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED;
if (rotation & (RR_Rotate_90 | RR_Reflect_X))
ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED_90;
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_90;
if (rotation & (RR_Rotate_180 | RR_Reflect_X))
ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED_180;
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_180;
if (rotation & (RR_Rotate_270 | RR_Reflect_X))
ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED_270;
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_270;
return ret;
}
@@ -150,7 +150,7 @@ output_get_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
atom = XInternAtom (manager_xrandr->xdisplay, "_MUTTER_PRESENTATION_OUTPUT", False);
XRRGetOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id,
(XID)output->output_id,
atom,
0, G_MAXLONG, False, False, XA_CARDINAL,
&actual_type, &actual_format,
@@ -186,7 +186,7 @@ output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
XRRGetOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id,
(XID)output->output_id,
atom,
0, G_MAXLONG, False, False, XA_INTEGER,
&actual_type, &actual_format,
@@ -211,7 +211,7 @@ output_get_backlight_limits_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
info = XRRQueryOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id,
(XID)output->output_id,
atom);
if (info == NULL)
@@ -278,25 +278,25 @@ get_edid_property (Display *dpy,
static GBytes *
read_output_edid (MetaMonitorManagerXrandr *manager_xrandr,
XID winsys_id)
XID output_id)
{
Atom edid_atom;
guint8 *result;
gsize len;
edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID", FALSE);
result = get_edid_property (manager_xrandr->xdisplay, winsys_id, edid_atom, &len);
result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len);
if (!result)
{
edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID_DATA", FALSE);
result = get_edid_property (manager_xrandr->xdisplay, winsys_id, edid_atom, &len);
result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len);
}
if (!result)
{
edid_atom = XInternAtom (manager_xrandr->xdisplay, "XFree86_DDC_EDID1_RAWDATA", FALSE);
result = get_edid_property (manager_xrandr->xdisplay, winsys_id, edid_atom, &len);
result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len);
}
if (result)
@@ -312,14 +312,14 @@ read_output_edid (MetaMonitorManagerXrandr *manager_xrandr,
static gboolean
output_get_hotplug_mode_update (MetaMonitorManagerXrandr *manager_xrandr,
XID winsys_id)
XID output_id)
{
Atom atom;
XRRPropertyInfo *info;
gboolean result = FALSE;
atom = XInternAtom (manager_xrandr->xdisplay, "hotplug_mode_update", False);
info = XRRQueryOutputProperty (manager_xrandr->xdisplay, winsys_id,
info = XRRQueryOutputProperty (manager_xrandr->xdisplay, output_id,
atom);
if (info)
@@ -434,8 +434,8 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
meta_crtc->rect.width = crtc->width;
meta_crtc->rect.height = crtc->height;
meta_crtc->is_dirty = FALSE;
meta_crtc->transform = meta_monitor_transform_from_xrandr (crtc->rotation);
meta_crtc->all_transforms = meta_monitor_transform_from_xrandr_all (crtc->rotations);
meta_crtc->transform = wl_transform_from_xrandr (crtc->rotation);
meta_crtc->all_transforms = wl_transform_from_xrandr_all (crtc->rotations);
for (j = 0; j < (unsigned)resources->nmode; j++)
{
@@ -467,10 +467,10 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
GBytes *edid;
MonitorInfo *parsed_edid;
meta_output->winsys_id = resources->outputs[i];
meta_output->output_id = resources->outputs[i];
meta_output->name = g_strdup (output->name);
edid = read_output_edid (manager_xrandr, meta_output->winsys_id);
edid = read_output_edid (manager_xrandr, meta_output->output_id);
if (edid)
{
gsize len;
@@ -504,7 +504,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
meta_output->height_mm = output->mm_height;
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
meta_output->hotplug_mode_update =
output_get_hotplug_mode_update (manager_xrandr, meta_output->winsys_id);
output_get_hotplug_mode_update (manager_xrandr, meta_output->output_id);
meta_output->n_modes = output->nmode;
meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
@@ -556,7 +556,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
meta_output->possible_clones[j] = GINT_TO_POINTER (output->clones[j]);
}
meta_output->is_primary = ((XID)meta_output->winsys_id == primary_output);
meta_output->is_primary = ((XID)meta_output->output_id == primary_output);
meta_output->is_presentation = output_get_presentation_xrandr (manager_xrandr, meta_output);
output_get_backlight_limits_xrandr (manager_xrandr, meta_output);
@@ -589,7 +589,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
for (k = 0; k < manager->n_outputs; k++)
{
if (clone == (XID)manager->outputs[k].winsys_id)
if (clone == (XID)manager->outputs[k].output_id)
{
meta_output->possible_clones[j] = &manager->outputs[k];
break;
@@ -605,7 +605,7 @@ meta_monitor_manager_xrandr_read_edid (MetaMonitorManager *manager,
{
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
return read_output_edid (manager_xrandr, output->winsys_id);
return read_output_edid (manager_xrandr, output->output_id);
}
static void
@@ -637,25 +637,25 @@ meta_monitor_manager_xrandr_set_power_save_mode (MetaMonitorManager *manager,
}
static Rotation
meta_monitor_transform_to_xrandr (MetaMonitorTransform transform)
wl_transform_to_xrandr (enum wl_output_transform transform)
{
switch (transform)
{
case META_MONITOR_TRANSFORM_NORMAL:
case WL_OUTPUT_TRANSFORM_NORMAL:
return RR_Rotate_0;
case META_MONITOR_TRANSFORM_90:
case WL_OUTPUT_TRANSFORM_90:
return RR_Rotate_90;
case META_MONITOR_TRANSFORM_180:
case WL_OUTPUT_TRANSFORM_180:
return RR_Rotate_180;
case META_MONITOR_TRANSFORM_270:
case WL_OUTPUT_TRANSFORM_270:
return RR_Rotate_270;
case META_MONITOR_TRANSFORM_FLIPPED:
case WL_OUTPUT_TRANSFORM_FLIPPED:
return RR_Reflect_X | RR_Rotate_0;
case META_MONITOR_TRANSFORM_FLIPPED_90:
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
return RR_Reflect_X | RR_Rotate_90;
case META_MONITOR_TRANSFORM_FLIPPED_180:
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
return RR_Reflect_X | RR_Rotate_180;
case META_MONITOR_TRANSFORM_FLIPPED_270:
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
return RR_Reflect_X | RR_Rotate_270;
}
@@ -672,7 +672,7 @@ output_set_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
atom = XInternAtom (manager_xrandr->xdisplay, "_MUTTER_PRESENTATION_OUTPUT", False);
XRRChangeOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id,
(XID)output->output_id,
atom,
XA_CARDINAL, 32, PropModeReplace,
(unsigned char*) &value, 1);
@@ -828,7 +828,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
output->crtc = crtc;
new_controlled_mask |= 1UL << j;
outputs[j] = output->winsys_id;
outputs[j] = output->output_id;
}
if (crtc->current_mode == mode &&
@@ -847,7 +847,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
manager_xrandr->time,
crtc_info->x, crtc_info->y,
(XID)mode->mode_id,
meta_monitor_transform_to_xrandr (crtc_info->transform),
wl_transform_to_xrandr (crtc_info->transform),
outputs, n_outputs);
if (ok != Success)
@@ -891,7 +891,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
{
XRRSetOutputPrimary (manager_xrandr->xdisplay,
DefaultRootWindow (manager_xrandr->xdisplay),
(XID)output_info->output->winsys_id);
(XID)output_info->output->output_id);
}
output_set_presentation_xrandr (manager_xrandr,
@@ -934,7 +934,7 @@ meta_monitor_manager_xrandr_change_backlight (MetaMonitorManager *manager,
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
XRRChangeOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id,
(XID)output->output_id,
atom,
XA_INTEGER, 32, PropModeReplace,
(unsigned char *) &hw_value, 1);

View File

@@ -15,7 +15,8 @@ struct _MetaCompositor
{
MetaDisplay *display;
guint repaint_func_id;
guint pre_paint_func_id;
guint post_paint_func_id;
gint64 server_time_query_time;
gint64 server_time_offset;
@@ -38,6 +39,9 @@ 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,6 +79,7 @@
#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"
@@ -136,7 +137,11 @@ meta_switch_workspace_completed (MetaCompositor *compositor)
void
meta_compositor_destroy (MetaCompositor *compositor)
{
clutter_threads_remove_repaint_func (compositor->repaint_func_id);
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 ();
}
static void
@@ -146,6 +151,35 @@ 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
get_output_window (MetaCompositor *compositor)
{
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
Window output;
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
output = XCompositeGetOverlayWindow (xdisplay, DefaultRootWindow (xdisplay));
meta_core_add_old_event_mask (xdisplay, output, &mask);
XISetMask (mask.mask, XI_KeyPress);
XISetMask (mask.mask, XI_KeyRelease);
XISetMask (mask.mask, XI_ButtonPress);
XISetMask (mask.mask, XI_ButtonRelease);
XISetMask (mask.mask, XI_Enter);
XISetMask (mask.mask, XI_Leave);
XISetMask (mask.mask, XI_FocusIn);
XISetMask (mask.mask, XI_FocusOut);
XISetMask (mask.mask, XI_Motion);
XISelectEvents (xdisplay, output, &mask, 1);
return output;
}
/* compat helper */
@@ -358,10 +392,6 @@ meta_begin_modal_for_plugin (MetaCompositor *compositor,
display->grab_have_pointer = TRUE;
display->grab_have_keyboard = TRUE;
g_signal_emit_by_name (display, "grab-op-begin",
meta_plugin_get_screen (plugin),
display->grab_window, display->grab_op);
if (meta_is_wayland_compositor ())
meta_display_sync_wayland_input_focus (display);
@@ -378,10 +408,6 @@ meta_end_modal_for_plugin (MetaCompositor *compositor,
g_return_if_fail (is_modal (display));
g_signal_emit_by_name (display, "grab-op-end",
meta_plugin_get_screen (plugin),
display->grab_window, display->grab_op);
display->grab_op = META_GRAB_OP_NONE;
display->grab_window = NULL;
display->grab_have_pointer = FALSE;
@@ -467,12 +493,12 @@ meta_compositor_manage (MetaCompositor *compositor)
MetaWaylandCompositor *wayland_compositor = meta_wayland_compositor_get_default ();
compositor->stage = meta_stage_new ();
clutter_actor_show (compositor->stage);
wayland_compositor->stage = compositor->stage;
meta_screen_get_size (screen, &width, &height);
clutter_actor_set_size (compositor->stage, width, height);
clutter_actor_show (compositor->stage);
}
else
{
@@ -491,6 +517,8 @@ meta_compositor_manage (MetaCompositor *compositor)
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
meta_core_add_old_event_mask (backend_xdisplay, xwin, &mask);
XISetMask (mask.mask, XI_KeyPress);
XISetMask (mask.mask, XI_KeyRelease);
XISetMask (mask.mask, XI_ButtonPress);
@@ -507,16 +535,10 @@ meta_compositor_manage (MetaCompositor *compositor)
}
}
/* We use connect_after() here to accomodate code in GNOME Shell that,
* when benchmarking drawing performance, connects to ::after-paint
* and calls glFinish(). The timing information from that will be
* more accurate if we hold off until that completes before we signal
* apps to begin drawing the next frame. If there are no other
* connections to ::after-paint, connect() vs. connect_after() doesn't
* matter.
*/
g_signal_connect_after (CLUTTER_STAGE (compositor->stage), "after-paint",
G_CALLBACK (after_stage_paint), compositor);
clutter_stage_set_paint_callback (CLUTTER_STAGE (compositor->stage),
after_stage_paint,
compositor,
NULL);
clutter_stage_set_sync_delay (CLUTTER_STAGE (compositor->stage), META_SYNC_DELAY);
@@ -535,8 +557,7 @@ meta_compositor_manage (MetaCompositor *compositor)
}
else
{
compositor->output = screen->composite_overlay_window;
compositor->output = get_output_window (compositor);
XReparentWindow (xdisplay, xwin, compositor->output, 0, 0);
meta_empty_stage_input_region (screen);
@@ -555,6 +576,8 @@ 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);
@@ -677,11 +700,12 @@ meta_compositor_remove_window (MetaCompositor *compositor,
}
void
meta_compositor_sync_updates_frozen (MetaCompositor *compositor,
MetaWindow *window)
meta_compositor_set_updates_frozen (MetaCompositor *compositor,
MetaWindow *window,
gboolean updates_frozen)
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
meta_window_actor_sync_updates_frozen (window_actor);
meta_window_actor_set_updates_frozen (window_actor, updates_frozen);
}
void
@@ -741,6 +765,9 @@ meta_compositor_process_event (MetaCompositor *compositor,
XEvent *event,
MetaWindow *window)
{
if (meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event))
return TRUE;
if (!meta_is_wayland_compositor () &&
event->type == meta_display_get_damage_event_base (compositor->display) + XDamageNotify)
{
@@ -762,6 +789,10 @@ 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.
@@ -1107,11 +1138,12 @@ frame_callback (CoglOnscreen *onscreen,
}
}
static void
pre_paint_windows (MetaCompositor *compositor)
static gboolean
meta_pre_paint_func (gpointer data)
{
GList *l;
MetaWindowActor *top_window;
MetaCompositor *compositor = data;
if (compositor->onscreen == NULL)
{
@@ -1123,7 +1155,7 @@ pre_paint_windows (MetaCompositor *compositor)
}
if (compositor->windows == NULL)
return;
return TRUE;
top_window = g_list_last (compositor->windows)->data;
@@ -1135,13 +1167,53 @@ pre_paint_windows (MetaCompositor *compositor)
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_repaint_func (gpointer data)
meta_post_paint_func (gpointer data)
{
MetaCompositor *compositor = data;
pre_paint_windows (compositor);
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;
}
return TRUE;
}
@@ -1180,10 +1252,16 @@ meta_compositor_new (MetaDisplay *display)
G_CALLBACK (on_shadow_factory_changed),
compositor);
compositor->repaint_func_id = clutter_threads_add_repaint_func (meta_repaint_func,
compositor,
NULL);
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);
return compositor;
}
@@ -1348,12 +1426,3 @@ 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,7 +20,6 @@
*/
#include <meta/meta-plugin.h>
#include <meta/meta-version.h>
#include "meta-module.h"
#include <gmodule.h>
@@ -69,7 +68,7 @@ meta_module_load (GTypeModule *gmodule)
(gpointer *)(void *)&register_type) &&
info && register_type)
{
if (info->version_api != META_PLUGIN_API_VERSION)
if (info->version_api != MUTTER_PLUGIN_API_VERSION)
g_warning ("Plugin API mismatch for [%s]", priv->path);
else
{

View File

@@ -374,20 +374,3 @@ 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,10 +87,5 @@ 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", { 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 } },
{ "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 } },
{ "utility", { 3, -1, 0, 1, 128 }, { 3, -1, 0, 1, 32 } },
{ "border", { 3, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
{ "menu", { 3, -1, 0, 3, 128 }, { 3, -1, 0, 0, 32 } },
{ "border", { 6, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
{ "menu", { 6, -1, 0, 3, 128 }, { 3, -1, 0, 0, 32 } },
{ "popup-menu", { 1, 0, 0, 1, 128 }, { 1, -1, 0, 1, 128 } },
{ "popup-menu", { 1, -1, 0, 1, 128 }, { 1, -1, 0, 1, 128 } },
{ "dropdown-menu", { 1, 10, 0, 1, 128 }, { 1, 10, 0, 1, 128 } },
{ "attached", { 1, 0, 0, 1, 128 }, { 1, -1, 0, 1, 128 } }
{ "attached", { 1, -1, 0, 1, 128 }, { 1, -1, 0, 1, 128 } }
};
G_DEFINE_TYPE (MetaShadowFactory, meta_shadow_factory, G_TYPE_OBJECT);
@@ -496,12 +496,7 @@ get_box_filter_size (int radius)
static int
get_shadow_spread (int radius)
{
int d;
if (radius == 0)
return 0;
d = get_box_filter_size (radius);
int d = get_box_filter_size (radius);
if (d % 2 == 1)
return 3 * (d / 2);

View File

@@ -109,7 +109,7 @@ meta_surface_actor_wayland_is_unredirected (MetaSurfaceActor *actor)
}
static int
get_output_scale (int winsys_id)
get_output_scale (int output_id)
{
MetaMonitorManager *monitor_manager = meta_monitor_manager_get ();
MetaOutput *outputs;
@@ -120,7 +120,7 @@ get_output_scale (int winsys_id)
for (i = 0; i < n_outputs; i++)
{
if (outputs[i].winsys_id == winsys_id)
if (outputs[i].output_id == output_id)
{
output_scale = outputs[i].scale;
break;
@@ -150,7 +150,7 @@ meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *actor)
/* XXX: We do not handle x11 clients yet */
if (window && window->client_type != META_WINDOW_CLIENT_TYPE_X11)
output_scale = get_output_scale (window->monitor->winsys_id);
output_scale = get_output_scale (window->monitor->output_id);
return (double)output_scale / (double)priv->surface->scale;
}

View File

@@ -34,7 +34,6 @@
#include "window-private.h"
#include "meta-shaped-texture-private.h"
#include "meta-cullable.h"
#include "x11/window-x11.h"
struct _MetaSurfaceActorX11Private
{
@@ -144,7 +143,7 @@ update_pixmap (MetaSurfaceActorX11 *self)
if (priv->pixmap == None)
{
Pixmap new_pixmap;
Window xwindow = meta_window_x11_get_toplevel_xwindow (priv->window);
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
meta_error_trap_push (display);
new_pixmap = XCompositeNameWindowPixmap (xdisplay, xwindow);
@@ -239,26 +238,6 @@ 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;
}
@@ -313,7 +292,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_x11_get_toplevel_xwindow (priv->window);
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
meta_error_trap_push (display);
@@ -405,7 +384,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_x11_get_toplevel_xwindow (priv->window);
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
priv->damage = XDamageCreate (xdisplay, xwindow, XDamageReportBoundingBox);
}

View File

@@ -0,0 +1,574 @@
/*
* 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

@@ -0,0 +1,17 @@
#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,7 +51,8 @@ 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_sync_updates_frozen (MetaWindowActor *self);
void meta_window_actor_set_updates_frozen (MetaWindowActor *self,
gboolean updates_frozen);
void meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
gboolean no_delay_frame);

View File

@@ -36,12 +36,6 @@
#include "wayland/meta-wayland-surface.h"
typedef enum {
INITIALLY_FROZEN,
DRAWING_FIRST_FRAME,
EMITTED_FIRST_FRAME
} FirstFrameState;
struct _MetaWindowActorPrivate
{
MetaWindow *window;
@@ -110,7 +104,6 @@ struct _MetaWindowActorPrivate
guint no_shadow : 1;
guint updates_frozen : 1;
guint first_frame_state : 2; /* FirstFrameState */
};
typedef struct _FrameData FrameData;
@@ -122,14 +115,6 @@ struct _FrameData
gint64 frame_drawn_time;
};
enum
{
FIRST_FRAME,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
enum
{
PROP_META_WINDOW = 1,
@@ -196,31 +181,6 @@ meta_window_actor_class_init (MetaWindowActorClass *klass)
actor_class->paint = meta_window_actor_paint;
actor_class->get_paint_volume = meta_window_actor_get_paint_volume;
/**
* MetaWindowActor::first-frame:
* @actor: the #MetaWindowActor instance
*
* The ::first-frame signal will be emitted the first time a frame
* of window contents has been drawn by the application and Mutter
* has had the chance to drawn that frame to the screen. If the
* window starts off initially hidden, obscured, or on on a
* different workspace, the ::first-frame signal will be emitted
* even though the user doesn't see the contents.
*
* MetaDisplay::window-created is a good place to connect to this
* signal - at that point, the MetaWindowActor for the window
* exists, but the window has reliably not yet been drawn.
* Connecting to an existing window that has already been drawn to
* the screen is not useful.
*/
signals[FIRST_FRAME] =
g_signal_new ("first-frame",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 0);
pspec = g_param_spec_object ("meta-window",
"MetaWindow",
"The displayed MetaWindow",
@@ -346,9 +306,6 @@ meta_window_actor_thaw (MetaWindowActor *self)
if (priv->freeze_count > 0)
return;
if (priv->first_frame_state == INITIALLY_FROZEN)
priv->first_frame_state = DRAWING_FIRST_FRAME;
if (priv->surface)
meta_surface_actor_set_frozen (priv->surface, FALSE);
@@ -391,9 +348,6 @@ set_surface (MetaWindowActor *self,
* frozen as well... */
meta_surface_actor_set_frozen (priv->surface, priv->freeze_count > 0);
if (!is_frozen (self) && priv->first_frame_state == INITIALLY_FROZEN)
priv->first_frame_state = DRAWING_FIRST_FRAME;
meta_window_actor_update_shape (self);
}
}
@@ -792,11 +746,9 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
return FALSE;
/*
* Add shadows to override redirect windows on X11 unless the toolkit
* indicates that it is handling shadows itself (e.g., Gtk menus).
* Add shadows to override redirect windows (e.g., Gtk menus).
*/
if (priv->window->override_redirect &&
!priv->window->has_custom_frame_extents)
if (priv->window->override_redirect)
return TRUE;
return FALSE;
@@ -899,7 +851,7 @@ queue_send_frame_messages_timeout (MetaWindowActor *self)
outputs = meta_monitor_manager_get_outputs (monitor_manager, &n_outputs);
for (i = 0; i < n_outputs; i++)
{
if (outputs[i].winsys_id == window->monitor->winsys_id && outputs[i].crtc)
if (outputs[i].output_id == window->monitor->output_id && outputs[i].crtc)
{
refresh_rate = outputs[i].crtc->current_mode->refresh_rate;
break;
@@ -1198,7 +1150,7 @@ meta_window_actor_sync_actor_geometry (MetaWindowActor *self,
MetaWindowActorPrivate *priv = self->priv;
MetaRectangle window_rect;
meta_window_get_buffer_rect (priv->window, &window_rect);
meta_window_get_input_rect (priv->window, &window_rect);
/* When running as a Wayland compositor we catch size changes when new
* buffers are attached */
@@ -1372,12 +1324,7 @@ meta_window_actor_new (MetaWindow *window)
priv = self->priv;
meta_window_actor_sync_updates_frozen (self);
if (is_frozen (self))
priv->first_frame_state = INITIALLY_FROZEN;
else
priv->first_frame_state = DRAWING_FIRST_FRAME;
meta_window_actor_set_updates_frozen (self, meta_window_updates_are_frozen (priv->window));
/* 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.
@@ -1961,12 +1908,6 @@ meta_window_actor_post_paint (MetaWindowActor *self)
do_send_frame_drawn (self, priv->frames->data);
priv->needs_frame_drawn = FALSE;
}
if (priv->first_frame_state == DRAWING_FIRST_FRAME)
{
priv->first_frame_state = EMITTED_FIRST_FRAME;
g_signal_emit (self, signals[FIRST_FRAME], 0);
}
}
static void
@@ -2079,7 +2020,7 @@ meta_window_actor_update_opacity (MetaWindowActor *self)
clutter_actor_set_opacity (CLUTTER_ACTOR (priv->surface), window->opacity);
}
static void
void
meta_window_actor_set_updates_frozen (MetaWindowActor *self,
gboolean updates_frozen)
{
@@ -2096,12 +2037,3 @@ 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,22 +1,12 @@
pkglibdir = $(MUTTER_PLUGIN_DIR)
pkglibdir=@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)\"
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@\"
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,26 +546,6 @@ 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
@@ -650,8 +630,7 @@ meta_rectangle_get_minimal_spanning_set_for_region (
for (strut_iter = all_struts; strut_iter; strut_iter = strut_iter->next)
{
GList *rect_iter;
MetaStrut *strut = (MetaStrut*)strut_iter->data;
MetaRectangle *strut_rect = &strut->rect;
MetaRectangle *strut_rect = &((MetaStrut*)strut_iter->data)->rect;
tmp_list = ret;
ret = NULL;
@@ -659,9 +638,7 @@ meta_rectangle_get_minimal_spanning_set_for_region (
while (rect_iter)
{
MetaRectangle *rect = (MetaRectangle*) rect_iter->data;
if (!meta_rectangle_overlap (strut_rect, rect) ||
!check_strut_align (strut, basic_rect))
if (!meta_rectangle_overlap (rect, strut_rect))
ret = g_list_prepend (ret, rect);
else
{

View File

@@ -404,6 +404,31 @@ 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"
@@ -588,7 +613,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,
@@ -601,7 +626,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,
@@ -620,7 +645,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,22 +392,6 @@ 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,
@@ -495,5 +479,46 @@ meta_core_set_screen_cursor (Display *xdisplay,
void
meta_invalidate_default_icons (void)
{
/* XXX: Actually invalidate the icons when they're used. */
MetaDisplay *display = meta_get_display ();
GSList *windows;
GSList *l;
if (display == NULL)
return; /* We can validly be called before the display is opened. */
windows = meta_display_list_windows (display, META_LIST_DEFAULT);
for (l = windows; l != NULL; l = l->next)
{
MetaWindow *window = (MetaWindow*)l->data;
if (window->icon_cache.origin == USING_FALLBACK_ICON)
{
meta_icon_cache_free (&(window->icon_cache));
meta_window_update_icon_now (window);
}
}
g_slist_free (windows);
}
void
meta_core_add_old_event_mask (Display *xdisplay,
Window xwindow,
XIEventMask *mask)
{
XIEventMask *prev;
gint n_masks, i, j;
prev = XIGetSelectedEvents (xdisplay, xwindow, &n_masks);
for (i = 0; i < n_masks; i++)
{
if (prev[i].deviceid != XIAllMasterDevices)
continue;
for (j = 0; j < MIN (mask->mask_len, prev[i].mask_len); j++)
mask->mask[j] |= prev[i].mask[j];
}
XFree (prev);
}

View File

@@ -26,7 +26,6 @@
/* Don't include core headers here */
#include <gdk/gdkx.h>
#include <meta/common.h>
#include <meta/boxes.h>
typedef enum
{
@@ -139,12 +138,6 @@ 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,
@@ -169,4 +162,8 @@ void meta_core_set_screen_cursor (Display *xdisplay,
void meta_invalidate_default_icons (void);
void meta_core_add_old_event_mask (Display *xdisplay,
Window xwindow,
XIEventMask *mask);
#endif

View File

@@ -37,6 +37,8 @@
#include <stdlib.h>
#include <stdio.h>
#include "wayland/meta-wayland-surface.h"
static void
dialog_exited (GPid pid, int status, gpointer user_data)
{

View File

@@ -35,7 +35,6 @@
#include <meta/boxes.h>
#include <meta/display.h>
#include "keybindings-private.h"
#include "meta-gesture-tracker-private.h"
#include <meta/prefs.h>
#include <meta/barrier.h>
#include <clutter/clutter.h>
@@ -146,6 +145,8 @@ struct _MetaDisplay
GHashTable *xids;
GHashTable *wayland_windows;
int server_grab_count;
/* serials of leave/unmap events that may
* correspond to an enter event we should
* ignore
@@ -180,6 +181,7 @@ 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;
@@ -252,8 +254,6 @@ struct _MetaDisplay
/* Managed by compositor.c */
MetaCompositor *compositor;
MetaGestureTracker *gesture_tracker;
int composite_event_base;
int composite_error_base;
int composite_major_version;
@@ -312,6 +312,8 @@ struct _MetaDisplayClass
gboolean meta_display_open (void);
void meta_display_close (MetaDisplay *display,
guint32 timestamp);
void meta_display_grab (MetaDisplay *display);
void meta_display_ungrab (MetaDisplay *display);
void meta_display_unmanage_windows_for_screen (MetaDisplay *display,
MetaScreen *screen,
@@ -441,16 +443,4 @@ void meta_display_sanity_check_timestamps (MetaDisplay *display,
gboolean meta_display_timestamp_too_old (MetaDisplay *display,
guint32 *timestamp);
void meta_display_remove_pending_pings_for_window (MetaDisplay *display,
MetaWindow *window);
MetaGestureTracker * meta_display_get_gesture_tracker (MetaDisplay *display);
gboolean meta_display_show_restart_message (MetaDisplay *display,
const char *message);
gboolean meta_display_request_restart (MetaDisplay *display);
void meta_restart_init (void);
void meta_restart_finish (void);
#endif

View File

@@ -51,7 +51,6 @@
#include "meta-cursor-tracker-private.h"
#include "meta-backend.h"
#include "backends/x11/meta-backend-x11.h"
#include <clutter/x11/clutter-x11.h>
#ifdef HAVE_RANDR
#include <X11/extensions/Xrandr.h>
@@ -71,6 +70,7 @@
#include "x11/xprops.h"
#include "wayland/meta-xwayland-private.h"
#include "meta-surface-actor-wayland.h"
/*
* SECTION:pings
@@ -117,8 +117,6 @@ enum
WINDOW_MARKED_URGENT,
GRAB_OP_BEGIN,
GRAB_OP_END,
SHOW_RESTART_MESSAGE,
RESTART,
LAST_SIGNAL
};
@@ -271,59 +269,6 @@ meta_display_class_init (MetaDisplayClass *klass)
META_TYPE_WINDOW,
META_TYPE_GRAB_OP);
/**
* MetaDisplay::show-restart-message:
* @display: the #MetaDisplay instance
* @message: (allow-none): The message to display, or %NULL
* to clear a previous restart message.
*
* The ::show-restart-message signal will be emitted to indicate
* that the compositor should show a message during restart. This is
* emitted when meta_restart() is called, either by Mutter
* internally or by the embedding compositor. The message should be
* immediately added to the Clutter stage in its final form -
* ::restart will be emitted to exit the application and leave the
* stage contents frozen as soon as the the stage is painted again.
*
* On case of failure to restart, this signal will be emitted again
* with %NULL for @message.
*
* Returns: %TRUE means the message was added to the stage; %FALSE
* indicates that the compositor did not show the message.
*/
display_signals[SHOW_RESTART_MESSAGE] =
g_signal_new ("show-restart-message",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
g_signal_accumulator_true_handled,
NULL, NULL,
G_TYPE_BOOLEAN, 1,
G_TYPE_STRING);
/**
* MetaDisplay::restart:
* @display: the #MetaDisplay instance
*
* The ::restart signal is emitted to indicate that compositor
* should reexec the process. This is
* emitted when meta_restart() is called, either by Mutter
* internally or by the embedding compositor. See also
* ::show-restart-message.
*
* Returns: %FALSE to indicate that the compositor could not
* be restarted. When the compositor is restarted, the signal
* should not return.
*/
display_signals[RESTART] =
g_signal_new ("restart",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
g_signal_accumulator_true_handled,
NULL, NULL,
G_TYPE_BOOLEAN, 0);
g_object_class_install_property (object_class,
PROP_FOCUS_WINDOW,
g_param_spec_object ("focus-window",
@@ -350,9 +295,16 @@ ping_data_free (MetaPingData *ping_data)
g_free (ping_data);
}
void
meta_display_remove_pending_pings_for_window (MetaDisplay *display,
MetaWindow *window)
/**
* remove_pending_pings_for_window:
* @display: The display the window appears on
* @xwindow: The X ID of the window whose pings we should remove
*
* Frees every pending ping structure for the given X window on the
* given display. This means that we also destroy the timeouts.
*/
static void
remove_pending_pings_for_window (MetaDisplay *display, Window xwindow)
{
GSList *tmp;
GSList *dead;
@@ -365,7 +317,7 @@ meta_display_remove_pending_pings_for_window (MetaDisplay *display,
{
MetaPingData *ping_data = tmp->data;
if (ping_data->window == window)
if (ping_data->window->xwindow == xwindow)
dead = g_slist_prepend (dead, ping_data);
}
@@ -461,28 +413,6 @@ meta_set_gnome_wm_keybindings (const char *wm_keybindings)
gnome_wm_keybindings = wm_keybindings;
}
static void
gesture_tracker_state_changed (MetaGestureTracker *tracker,
ClutterEventSequence *sequence,
MetaSequenceState state,
MetaDisplay *display)
{
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
int event_mode;
if (state == META_SEQUENCE_ACCEPTED)
event_mode = XIAcceptTouch;
else if (state == META_SEQUENCE_REJECTED)
event_mode = XIRejectTouch;
else
return;
XIAllowTouchEvents (meta_backend_x11_get_xdisplay (backend),
META_VIRTUAL_CORE_POINTER_ID,
clutter_x11_event_sequence_get_touch_detail (sequence),
DefaultRootWindow (display->xdisplay), event_mode);
}
/**
* meta_display_open:
*
@@ -496,7 +426,6 @@ gesture_tracker_state_changed (MetaGestureTracker *tracker,
gboolean
meta_display_open (void)
{
MetaDisplay *display;
Display *xdisplay;
MetaScreen *screen;
int i;
@@ -528,223 +457,224 @@ meta_display_open (void)
XSynchronize (xdisplay, True);
g_assert (the_display == NULL);
display = the_display = g_object_new (META_TYPE_DISPLAY, NULL);
the_display = g_object_new (META_TYPE_DISPLAY, NULL);
display->closing = 0;
the_display->closing = 0;
/* here we use XDisplayName which is what the user
* probably put in, vs. DisplayString(display) which is
* canonicalized by XOpenDisplay()
*/
display->name = g_strdup (XDisplayName (NULL));
display->xdisplay = xdisplay;
display->display_opening = TRUE;
the_display->name = g_strdup (XDisplayName (NULL));
the_display->xdisplay = xdisplay;
the_display->server_grab_count = 0;
the_display->display_opening = TRUE;
display->pending_pings = NULL;
display->autoraise_timeout_id = 0;
display->autoraise_window = NULL;
display->focus_window = NULL;
display->focus_serial = 0;
display->server_focus_window = None;
display->server_focus_serial = 0;
the_display->pending_pings = NULL;
the_display->autoraise_timeout_id = 0;
the_display->autoraise_window = NULL;
the_display->focus_window = NULL;
the_display->focus_serial = 0;
the_display->server_focus_window = None;
the_display->server_focus_serial = 0;
display->mouse_mode = TRUE; /* Only relevant for mouse or sloppy focus */
display->allow_terminal_deactivation = TRUE; /* Only relevant for when a
the_display->mouse_mode = TRUE; /* Only relevant for mouse or sloppy focus */
the_display->allow_terminal_deactivation = TRUE; /* Only relevant for when a
terminal has the focus */
meta_bell_init (display);
meta_bell_init (the_display);
meta_display_init_keys (display);
meta_display_init_keys (the_display);
update_window_grab_modifiers (display);
update_window_grab_modifiers (the_display);
meta_prefs_add_listener (prefs_changed_callback, display);
meta_prefs_add_listener (prefs_changed_callback, the_display);
meta_verbose ("Creating %d atoms\n", (int) G_N_ELEMENTS (atom_names));
XInternAtoms (display->xdisplay, atom_names, G_N_ELEMENTS (atom_names),
XInternAtoms (the_display->xdisplay, atom_names, G_N_ELEMENTS (atom_names),
False, atoms);
{
int i = 0;
#define item(x) display->atom_##x = atoms[i++];
#define item(x) the_display->atom_##x = atoms[i++];
#include <meta/atomnames.h>
#undef item
}
display->prop_hooks = NULL;
meta_display_init_window_prop_hooks (display);
display->group_prop_hooks = NULL;
meta_display_init_group_prop_hooks (display);
the_display->prop_hooks = NULL;
meta_display_init_window_prop_hooks (the_display);
the_display->group_prop_hooks = NULL;
meta_display_init_group_prop_hooks (the_display);
/* Offscreen unmapped window used for _NET_SUPPORTING_WM_CHECK,
* created in screen_new
*/
display->leader_window = None;
display->timestamp_pinging_window = None;
the_display->leader_window = None;
the_display->timestamp_pinging_window = None;
display->monitor_cache_invalidated = TRUE;
the_display->monitor_cache_invalidated = TRUE;
display->groups_by_leader = NULL;
the_display->groups_by_leader = NULL;
display->screen = NULL;
the_display->screen = NULL;
#ifdef HAVE_STARTUP_NOTIFICATION
display->sn_display = sn_display_new (display->xdisplay,
the_display->sn_display = sn_display_new (the_display->xdisplay,
sn_error_trap_push,
sn_error_trap_pop);
#endif
/* Get events */
meta_display_init_events (display);
meta_display_init_events (the_display);
display->xids = g_hash_table_new (meta_unsigned_long_hash,
the_display->xids = g_hash_table_new (meta_unsigned_long_hash,
meta_unsigned_long_equal);
display->wayland_windows = g_hash_table_new (NULL, NULL);
the_display->wayland_windows = g_hash_table_new (NULL, NULL);
i = 0;
while (i < N_IGNORED_CROSSING_SERIALS)
{
display->ignored_crossing_serials[i] = 0;
the_display->ignored_crossing_serials[i] = 0;
++i;
}
display->ungrab_should_not_cause_focus_window = None;
the_display->ungrab_should_not_cause_focus_window = None;
display->current_time = CurrentTime;
display->sentinel_counter = 0;
the_display->current_time = CurrentTime;
the_display->sentinel_counter = 0;
display->grab_resize_timeout_id = 0;
display->grab_have_keyboard = FALSE;
the_display->grab_resize_timeout_id = 0;
the_display->grab_have_keyboard = FALSE;
#ifdef HAVE_XKB
display->last_bell_time = 0;
the_display->last_bell_time = 0;
#endif
display->grab_op = META_GRAB_OP_NONE;
display->grab_window = NULL;
display->grab_tile_mode = META_TILE_NONE;
display->grab_tile_monitor_number = -1;
the_display->grab_op = META_GRAB_OP_NONE;
the_display->grab_window = NULL;
the_display->grab_tile_mode = META_TILE_NONE;
the_display->grab_tile_monitor_number = -1;
display->grab_edge_resistance_data = NULL;
the_display->grab_edge_resistance_data = NULL;
{
int major, minor;
display->have_xsync = FALSE;
the_display->have_xsync = FALSE;
display->xsync_error_base = 0;
display->xsync_event_base = 0;
the_display->xsync_error_base = 0;
the_display->xsync_event_base = 0;
/* I don't think we really have to fill these in */
major = SYNC_MAJOR_VERSION;
minor = SYNC_MINOR_VERSION;
if (!XSyncQueryExtension (display->xdisplay,
&display->xsync_event_base,
&display->xsync_error_base) ||
!XSyncInitialize (display->xdisplay,
if (!XSyncQueryExtension (the_display->xdisplay,
&the_display->xsync_event_base,
&the_display->xsync_error_base) ||
!XSyncInitialize (the_display->xdisplay,
&major, &minor))
{
display->xsync_error_base = 0;
display->xsync_event_base = 0;
the_display->xsync_error_base = 0;
the_display->xsync_event_base = 0;
}
else
{
display->have_xsync = TRUE;
XSyncSetPriority (display->xdisplay, None, 10);
the_display->have_xsync = TRUE;
XSyncSetPriority (the_display->xdisplay, None, 10);
}
meta_verbose ("Attempted to init Xsync, found version %d.%d error base %d event base %d\n",
major, minor,
display->xsync_error_base,
display->xsync_event_base);
the_display->xsync_error_base,
the_display->xsync_event_base);
}
{
display->have_shape = FALSE;
the_display->have_shape = FALSE;
display->shape_error_base = 0;
display->shape_event_base = 0;
the_display->shape_error_base = 0;
the_display->shape_event_base = 0;
if (!XShapeQueryExtension (display->xdisplay,
&display->shape_event_base,
&display->shape_error_base))
if (!XShapeQueryExtension (the_display->xdisplay,
&the_display->shape_event_base,
&the_display->shape_error_base))
{
display->shape_error_base = 0;
display->shape_event_base = 0;
the_display->shape_error_base = 0;
the_display->shape_event_base = 0;
}
else
display->have_shape = TRUE;
the_display->have_shape = TRUE;
meta_verbose ("Attempted to init Shape, found error base %d event base %d\n",
display->shape_error_base,
display->shape_event_base);
the_display->shape_error_base,
the_display->shape_event_base);
}
{
display->have_composite = FALSE;
the_display->have_composite = FALSE;
display->composite_error_base = 0;
display->composite_event_base = 0;
the_display->composite_error_base = 0;
the_display->composite_event_base = 0;
if (!XCompositeQueryExtension (display->xdisplay,
&display->composite_event_base,
&display->composite_error_base))
if (!XCompositeQueryExtension (the_display->xdisplay,
&the_display->composite_event_base,
&the_display->composite_error_base))
{
display->composite_error_base = 0;
display->composite_event_base = 0;
the_display->composite_error_base = 0;
the_display->composite_event_base = 0;
}
else
{
display->composite_major_version = 0;
display->composite_minor_version = 0;
if (XCompositeQueryVersion (display->xdisplay,
&display->composite_major_version,
&display->composite_minor_version))
the_display->composite_major_version = 0;
the_display->composite_minor_version = 0;
if (XCompositeQueryVersion (the_display->xdisplay,
&the_display->composite_major_version,
&the_display->composite_minor_version))
{
display->have_composite = TRUE;
the_display->have_composite = TRUE;
}
else
{
display->composite_major_version = 0;
display->composite_minor_version = 0;
the_display->composite_major_version = 0;
the_display->composite_minor_version = 0;
}
}
meta_verbose ("Attempted to init Composite, found error base %d event base %d "
"extn ver %d %d\n",
display->composite_error_base,
display->composite_event_base,
display->composite_major_version,
display->composite_minor_version);
the_display->composite_error_base,
the_display->composite_event_base,
the_display->composite_major_version,
the_display->composite_minor_version);
display->have_damage = FALSE;
the_display->have_damage = FALSE;
display->damage_error_base = 0;
display->damage_event_base = 0;
the_display->damage_error_base = 0;
the_display->damage_event_base = 0;
if (!XDamageQueryExtension (display->xdisplay,
&display->damage_event_base,
&display->damage_error_base))
if (!XDamageQueryExtension (the_display->xdisplay,
&the_display->damage_event_base,
&the_display->damage_error_base))
{
display->damage_error_base = 0;
display->damage_event_base = 0;
the_display->damage_error_base = 0;
the_display->damage_event_base = 0;
}
else
display->have_damage = TRUE;
the_display->have_damage = TRUE;
meta_verbose ("Attempted to init Damage, found error base %d event base %d\n",
display->damage_error_base,
display->damage_event_base);
the_display->damage_error_base,
the_display->damage_event_base);
display->xfixes_error_base = 0;
display->xfixes_event_base = 0;
the_display->xfixes_error_base = 0;
the_display->xfixes_event_base = 0;
if (XFixesQueryExtension (display->xdisplay,
&display->xfixes_event_base,
&display->xfixes_error_base))
if (XFixesQueryExtension (the_display->xdisplay,
&the_display->xfixes_event_base,
&the_display->xfixes_error_base))
{
int xfixes_major, xfixes_minor;
XFixesQueryVersion (display->xdisplay, &xfixes_major, &xfixes_minor);
XFixesQueryVersion (the_display->xdisplay, &xfixes_major, &xfixes_minor);
if (xfixes_major * 100 + xfixes_minor < 500)
meta_fatal ("Mutter requires XFixes 5.0");
@@ -755,21 +685,21 @@ meta_display_open (void)
}
meta_verbose ("Attempted to init XFixes, found error base %d event base %d\n",
display->xfixes_error_base,
display->xfixes_event_base);
the_display->xfixes_error_base,
the_display->xfixes_event_base);
}
{
int major = 2, minor = 3;
gboolean has_xi = FALSE;
if (XQueryExtension (display->xdisplay,
if (XQueryExtension (the_display->xdisplay,
"XInputExtension",
&display->xinput_opcode,
&display->xinput_error_base,
&display->xinput_event_base))
&the_display->xinput_opcode,
&the_display->xinput_error_base,
&the_display->xinput_event_base))
{
if (XIQueryVersion (display->xdisplay, &major, &minor) == Success)
if (XIQueryVersion (the_display->xdisplay, &major, &minor) == Success)
{
int version = (major * 10) + minor;
if (version >= 22)
@@ -777,7 +707,7 @@ meta_display_open (void)
#ifdef HAVE_XI23
if (version >= 23)
display->have_xinput_23 = TRUE;
the_display->have_xinput_23 = TRUE;
#endif /* HAVE_XI23 */
}
}
@@ -801,35 +731,35 @@ meta_display_open (void)
* this window, so we can't rely on it still being set later. See bug
* 354213 for details.
*/
display->leader_window =
meta_create_offscreen_window (display->xdisplay,
DefaultRootWindow (display->xdisplay),
the_display->leader_window =
meta_create_offscreen_window (the_display->xdisplay,
DefaultRootWindow (the_display->xdisplay),
PropertyChangeMask);
meta_prop_set_utf8_string_hint (display,
display->leader_window,
display->atom__NET_WM_NAME,
meta_prop_set_utf8_string_hint (the_display,
the_display->leader_window,
the_display->atom__NET_WM_NAME,
net_wm_name);
meta_prop_set_utf8_string_hint (display,
display->leader_window,
display->atom__GNOME_WM_KEYBINDINGS,
meta_prop_set_utf8_string_hint (the_display,
the_display->leader_window,
the_display->atom__GNOME_WM_KEYBINDINGS,
gnome_wm_keybindings);
meta_prop_set_utf8_string_hint (display,
display->leader_window,
display->atom__MUTTER_VERSION,
meta_prop_set_utf8_string_hint (the_display,
the_display->leader_window,
the_display->atom__MUTTER_VERSION,
VERSION);
data[0] = display->leader_window;
XChangeProperty (display->xdisplay,
display->leader_window,
display->atom__NET_SUPPORTING_WM_CHECK,
data[0] = the_display->leader_window;
XChangeProperty (the_display->xdisplay,
the_display->leader_window,
the_display->atom__NET_SUPPORTING_WM_CHECK,
XA_WINDOW,
32, PropModeReplace, (guchar*) data, 1);
XWindowEvent (display->xdisplay,
display->leader_window,
XWindowEvent (the_display->xdisplay,
the_display->leader_window,
PropertyChangeMask,
&event);
@@ -838,52 +768,45 @@ meta_display_open (void)
/* Make it painfully clear that we can't rely on PropertyNotify events on
* this window, as per bug 354213.
*/
XSelectInput(display->xdisplay,
display->leader_window,
XSelectInput(the_display->xdisplay,
the_display->leader_window,
NoEventMask);
}
/* Make a little window used only for pinging the server for timestamps; note
* that meta_create_offscreen_window already selects for PropertyChangeMask.
*/
display->timestamp_pinging_window =
meta_create_offscreen_window (display->xdisplay,
DefaultRootWindow (display->xdisplay),
the_display->timestamp_pinging_window =
meta_create_offscreen_window (the_display->xdisplay,
DefaultRootWindow (the_display->xdisplay),
PropertyChangeMask);
display->last_focus_time = timestamp;
display->last_user_time = timestamp;
display->compositor = NULL;
the_display->last_focus_time = timestamp;
the_display->last_user_time = timestamp;
the_display->compositor = NULL;
/* Mutter used to manage all X screens of the display in a single process, but
* now it always manages exactly one screen as specified by the DISPLAY
* environment variable.
*/
i = meta_ui_get_screen_number ();
screen = meta_screen_new (display, i, timestamp);
screen = meta_screen_new (the_display, i, timestamp);
if (!screen)
{
/* This would typically happen because all the screens already
* have window managers.
*/
meta_display_close (display, timestamp);
meta_display_close (the_display, timestamp);
return FALSE;
}
display->screen = screen;
the_display->screen = screen;
meta_screen_init_workspaces (screen);
enable_compositor (display);
enable_compositor (the_display);
meta_screen_create_guard_window (screen);
/* Set up touch support */
display->gesture_tracker = meta_gesture_tracker_new ();
g_signal_connect (display->gesture_tracker, "state-changed",
G_CALLBACK (gesture_tracker_state_changed), display);
/* We know that if mutter is running as a Wayland compositor,
* we start out with no windows.
*/
@@ -895,12 +818,12 @@ meta_display_open (void)
int ret_to;
/* kinda bogus because GetInputFocus has no possible errors */
meta_error_trap_push (display);
meta_error_trap_push (the_display);
/* FIXME: This is totally broken; see comment 9 of bug 88194 about this */
focus = None;
ret_to = RevertToPointerRoot;
XGetInputFocus (display->xdisplay, &focus, &ret_to);
XGetInputFocus (the_display->xdisplay, &focus, &ret_to);
/* Force a new FocusIn (does this work?) */
@@ -909,29 +832,29 @@ meta_display_open (void)
*/
if (focus == None || focus == PointerRoot)
/* Just focus the no_focus_window on the first screen */
meta_display_focus_the_no_focus_window (display,
display->screen,
meta_display_focus_the_no_focus_window (the_display,
the_display->screen,
timestamp);
else
{
MetaWindow * window;
window = meta_display_lookup_x_window (display, focus);
window = meta_display_lookup_x_window (the_display, focus);
if (window)
meta_display_set_input_focus_window (display, window, FALSE, timestamp);
meta_display_set_input_focus_window (the_display, window, FALSE, timestamp);
else
/* Just focus the no_focus_window on the first screen */
meta_display_focus_the_no_focus_window (display,
display->screen,
meta_display_focus_the_no_focus_window (the_display,
the_display->screen,
timestamp);
}
meta_error_trap_pop (display);
meta_error_trap_pop (the_display);
}
meta_idle_monitor_init_dbus ();
/* Done opening new display */
display->display_opening = FALSE;
the_display->display_opening = FALSE;
return TRUE;
}
@@ -1040,7 +963,6 @@ meta_display_close (MetaDisplay *display,
guint32 timestamp)
{
g_assert (display != NULL);
g_assert (display == the_display);
if (display->closing != 0)
{
@@ -1054,8 +976,6 @@ meta_display_close (MetaDisplay *display,
meta_display_remove_autoraise_callback (display);
g_clear_object (&display->gesture_tracker);
if (display->focus_timeout_id)
g_source_remove (display->focus_timeout_id);
display->focus_timeout_id = 0;
@@ -1100,6 +1020,50 @@ meta_display_close (MetaDisplay *display,
meta_quit (META_EXIT_SUCCESS);
}
/* Grab/ungrab routines taken from fvwm.
* Calling this function will cause X to ignore all other clients until
* you ungrab. This may not be quite as bad as it sounds, yet there is
* agreement that avoiding server grabs except when they are clearly needed
* is a good thing.
*
* If you do use such grabs, please clearly explain the necessity for their
* usage in a comment. Try to keep their scope extremely limited. In
* particular, try to avoid emitting any signals or notifications while
* a grab is active (if the signal receiver tries to block on an X request
* from another client at this point, you will have a deadlock).
*/
void
meta_display_grab (MetaDisplay *display)
{
if (display->server_grab_count == 0)
{
XGrabServer (display->xdisplay);
}
display->server_grab_count += 1;
meta_verbose ("Grabbing display, grab count now %d\n",
display->server_grab_count);
}
void
meta_display_ungrab (MetaDisplay *display)
{
if (display->server_grab_count == 0)
meta_bug ("Ungrabbed non-grabbed server\n");
display->server_grab_count -= 1;
if (display->server_grab_count == 0)
{
/* FIXME we want to purge all pending "queued" stuff
* at this point, such as window hide/show
*/
XUngrabServer (display->xdisplay);
XFlush (display->xdisplay);
}
meta_verbose ("Ungrabbing display, grab count now %d\n",
display->server_grab_count);
}
/**
* meta_display_for_x_display:
* @xdisplay: An X display
@@ -1379,7 +1343,23 @@ window_raise_with_delay_callback (void *data)
*/
if (meta_stack_get_top (window->screen->stack) != window)
{
if (meta_window_has_pointer (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)
meta_window_raise (window);
else
meta_topic (META_DEBUG_FOCUS,
@@ -1387,7 +1367,7 @@ window_raise_with_delay_callback (void *data)
window->desc);
}
return G_SOURCE_REMOVE;
return FALSE;
}
void
@@ -1534,7 +1514,7 @@ request_xserver_input_focus_change (MetaDisplay *display,
* we know which is which by making two requests that the server will
* process at the same time.
*/
XGrabServer (display->xdisplay);
meta_display_grab (display);
serial = XNextRequest (display->xdisplay);
@@ -1547,8 +1527,7 @@ request_xserver_input_focus_change (MetaDisplay *display,
display->atom__MUTTER_FOCUS_SET,
XA_STRING, 8, PropModeAppend, NULL, 0);
XUngrabServer (display->xdisplay);
XFlush (display->xdisplay);
meta_display_ungrab (display);
meta_display_update_focus_window (display,
meta_window,
@@ -1588,6 +1567,9 @@ meta_display_unregister_x_window (MetaDisplay *display,
g_return_if_fail (g_hash_table_lookup (display->xids, &xwindow) != NULL);
g_hash_table_remove (display->xids, &xwindow);
/* Remove any pending pings */
remove_pending_pings_for_window (display, xwindow);
}
void
@@ -1714,15 +1696,15 @@ meta_display_update_cursor (MetaDisplay *display)
}
static MetaWindow *
get_first_freefloating_window (MetaWindow *window)
get_toplevel_transient_for (MetaWindow *window)
{
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;
while (TRUE)
{
MetaWindow *parent = meta_window_get_transient_for (window);
if (parent == NULL)
return window;
window = parent;
}
}
gboolean
@@ -1770,11 +1752,11 @@ meta_display_begin_grab_op (MetaDisplay *display,
grab_window = window;
/* If we're trying to move a window, move the first
* non-attached dialog instead.
/* If window is a modal dialog attached to its parent,
* grab the parent instead for moving.
*/
if (meta_grab_op_is_moving (op))
grab_window = get_first_freefloating_window (window);
if (meta_window_is_attached_dialog (window) && meta_grab_op_is_moving (op))
grab_window = get_toplevel_transient_for (window);
g_assert (grab_window != NULL);
g_assert (op != META_GRAB_OP_NONE);
@@ -1863,19 +1845,18 @@ void
meta_display_end_grab_op (MetaDisplay *display,
guint32 timestamp)
{
MetaWindow *grab_window = display->grab_window;
MetaGrabOp grab_op = display->grab_op;
meta_topic (META_DEBUG_WINDOW_OPS,
"Ending grab op %u at time %u\n", grab_op, timestamp);
"Ending grab op %u at time %u\n", display->grab_op, timestamp);
if (display->grab_op == META_GRAB_OP_NONE)
return;
g_signal_emit (display, display_signals[GRAB_OP_END], 0,
display->screen, grab_window, grab_op);
display->screen, display->grab_window, display->grab_op);
if (meta_grab_op_is_moving_or_resizing (grab_op))
meta_window_grab_op_ended (display->grab_window, display->grab_op);
if (meta_grab_op_is_moving_or_resizing (display->grab_op))
{
/* Clear out the edge cache */
meta_display_cleanup_edges (display);
@@ -1901,7 +1882,7 @@ meta_display_end_grab_op (MetaDisplay *display,
{
meta_topic (META_DEBUG_WINDOW_OPS,
"Ungrabbing all keys timestamp %u\n", timestamp);
meta_window_ungrab_all_keys (grab_window, timestamp);
meta_window_ungrab_all_keys (display->grab_window, timestamp);
}
display->grab_timestamp = 0;
@@ -1918,8 +1899,6 @@ meta_display_end_grab_op (MetaDisplay *display,
display->grab_resize_timeout_id = 0;
}
meta_window_grab_op_ended (grab_window, grab_op);
if (meta_is_wayland_compositor ())
meta_display_sync_wayland_input_focus (display);
}
@@ -2546,19 +2525,21 @@ 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.
* all windows on @screen.
*
* 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;
@@ -2633,7 +2614,7 @@ meta_display_get_tab_next (MetaDisplay *display,
gboolean skip;
GList *tab_list;
MetaWindow *ret;
tab_list = meta_display_get_tab_list (display, type, workspace);
tab_list = meta_display_get_tab_list (display, type, NULL, workspace);
if (tab_list == NULL)
return NULL;
@@ -3139,6 +3120,12 @@ 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
@@ -3167,6 +3154,12 @@ 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
@@ -3188,34 +3181,3 @@ meta_display_create_x_cursor (MetaDisplay *display,
{
return meta_cursor_create_x_cursor (display->xdisplay, cursor);
}
MetaGestureTracker *
meta_display_get_gesture_tracker (MetaDisplay *display)
{
return display->gesture_tracker;
}
gboolean
meta_display_show_restart_message (MetaDisplay *display,
const char *message)
{
gboolean result = FALSE;
g_signal_emit (display,
display_signals[SHOW_RESTART_MESSAGE], 0,
message, &result);
return result;
}
gboolean
meta_display_request_restart (MetaDisplay *display)
{
gboolean result = FALSE;
g_signal_emit (display,
display_signals[RESTART], 0,
&result);
return result;
}

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -26,11 +26,14 @@
#include "bell.h"
#include <meta/errors.h>
#include "keybindings-private.h"
#include "backends/x11/meta-backend-x11.h"
#define EVENT_MASK (SubstructureRedirectMask | \
StructureNotifyMask | SubstructureNotifyMask | \
ExposureMask | FocusChangeMask)
ExposureMask | \
ButtonPressMask | ButtonReleaseMask | \
PointerMotionMask | PointerMotionHintMask | \
EnterWindowMask | LeaveWindowMask | \
FocusChangeMask)
void
meta_window_ensure_frame (MetaWindow *window)
@@ -106,19 +109,6 @@ meta_window_ensure_frame (MetaWindow *window)
XChangeWindowAttributes (window->display->xdisplay,
frame->xwindow, CWEventMask, &attrs);
{
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
XISetMask (mask.mask, XI_ButtonPress);
XISetMask (mask.mask, XI_ButtonRelease);
XISetMask (mask.mask, XI_Motion);
XISetMask (mask.mask, XI_Enter);
XISetMask (mask.mask, XI_Leave);
XISelectEvents (window->display->xdisplay, frame->xwindow, &mask, 1);
}
meta_display_register_x_window (window->display, &frame->xwindow, window);
meta_error_trap_push (window->display);
@@ -160,16 +150,10 @@ meta_window_ensure_frame (MetaWindow *window)
meta_ui_map_frame (frame->window->screen->ui, frame->xwindow);
{
MetaBackend *backend = meta_get_backend ();
if (META_IS_BACKEND_X11 (backend))
{
/* Since the backend takes keygrabs on another connection, make sure
* to sync the GTK+ connection to ensure that the frame window has
* been created on the server at this point. */
XSync (window->display->xdisplay, False);
}
}
/* Since the backend takes keygrabs on another connection, make sure
* to sync the GTK+ connection to ensure that the frame window has
* been created on the server at this point. */
XSync (window->display->xdisplay, False);
/* Move keybindings to frame instead of window */
meta_window_grab_keys (window);

View File

@@ -55,8 +55,8 @@
#include <X11/XKBlib.h>
#endif
#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"
@@ -1194,8 +1194,9 @@ meta_window_change_keygrabs (MetaWindow *window,
void
meta_window_grab_keys (MetaWindow *window)
{
/* Under Wayland, we don't need to grab at all. */
if (meta_is_wayland_compositor ())
MetaBackend *backend = meta_get_backend ();
if (!META_IS_BACKEND_X11 (backend))
return;
if (window->all_keys_grabbed)
@@ -1222,7 +1223,7 @@ meta_window_grab_keys (MetaWindow *window)
}
meta_window_change_keygrabs (window,
meta_window_x11_get_toplevel_xwindow (window),
meta_window_get_toplevel_xwindow (window),
TRUE);
window->keys_grabbed = TRUE;
@@ -1436,7 +1437,7 @@ meta_window_grab_all_keys (MetaWindow *window,
window->desc);
meta_window_focus (window, timestamp);
grabwindow = meta_window_x11_get_toplevel_xwindow (window);
grabwindow = meta_window_get_toplevel_xwindow (window);
meta_topic (META_DEBUG_KEYBINDINGS,
"Grabbing all keys on window %s\n", window->desc);

View File

@@ -94,6 +94,26 @@ static GMainLoop *meta_main_loop = NULL;
static void prefs_changed_callback (MetaPreference pref,
gpointer data);
/**
* log_handler:
* @log_domain: the domain the error occurred in (we ignore this)
* @log_level: the log level so that we can filter out less
* important messages
* @message: the message to log
* @user_data: arbitrary data (we ignore this)
*
* Prints log messages. If Mutter was compiled with backtrace support,
* also prints a backtrace (see meta_print_backtrace()).
*/
static void
log_handler (const gchar *log_domain,
GLogLevelFlags log_level,
const gchar *message,
gpointer user_data)
{
meta_warning ("Log level %d: %s\n", log_level, message);
}
/**
* meta_print_compilation_info:
*
@@ -367,8 +387,6 @@ meta_init (void)
meta_clutter_init ();
}
meta_restart_init ();
/*
* XXX: We cannot handle high dpi scaling yet, so fix the scale to 1
* for now.
@@ -426,10 +444,24 @@ meta_register_with_session (void)
int
meta_run (void)
{
const gchar *log_domains[] = {
NULL, G_LOG_DOMAIN, "Gtk", "Gdk", "GLib",
"Pango", "GLib-GObject", "GThread"
};
guint i;
/* Load prefs */
meta_prefs_init ();
meta_prefs_add_listener (prefs_changed_callback, NULL);
for (i=0; i<G_N_ELEMENTS(log_domains); i++)
g_log_set_handler (log_domains[i],
G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,
log_handler, NULL);
if (g_getenv ("MUTTER_G_FATAL_WARNINGS") != NULL)
g_log_set_always_fatal (G_LOG_LEVEL_MASK);
meta_ui_set_current_theme (meta_prefs_get_theme ());
/* Try to find some theme that'll work if the theme preference

View File

@@ -309,16 +309,9 @@ accelerator_parse (const gchar *accelerator,
keyval = xkb_keysym_from_name (accelerator, XKB_KEYSYM_CASE_INSENSITIVE);
if (keyval == XKB_KEY_NoSymbol)
{
char *with_xf86 = g_strconcat ("XF86", accelerator, NULL);
keyval = xkb_keysym_from_name (with_xf86, XKB_KEYSYM_CASE_INSENSITIVE);
g_free (with_xf86);
if (keyval == XKB_KEY_NoSymbol)
{
error = TRUE;
goto out;
}
}
error = TRUE;
goto out;
}
}
accelerator += len;

View File

@@ -1,76 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#ifndef META_GESTURE_TRACKER_PRIVATE_H
#define META_GESTURE_TRACKER_PRIVATE_H
#include <glib-object.h>
#include <clutter/clutter.h>
#include <meta/window.h>
#define META_TYPE_GESTURE_TRACKER (meta_gesture_tracker_get_type ())
#define META_GESTURE_TRACKER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_GESTURE_TRACKER, MetaGestureTracker))
#define META_GESTURE_TRACKER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_GESTURE_TRACKER, MetaGestureTrackerClass))
#define META_IS_GESTURE_TRACKER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_GESTURE_TRACKER))
#define META_IS_GESTURE_TRACKER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_GESTURE_TRACKER))
#define META_GESTURE_TRACKER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_GESTURE_TRACKER, MetaGestureTrackerClass))
typedef struct _MetaGestureTracker MetaGestureTracker;
typedef struct _MetaGestureTrackerClass MetaGestureTrackerClass;
typedef enum {
META_SEQUENCE_NONE,
META_SEQUENCE_ACCEPTED,
META_SEQUENCE_REJECTED,
META_SEQUENCE_PENDING_END
} MetaSequenceState;
struct _MetaGestureTracker
{
GObject parent_instance;
};
struct _MetaGestureTrackerClass
{
GObjectClass parent_class;
void (* state_changed) (MetaGestureTracker *tracker,
ClutterEventSequence *sequence,
MetaSequenceState state);
};
GType meta_gesture_tracker_get_type (void) G_GNUC_CONST;
MetaGestureTracker * meta_gesture_tracker_new (void);
gboolean meta_gesture_tracker_handle_event (MetaGestureTracker *tracker,
const ClutterEvent *event);
gboolean meta_gesture_tracker_set_sequence_state (MetaGestureTracker *tracker,
ClutterEventSequence *sequence,
MetaSequenceState state);
MetaSequenceState meta_gesture_tracker_get_sequence_state (MetaGestureTracker *tracker,
ClutterEventSequence *sequence);
gboolean meta_gesture_tracker_consumes_event (MetaGestureTracker *tracker,
const ClutterEvent *event);
#endif /* META_GESTURE_TRACKER_PRIVATE_H */

View File

@@ -1,567 +0,0 @@
/*
* 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>
*/
/**
* SECTION:gesture-tracker
* @Title: MetaGestureTracker
* @Short_Description: Manages gestures on windows/desktop
*
* Forwards touch events to clutter actors, and accepts/rejects touch sequences
* based on the outcome of those.
*/
#include "config.h"
#include "meta-gesture-tracker-private.h"
#include "meta-surface-actor.h"
#define DISTANCE_THRESHOLD 30
typedef struct _MetaGestureTrackerPrivate MetaGestureTrackerPrivate;
typedef struct _GestureActionData GestureActionData;
typedef struct _MetaSequenceInfo MetaSequenceInfo;
struct _MetaSequenceInfo
{
MetaGestureTracker *tracker;
ClutterEventSequence *sequence;
MetaSequenceState state;
guint autodeny_timeout_id;
gfloat start_x;
gfloat start_y;
};
struct _GestureActionData
{
ClutterGestureAction *gesture;
MetaSequenceState state;
guint gesture_begin_id;
guint gesture_end_id;
guint gesture_cancel_id;
};
struct _MetaGestureTrackerPrivate
{
GHashTable *sequences; /* Hashtable of ClutterEventSequence->MetaSequenceInfo */
MetaSequenceState stage_state;
GArray *stage_gestures; /* Array of GestureActionData */
GList *listeners; /* List of ClutterGestureAction */
guint autodeny_timeout;
};
enum {
PROP_0,
PROP_AUTODENY_TIMEOUT,
LAST_PROP,
};
static GParamSpec *obj_props[LAST_PROP];
enum {
STATE_CHANGED,
N_SIGNALS
};
static guint signals[N_SIGNALS] = { 0 };
#define DEFAULT_AUTODENY_TIMEOUT 150
static void meta_gesture_tracker_untrack_stage (MetaGestureTracker *tracker);
G_DEFINE_TYPE_WITH_PRIVATE (MetaGestureTracker, meta_gesture_tracker, G_TYPE_OBJECT)
static void
meta_gesture_tracker_finalize (GObject *object)
{
MetaGestureTrackerPrivate *priv;
priv = meta_gesture_tracker_get_instance_private (META_GESTURE_TRACKER (object));
g_hash_table_destroy (priv->sequences);
g_array_free (priv->stage_gestures, TRUE);
g_list_free (priv->listeners);
G_OBJECT_CLASS (meta_gesture_tracker_parent_class)->finalize (object);
}
static void
meta_gesture_tracker_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MetaGestureTrackerPrivate *priv;
priv = meta_gesture_tracker_get_instance_private (META_GESTURE_TRACKER (object));
switch (prop_id)
{
case PROP_AUTODENY_TIMEOUT:
priv->autodeny_timeout = g_value_get_uint (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_gesture_tracker_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MetaGestureTrackerPrivate *priv;
priv = meta_gesture_tracker_get_instance_private (META_GESTURE_TRACKER (object));
switch (prop_id)
{
case PROP_AUTODENY_TIMEOUT:
g_value_set_uint (value, priv->autodeny_timeout);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_gesture_tracker_class_init (MetaGestureTrackerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_gesture_tracker_finalize;
object_class->set_property = meta_gesture_tracker_set_property;
object_class->get_property = meta_gesture_tracker_get_property;
obj_props[PROP_AUTODENY_TIMEOUT] = g_param_spec_uint ("autodeny-timeout",
"Auto-deny timeout",
"Auto-deny timeout",
0, G_MAXUINT, DEFAULT_AUTODENY_TIMEOUT,
G_PARAM_STATIC_STRINGS |
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_properties (object_class, LAST_PROP, obj_props);
signals[STATE_CHANGED] =
g_signal_new ("state-changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (MetaGestureTrackerClass, state_changed),
NULL, NULL, NULL,
G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_UINT);
}
static gboolean
autodeny_sequence (gpointer user_data)
{
MetaSequenceInfo *info = user_data;
/* Deny the sequence automatically after the given timeout */
if (info->state == META_SEQUENCE_NONE)
meta_gesture_tracker_set_sequence_state (info->tracker, info->sequence,
META_SEQUENCE_REJECTED);
info->autodeny_timeout_id = 0;
return G_SOURCE_REMOVE;
}
static MetaSequenceInfo *
meta_sequence_info_new (MetaGestureTracker *tracker,
const ClutterEvent *event)
{
MetaGestureTrackerPrivate *priv;
MetaSequenceInfo *info;
guint ms;
priv = meta_gesture_tracker_get_instance_private (tracker);
ms = priv->autodeny_timeout;
info = g_slice_new0 (MetaSequenceInfo);
info->tracker = tracker;
info->sequence = event->touch.sequence;
info->state = META_SEQUENCE_NONE;
info->autodeny_timeout_id = g_timeout_add (ms, autodeny_sequence, info);
clutter_event_get_coords (event, &info->start_x, &info->start_y);
return info;
}
static void
meta_sequence_info_free (MetaSequenceInfo *info)
{
if (info->autodeny_timeout_id)
g_source_remove (info->autodeny_timeout_id);
if (info->state == META_SEQUENCE_NONE)
meta_gesture_tracker_set_sequence_state (info->tracker, info->sequence,
META_SEQUENCE_REJECTED);
g_slice_free (MetaSequenceInfo, info);
}
static gboolean
state_is_applicable (MetaSequenceState prev_state,
MetaSequenceState state)
{
if (prev_state == META_SEQUENCE_PENDING_END)
return FALSE;
/* Don't allow reverting to none */
if (state == META_SEQUENCE_NONE)
return FALSE;
/* PENDING_END state is final */
if (prev_state == META_SEQUENCE_PENDING_END)
return FALSE;
/* Sequences must be accepted/denied before PENDING_END */
if (prev_state == META_SEQUENCE_NONE &&
state == META_SEQUENCE_PENDING_END)
return FALSE;
/* Make sequences stick to their accepted/denied state */
if (state != META_SEQUENCE_PENDING_END &&
prev_state != META_SEQUENCE_NONE)
return FALSE;
return TRUE;
}
static gboolean
meta_gesture_tracker_set_state (MetaGestureTracker *tracker,
MetaSequenceState state)
{
MetaGestureTrackerPrivate *priv;
ClutterEventSequence *sequence;
GHashTableIter iter;
priv = meta_gesture_tracker_get_instance_private (tracker);
if (priv->stage_state != state &&
!state_is_applicable (priv->stage_state, state))
return FALSE;
g_hash_table_iter_init (&iter, priv->sequences);
priv->stage_state = state;
while (g_hash_table_iter_next (&iter, (gpointer*) &sequence, NULL))
meta_gesture_tracker_set_sequence_state (tracker, sequence, state);
return TRUE;
}
static gboolean
gesture_begin_cb (ClutterGestureAction *gesture,
ClutterActor *actor,
MetaGestureTracker *tracker)
{
MetaGestureTrackerPrivate *priv;
priv = meta_gesture_tracker_get_instance_private (tracker);
if (!g_list_find (priv->listeners, gesture) &&
meta_gesture_tracker_set_state (tracker, META_SEQUENCE_ACCEPTED))
priv->listeners = g_list_prepend (priv->listeners, gesture);
return TRUE;
}
static void
gesture_end_cb (ClutterGestureAction *gesture,
ClutterActor *actor,
MetaGestureTracker *tracker)
{
MetaGestureTrackerPrivate *priv;
priv = meta_gesture_tracker_get_instance_private (tracker);
priv->listeners = g_list_remove (priv->listeners, gesture);
if (!priv->listeners)
meta_gesture_tracker_untrack_stage (tracker);
}
static void
gesture_cancel_cb (ClutterGestureAction *gesture,
ClutterActor *actor,
MetaGestureTracker *tracker)
{
MetaGestureTrackerPrivate *priv;
priv = meta_gesture_tracker_get_instance_private (tracker);
if (g_list_find (priv->listeners, gesture))
{
priv->listeners = g_list_remove (priv->listeners, gesture);
if (!priv->listeners)
meta_gesture_tracker_set_state (tracker, META_SEQUENCE_PENDING_END);
}
}
static gboolean
cancel_and_unref_gesture_cb (ClutterGestureAction *action)
{
clutter_gesture_action_cancel (action);
g_object_unref (action);
return G_SOURCE_REMOVE;
}
static void
clear_gesture_data (GestureActionData *data)
{
g_signal_handler_disconnect (data->gesture, data->gesture_begin_id);
g_signal_handler_disconnect (data->gesture, data->gesture_end_id);
g_signal_handler_disconnect (data->gesture, data->gesture_cancel_id);
/* Defer cancellation to an idle, as it may happen within event handling */
g_idle_add ((GSourceFunc) cancel_and_unref_gesture_cb, data->gesture);
}
static void
meta_gesture_tracker_init (MetaGestureTracker *tracker)
{
MetaGestureTrackerPrivate *priv;
priv = meta_gesture_tracker_get_instance_private (tracker);
priv->sequences = g_hash_table_new_full (NULL, NULL, NULL,
(GDestroyNotify) meta_sequence_info_free);
priv->stage_gestures = g_array_new (FALSE, FALSE, sizeof (GestureActionData));
g_array_set_clear_func (priv->stage_gestures, (GDestroyNotify) clear_gesture_data);
}
MetaGestureTracker *
meta_gesture_tracker_new (void)
{
return g_object_new (META_TYPE_GESTURE_TRACKER, NULL);
}
static void
meta_gesture_tracker_track_stage (MetaGestureTracker *tracker,
ClutterActor *stage)
{
MetaGestureTrackerPrivate *priv;
GList *actions, *l;
priv = meta_gesture_tracker_get_instance_private (tracker);
actions = clutter_actor_get_actions (stage);
for (l = actions; l; l = l->next)
{
GestureActionData data;
if (!CLUTTER_IS_GESTURE_ACTION (l->data))
continue;
data.gesture = g_object_ref (l->data);
data.state = META_SEQUENCE_NONE;
data.gesture_begin_id =
g_signal_connect (data.gesture, "gesture-begin",
G_CALLBACK (gesture_begin_cb), tracker);
data.gesture_end_id =
g_signal_connect (data.gesture, "gesture-end",
G_CALLBACK (gesture_end_cb), tracker);
data.gesture_cancel_id =
g_signal_connect (data.gesture, "gesture-cancel",
G_CALLBACK (gesture_cancel_cb), tracker);
g_array_append_val (priv->stage_gestures, data);
}
g_list_free (actions);
}
static void
meta_gesture_tracker_untrack_stage (MetaGestureTracker *tracker)
{
MetaGestureTrackerPrivate *priv;
priv = meta_gesture_tracker_get_instance_private (tracker);
priv->stage_state = META_SEQUENCE_NONE;
g_hash_table_remove_all (priv->sequences);
if (priv->stage_gestures->len > 0)
g_array_remove_range (priv->stage_gestures, 0, priv->stage_gestures->len);
g_list_free (priv->listeners);
priv->listeners = NULL;
}
gboolean
meta_gesture_tracker_handle_event (MetaGestureTracker *tracker,
const ClutterEvent *event)
{
MetaGestureTrackerPrivate *priv;
ClutterEventSequence *sequence;
MetaSequenceInfo *info;
ClutterActor *stage;
gfloat x, y;
sequence = clutter_event_get_event_sequence (event);
if (!sequence)
return FALSE;
priv = meta_gesture_tracker_get_instance_private (tracker);
stage = CLUTTER_ACTOR (clutter_event_get_stage (event));
switch (event->type)
{
case CLUTTER_TOUCH_BEGIN:
if (g_hash_table_size (priv->sequences) == 0)
meta_gesture_tracker_track_stage (tracker, stage);
info = meta_sequence_info_new (tracker, event);
g_hash_table_insert (priv->sequences, sequence, info);
if (priv->stage_gestures->len == 0)
{
/* If no gestures are attached, reject the sequence right away */
meta_gesture_tracker_set_sequence_state (tracker, sequence,
META_SEQUENCE_REJECTED);
}
else if (priv->stage_state != META_SEQUENCE_NONE)
{
/* Make the sequence state match the general state */
meta_gesture_tracker_set_sequence_state (tracker, sequence,
priv->stage_state);
}
break;
case CLUTTER_TOUCH_END:
info = g_hash_table_lookup (priv->sequences, sequence);
if (!info)
return FALSE;
/* If nothing was done yet about the sequence, reject it so X11
* clients may see it
*/
if (info->state == META_SEQUENCE_NONE)
meta_gesture_tracker_set_sequence_state (tracker, sequence,
META_SEQUENCE_REJECTED);
g_hash_table_remove (priv->sequences, sequence);
if (g_hash_table_size (priv->sequences) == 0)
meta_gesture_tracker_untrack_stage (tracker);
break;
case CLUTTER_TOUCH_UPDATE:
info = g_hash_table_lookup (priv->sequences, sequence);
if (!info)
return FALSE;
clutter_event_get_coords (event, &x, &y);
if (info->state == META_SEQUENCE_NONE &&
(ABS (info->start_x - x) > DISTANCE_THRESHOLD ||
ABS (info->start_y - y) > DISTANCE_THRESHOLD))
meta_gesture_tracker_set_sequence_state (tracker, sequence,
META_SEQUENCE_REJECTED);
break;
default:
return FALSE;
break;
}
return TRUE;
}
gboolean
meta_gesture_tracker_set_sequence_state (MetaGestureTracker *tracker,
ClutterEventSequence *sequence,
MetaSequenceState state)
{
MetaGestureTrackerPrivate *priv;
MetaSequenceInfo *info;
g_return_val_if_fail (META_IS_GESTURE_TRACKER (tracker), FALSE);
priv = meta_gesture_tracker_get_instance_private (tracker);
info = g_hash_table_lookup (priv->sequences, sequence);
if (!info)
return FALSE;
else if (state == info->state)
return TRUE;
if (!state_is_applicable (info->state, state))
return FALSE;
/* Unset autodeny timeout */
if (info->autodeny_timeout_id)
{
g_source_remove (info->autodeny_timeout_id);
info->autodeny_timeout_id = 0;
}
info->state = state;
g_signal_emit (tracker, signals[STATE_CHANGED], 0, sequence, info->state);
/* If the sequence was denied, set immediately to PENDING_END after emission */
if (state == META_SEQUENCE_REJECTED)
{
info->state = META_SEQUENCE_PENDING_END;
g_signal_emit (tracker, signals[STATE_CHANGED], 0, sequence, info->state);
}
return TRUE;
}
MetaSequenceState
meta_gesture_tracker_get_sequence_state (MetaGestureTracker *tracker,
ClutterEventSequence *sequence)
{
MetaGestureTrackerPrivate *priv;
MetaSequenceInfo *info;
g_return_val_if_fail (META_IS_GESTURE_TRACKER (tracker), META_SEQUENCE_PENDING_END);
priv = meta_gesture_tracker_get_instance_private (tracker);
info = g_hash_table_lookup (priv->sequences, sequence);
if (!info)
return META_SEQUENCE_PENDING_END;
return info->state;
}
gboolean
meta_gesture_tracker_consumes_event (MetaGestureTracker *tracker,
const ClutterEvent *event)
{
ClutterEventSequence *sequence;
MetaSequenceState state;
g_return_val_if_fail (META_IS_GESTURE_TRACKER (tracker), FALSE);
sequence = clutter_event_get_event_sequence (event);
if (!sequence)
return FALSE;
state = meta_gesture_tracker_get_sequence_state (tracker, sequence);
return (event->type != CLUTTER_TOUCH_END &&
(state == META_SEQUENCE_REJECTED || state == META_SEQUENCE_PENDING_END));
}

View File

@@ -1234,7 +1234,6 @@ 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;
@@ -1248,13 +1247,8 @@ 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

@@ -1,82 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* SECTION:restart-helper
* @short_description: helper program during a restart
*
* To smoothly restart Mutter, we want to keep the composite
* overlay window enabled during the restart. This is done by
* spawning this program, which keeps a reference to the the composite
* overlay window until Mutter picks it back up.
*/
/*
* Copyright (C) 2014 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xcomposite.h>
int
main (int argc,
char **argv)
{
Display *display = XOpenDisplay (NULL);
Window selection_window;
XSetWindowAttributes xwa;
unsigned long mask = 0;
xwa.override_redirect = True;
mask |= CWOverrideRedirect;
XCompositeGetOverlayWindow (display, DefaultRootWindow (display));
selection_window = XCreateWindow (display,
DefaultRootWindow (display),
-100, -100, 1, 1, 0,
0,
InputOnly,
DefaultVisual (display, DefaultScreen (display)),
mask, &xwa);
XSetSelectionOwner (display,
XInternAtom (display, "_MUTTER_RESTART_HELPER", False),
selection_window,
CurrentTime);
/* Mutter looks for an (arbitrary) line printed to stdout to know that
* we have started and have a reference to the COW. XSync() so that
* everything is set on the X server before Mutter starts restarting.
*/
XSync (display, False);
printf ("STARTED\n");
fflush (stdout);
while (True)
{
XEvent xev;
XNextEvent (display, &xev);
/* Mutter restarted and unset the selection to indicate that
* it has a reference on the COW again */
if (xev.xany.type == SelectionClear)
return 0;
}
}

View File

@@ -1,212 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2014 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/*
* SECTION:restart
* @short_description: Smoothly restart the compositor
*
* There are some cases where we need to restart Mutter in order
* to deal with changes in state - the particular case inspiring
* this is enabling or disabling stereo output. To make this
* fairly smooth for the user, we need to do two things:
*
* - Display a message to the user and make sure that it is
* actually painted before we exit.
* - Use a helper program so that the Composite Overlay Window
* isn't unmapped and mapped.
*
* This handles both of these.
*/
#include <config.h>
#include <clutter/clutter.h>
#include <gio/gunixinputstream.h>
#include <meta/main.h>
#include "ui.h"
#include "util-private.h"
#include "display-private.h"
static gboolean restart_helper_started = FALSE;
static gboolean restart_message_shown = FALSE;
static gboolean is_restart = FALSE;
void
meta_restart_init (void)
{
Display *xdisplay = meta_ui_get_display ();
Atom atom_restart_helper = XInternAtom (xdisplay, "_MUTTER_RESTART_HELPER", False);
Window restart_helper_window = None;
restart_helper_window = XGetSelectionOwner (xdisplay, atom_restart_helper);
if (restart_helper_window)
is_restart = TRUE;
}
static void
restart_check_ready (void)
{
if (restart_helper_started && restart_message_shown)
meta_display_request_restart (meta_get_display ());
}
static void
restart_helper_read_line_callback (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
GError *error = NULL;
gsize length;
char *line = g_data_input_stream_read_line_finish_utf8 (G_DATA_INPUT_STREAM (source_object),
res,
&length, &error);
if (line == NULL)
{
meta_warning ("Failed to read output from restart helper%s%s\n",
error ? ": " : NULL,
error ? error->message : NULL);
}
else
g_free (line); /* We don't actually care what the restart helper outputs */
g_object_unref (source_object);
restart_helper_started = TRUE;
restart_check_ready ();
}
static gboolean
restart_message_painted (gpointer data)
{
restart_message_shown = TRUE;
restart_check_ready ();
return FALSE;
}
/**
* meta_restart:
* @message: message to display to the user.
*
* Starts the process of restarting the compositor. Note that Mutter's
* involvement here is to make the restart visually smooth for the
* user - it cannot itself safely reexec a program that embeds libmuttter.
* So in order for this to work, the compositor must handle two
* signals - MetaDisplay::show-restart-message, to display the
* message passed here on the Clutter stage, and ::restart to actually
* reexec the compositor.
*/
void
meta_restart (const char *message)
{
MetaDisplay *display = meta_get_display();
GInputStream *unix_stream;
GDataInputStream *data_stream;
GError *error = NULL;
int helper_out_fd;
static const char * const helper_argv[] = {
MUTTER_LIBEXECDIR "/mutter-restart-helper", NULL
};
if (meta_display_show_restart_message (display, message))
{
/* Wait until the stage was painted */
clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT,
restart_message_painted,
NULL, NULL);
}
else
{
/* Can't show the message, show the message as soon as the
* restart helper starts
*/
restart_message_painted (NULL);
}
/* We also need to wait for the restart helper to get its
* reference to the Composite Overlay Window.
*/
if (!g_spawn_async_with_pipes (NULL, /* working directory */
(char **)helper_argv,
NULL, /* envp */
G_SPAWN_DEFAULT,
NULL, NULL, /* child_setup */
NULL, /* child_pid */
NULL, /* standard_input */
&helper_out_fd,
NULL, /* standard_error */
&error))
{
meta_warning ("Failed to start restart helper: %s\n", error->message);
goto error;
}
unix_stream = g_unix_input_stream_new (helper_out_fd, TRUE);
data_stream = g_data_input_stream_new (unix_stream);
g_object_unref (unix_stream);
g_data_input_stream_read_line_async (data_stream, G_PRIORITY_DEFAULT,
NULL, restart_helper_read_line_callback,
&error);
if (error != NULL)
{
meta_warning ("Failed to read from restart helper: %s\n", error->message);
g_object_unref (data_stream);
goto error;
}
return;
error:
/* If starting the restart helper fails, then we just go ahead and restart
* immediately. We won't get a smooth transition, since the overlay window
* will be destroyed and recreated, but otherwise it will work fine.
*/
restart_helper_started = TRUE;
restart_check_ready ();
return;
}
void
meta_restart_finish (void)
{
if (is_restart)
{
Display *xdisplay = meta_display_get_xdisplay (meta_get_display ());
Atom atom_restart_helper = XInternAtom (xdisplay, "_MUTTER_RESTART_HELPER", False);
XSetSelectionOwner (xdisplay, atom_restart_helper, None, CurrentTime);
}
}
/**
* meta_is_restart:
*
* Returns %TRUE if this instance of Mutter comes from Mutter
* restarting itself (for example to enable/disable stereo.)
* See meta_restart(). If this is the case, any startup visuals
* or animations should be suppressed.
*/
gboolean
meta_is_restart (void)
{
return is_restart;
}

View File

@@ -119,8 +119,6 @@ struct _MetaScreen
* and restack them below a guard window. When using a compositor
* this allows us to provide live previews of unmapped windows */
Window guard_window;
Window composite_overlay_window;
};
struct _MetaScreenClass
@@ -137,7 +135,6 @@ 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

@@ -45,7 +45,6 @@
#include "meta-cursor-tracker-private.h"
#include <X11/extensions/Xinerama.h>
#include <X11/extensions/Xcomposite.h>
#include <X11/Xatom.h>
#include <locale.h>
@@ -56,8 +55,6 @@
#include "x11/window-x11.h"
#include "x11/xprops.h"
#include "backends/x11/meta-backend-x11.h"
static char* get_screen_name (MetaDisplay *display,
int number);
@@ -472,24 +469,13 @@ create_guard_window (Display *xdisplay, MetaScreen *screen)
XStoreName (xdisplay, guard_window, "mutter guard window");
{
if (!meta_is_wayland_compositor ())
{
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
Display *backend_xdisplay = meta_backend_x11_get_xdisplay (backend);
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
XISetMask (mask.mask, XI_ButtonPress);
XISetMask (mask.mask, XI_ButtonRelease);
XISetMask (mask.mask, XI_Motion);
/* Sync on the connection we created the window on to
* make sure it's created before we select on it on the
* backend connection. */
XSync (xdisplay, False);
XISelectEvents (backend_xdisplay, guard_window, &mask, 1);
}
XISetMask (mask.mask, XI_ButtonPress);
XISetMask (mask.mask, XI_ButtonRelease);
XISetMask (mask.mask, XI_Motion);
XISelectEvents (xdisplay, guard_window, &mask, 1);
}
stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
@@ -506,15 +492,6 @@ create_guard_window (Display *xdisplay, MetaScreen *screen)
return guard_window;
}
/* Set a black background on the root window so that we don't
* see confusing old copies of old windows when debugging
* and testing. */
static void
meta_screen_set_background (MetaScreen *screen)
{
XSetWindowBackground (screen->display->xdisplay, screen->xroot, 0x00000000);
}
MetaScreen*
meta_screen_new (MetaDisplay *display,
int number,
@@ -529,6 +506,7 @@ 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 ();
@@ -634,15 +612,24 @@ meta_screen_new (MetaDisplay *display,
/* select our root window events */
meta_error_trap_push (display);
/* We need to or with the existing event mask since
* gtk+ may be interested in other events.
*/
{
long event_mask;
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
XWindowAttributes attr;
meta_core_add_old_event_mask (xdisplay, xroot, &mask);
XISetMask (mask.mask, XI_KeyPress);
XISetMask (mask.mask, XI_KeyRelease);
XISetMask (mask.mask, XI_Enter);
XISetMask (mask.mask, XI_Leave);
XISetMask (mask.mask, XI_FocusIn);
XISetMask (mask.mask, XI_FocusOut);
XISetMask (mask.mask, XI_Motion);
#ifdef HAVE_XI23
if (META_DISPLAY_HAS_XINPUT_23 (display))
{
@@ -654,6 +641,9 @@ meta_screen_new (MetaDisplay *display,
event_mask = (SubstructureRedirectMask | SubstructureNotifyMask |
StructureNotifyMask | ColormapChangeMask | PropertyChangeMask);
if (XGetWindowAttributes (xdisplay, xroot, &attr))
event_mask |= attr.your_event_mask;
XSelectInput (xdisplay, xroot, event_mask);
}
@@ -667,9 +657,6 @@ meta_screen_new (MetaDisplay *display,
return NULL;
}
/* Select for cursor changes so the cursor tracker is up to date. */
XFixesSelectCursorInput (xdisplay, xroot, XFixesDisplayCursorNotifyMask);
screen = g_object_new (META_TYPE_SCREEN, NULL);
screen->closing = 0;
@@ -710,16 +697,9 @@ meta_screen_new (MetaDisplay *display,
screen->starting_corner = META_SCREEN_TOPLEFT;
screen->guard_window = None;
screen->composite_overlay_window = XCompositeGetOverlayWindow (xdisplay, xroot);
/* Now that we've gotten taken a reference count on the COW, we
* can close the helper that is holding on to it */
meta_restart_finish ();
reload_monitor_infos (screen);
meta_screen_set_cursor (screen, META_CURSOR_DEFAULT);
meta_screen_set_background (screen);
/* Handle creating a no_focus_window for this screen */
screen->no_focus_window =
@@ -741,10 +721,24 @@ 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_new (screen);
meta_workspace_activate (meta_workspace_new (screen), timestamp);
update_num_workspaces (screen, timestamp);
set_workspace_names (screen);
screen->keys_grabbed = FALSE;
meta_screen_grab_keys (screen);
@@ -770,47 +764,23 @@ 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");
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);
else
meta_workspace_activate (screen->workspaces->data, timestamp);
}
void
meta_screen_free (MetaScreen *screen,
guint32 timestamp)
@@ -821,6 +791,8 @@ meta_screen_free (MetaScreen *screen,
screen->closing += 1;
meta_display_grab (display);
meta_compositor_unmanage (screen->display->compositor);
meta_display_unmanage_windows_for_screen (display, screen, timestamp);
@@ -877,6 +849,9 @@ meta_screen_free (MetaScreen *screen,
g_free (screen->screen_name);
g_object_unref (screen);
XFlush (display->xdisplay);
meta_display_ungrab (display);
}
void

View File

@@ -234,36 +234,32 @@ meta_stack_op_dump (MetaStackOp *op,
g_free (window_id);
}
static void
stack_dump (GArray *stack)
{
guint i;
meta_push_no_msg_prefix ();
for (i = 0; i < stack->len; i++)
{
MetaStackWindow *window = &g_array_index (stack, MetaStackWindow, i);
char *window_id = get_window_id (window);
meta_topic (META_DEBUG_STACK, " %s", window_id);
g_free (window_id);
}
meta_topic (META_DEBUG_STACK, "\n");
meta_pop_no_msg_prefix ();
}
static void
meta_stack_tracker_dump (MetaStackTracker *tracker)
{
guint i;
GList *l;
meta_topic (META_DEBUG_STACK, "MetaStackTracker state (screen=%d)\n", tracker->screen->number);
meta_push_no_msg_prefix ();
meta_topic (META_DEBUG_STACK, " xserver_serial: %ld\n", tracker->xserver_serial);
meta_topic (META_DEBUG_STACK, " xserver_stack: ");
stack_dump (tracker->xserver_stack);
meta_topic (META_DEBUG_STACK, " verfied_stack: ");
stack_dump (tracker->verified_stack);
meta_topic (META_DEBUG_STACK, " unverified_predictions: [");
for (i = 0; i < tracker->xserver_stack->len; i++)
{
MetaStackWindow *window = &g_array_index (tracker->xserver_stack, MetaStackWindow, i);
char *window_id = get_window_id (window);
meta_topic (META_DEBUG_STACK, " %s", window_id);
g_free (window_id);
}
meta_topic (META_DEBUG_STACK, "\n verfied_stack: ");
for (i = 0; i < tracker->verified_stack->len; i++)
{
MetaStackWindow *window = &g_array_index (tracker->verified_stack, MetaStackWindow, i);
char *window_id = get_window_id (window);
meta_topic (META_DEBUG_STACK, " %s", window_id);
g_free (window_id);
}
meta_topic (META_DEBUG_STACK, "\n unverified_predictions: [");
for (l = tracker->unverified_predictions->head; l; l = l->next)
{
MetaStackOp *op = l->data;
@@ -273,8 +269,15 @@ meta_stack_tracker_dump (MetaStackTracker *tracker)
if (tracker->predicted_stack)
{
meta_topic (META_DEBUG_STACK, "\n predicted_stack: ");
stack_dump (tracker->predicted_stack);
for (i = 0; i < tracker->predicted_stack->len; i++)
{
MetaStackWindow *window = &g_array_index (tracker->predicted_stack, MetaStackWindow, i);
char *window_id = get_window_id (window);
meta_topic (META_DEBUG_STACK, " %s", window_id);
g_free (window_id);
}
}
meta_topic (META_DEBUG_STACK, "\n");
meta_pop_no_msg_prefix ();
}
@@ -482,12 +485,14 @@ requery_xserver_stack (MetaStackTracker *tracker)
screen->xroot,
&ignored1, &ignored2, &children, &n_children);
tracker->xserver_stack = g_array_sized_new (FALSE, FALSE, sizeof (MetaStackWindow), n_children);
tracker->xserver_stack =
g_array_sized_new (FALSE, FALSE, sizeof (MetaStackWindow), n_children);
g_array_set_size (tracker->xserver_stack, n_children);
for (i = 0; i < n_children; i++)
{
MetaStackWindow *window = &g_array_index (tracker->xserver_stack, MetaStackWindow, i);
MetaStackWindow *window =
&g_array_index (tracker->xserver_stack, MetaStackWindow, i);
window->any.type = META_WINDOW_CLIENT_TYPE_X11;
window->x11.xwindow = children[i];
}
@@ -709,10 +714,14 @@ meta_stack_tracker_record_lower (MetaStackTracker *tracker,
*
* Return value: %TRUE if the predicted state is consistent with
* receiving the given @op from X, else %FALSE.
*
* @modified will be set to %TRUE if tracker->verified_stack is
* changed by applying any newly validated operations, else %FALSE.
*/
static gboolean
stack_tracker_verify_predictions (MetaStackTracker *tracker,
MetaStackOp *op)
MetaStackOp *op,
gboolean *modified)
{
GArray *tmp_predicted_stack = NULL;
GArray *predicted_stack;
@@ -722,8 +731,6 @@ stack_tracker_verify_predictions (MetaStackTracker *tracker,
* passed to this api. */
g_return_val_if_fail (op->any.window.any.type == META_WINDOW_CLIENT_TYPE_X11, FALSE);
meta_topic (META_DEBUG_STACK, "Verifying predictions:\n");
if (tracker->unverified_predictions->length)
{
GList *l;
@@ -743,9 +750,6 @@ stack_tracker_verify_predictions (MetaStackTracker *tracker,
else
predicted_stack = tracker->verified_stack;
meta_topic (META_DEBUG_STACK, " predicted_stack: ");
stack_dump (predicted_stack);
switch (op->any.type)
{
case STACK_OP_ADD:
@@ -821,6 +825,7 @@ verified:
meta_stack_op_free (queued_op);
}
*modified = modified_stack;
if (modified_stack)
{
g_array_free (tracker->verified_stack, TRUE);
@@ -842,6 +847,8 @@ not_verified:
tracker->predicted_stack = NULL;
}
*modified = FALSE;
return FALSE;
}
@@ -874,17 +881,17 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker)
* windows and free the queue of unverified_predictions.
*
* - Iterate through the x windows listed in verified_stack at the
* same time as iterating the windows in xserver_stack. (Stop
* when we reach the end of the xserver_stack)
* same time as iterating the windows in xserver_list. (Stop
* when we reach the end of the xserver_list)
* - If the window found doesn't match the window expected
* according to the order of xserver_stack then:
* according to the order of xserver_list then:
* - Look ahead for the window we were expecting and restack
* that above the previous X window. If we fail to find the
* expected window then create a new entry for it and stack
* that.
*
* - Continue to iterate through verified_stack for any remaining
* X windows that we now know aren't in the xserver_stack and
* X windows that we now know aren't in the xserver_list and
* remove them.
*
* - Free ->predicted_stack if any.
@@ -902,11 +909,15 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker)
g_queue_clear (tracker->unverified_predictions);
j = 0;
expected_xwindow = &g_array_index (tracker->xserver_stack, MetaStackWindow, j);
expected_xwindow =
&g_array_index (tracker->xserver_stack, MetaStackWindow, j);
for (i = 0; i < tracker->verified_stack->len; )
for (i = 0;
i < tracker->verified_stack->len;
)
{
MetaStackWindow *current = &g_array_index (tracker->verified_stack, MetaStackWindow, i);
MetaStackWindow *current =
&g_array_index (tracker->verified_stack, MetaStackWindow, i);
if (current->any.type != META_WINDOW_CLIENT_TYPE_X11)
{
@@ -943,7 +954,8 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker)
/* Technically we only need to look forward from i if we
* wanted to optimize this a bit... */
expected_index = find_window (tracker->verified_stack, expected_xwindow);
expected_index =
find_window (tracker->verified_stack, expected_xwindow);
if (expected_index >= 0)
{
@@ -981,7 +993,8 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker)
i++;
j++;
expected_xwindow = &g_array_index (tracker->xserver_stack, MetaStackWindow, j);
expected_xwindow =
&g_array_index (tracker->xserver_stack, MetaStackWindow, j);
if (j >= tracker->xserver_stack->len)
break;
@@ -991,7 +1004,8 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker)
* xserver_stack and so we can remove them. */
while (i < tracker->verified_stack->len)
{
MetaStackWindow *current = &g_array_index (tracker->verified_stack, MetaStackWindow, i);
MetaStackWindow *current =
&g_array_index (tracker->verified_stack, MetaStackWindow, i);
if (current->any.type == META_WINDOW_CLIENT_TYPE_X11)
g_array_remove_index (tracker->verified_stack, i);
@@ -1002,10 +1016,11 @@ resync_verified_stack_with_xserver_stack (MetaStackTracker *tracker)
}
/* If we get to the end of verified_list and there are any remaining
* entries in xserver_stack then append them all to the end */
* entries in xserver_list then append them all to the end */
for (; j < tracker->xserver_stack->len; j++)
{
MetaStackWindow *current = &g_array_index (tracker->xserver_stack, MetaStackWindow, j);
MetaStackWindow *current =
&g_array_index (tracker->xserver_stack, MetaStackWindow, j);
g_array_append_val (tracker->verified_stack, *current);
modified_stack = TRUE;
@@ -1029,13 +1044,19 @@ static void
stack_tracker_event_received (MetaStackTracker *tracker,
MetaStackOp *op)
{
/* If the event is older than our latest requery, then it's
* already included in our tree. Just ignore it. */
if (op->any.serial < tracker->xserver_serial)
return;
gboolean need_sync = FALSE;
gboolean verified;
meta_stack_op_dump (op, "Stack op event received: ", "\n");
if (op->any.serial < tracker->xserver_serial)
{
/* g_warning ("Spurious X event received affecting stack; doing full re-query"); */
resync_verified_stack_with_xserver_stack (tracker);
meta_stack_tracker_dump (tracker);
return;
}
tracker->xserver_serial = op->any.serial;
/* XXX: With the design we have ended up with it looks like we've
@@ -1049,8 +1070,13 @@ stack_tracker_event_received (MetaStackTracker *tracker,
*/
meta_stack_op_apply (op, tracker->xserver_stack);
if (!stack_tracker_verify_predictions (tracker, op))
resync_verified_stack_with_xserver_stack (tracker);
verified = stack_tracker_verify_predictions (tracker, op, &need_sync);
if (!verified)
{
resync_verified_stack_with_xserver_stack (tracker);
meta_stack_tracker_dump (tracker);
return;
}
meta_stack_tracker_dump (tracker);
}

View File

@@ -25,7 +25,6 @@
#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
@@ -239,7 +238,7 @@ static GSList*
get_strut_list (int which)
{
GSList *ans;
MetaSide wc = 0; /* wc == who cares? ;-) */
MetaDirection wc = 0; /* wc == who cares? ;-) */
ans = NULL;
@@ -249,32 +248,32 @@ get_strut_list (int which)
case 0:
break;
case 1:
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));
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));
break;
case 2:
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));
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));
break;
case 3:
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 ( 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 ( 700, 525, 200, 150, wc));
break;
case 4:
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));
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));
break;
case 5:
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));
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));
break;
case 6:
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));
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));
break;
}
@@ -624,9 +623,15 @@ 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, 1220, 1180)); /* 377600 */
tmp = g_list_prepend (tmp, new_meta_rect ( 0, 20, 1600, 1130)); /* 791000 */
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 */
#if 0
printf ("Got to here...\n");
char region_list[(RECT_LENGTH+2) * g_list_length (region)];
@@ -1327,7 +1332,6 @@ test_gravity_resize ()
printf ("%s passed.\n", G_STRFUNC);
}
#define EPSILON 0.000000001
static void
test_find_closest_point_to_line ()
{
@@ -1342,7 +1346,7 @@ test_find_closest_point_to_line ()
x2, y2,
px, py,
&rx, &ry);
g_assert (fabs (rx - answer_x) < EPSILON && fabs (ry - answer_y) < EPSILON);
g_assert (rx == answer_x && ry == answer_y);
/* Special test for x1 == x2, so that slop of line is infinite */
x1 = 3.0; y1 = 49.0;
@@ -1353,7 +1357,7 @@ test_find_closest_point_to_line ()
x2, y2,
px, py,
&rx, &ry);
g_assert (fabs (rx - answer_x) < EPSILON && fabs (ry - answer_y) < EPSILON);
g_assert (rx == answer_x && ry == answer_y);
/* Special test for y1 == y2, so perp line has slope of infinity */
x1 = 3.14; y1 = 7.0;
@@ -1364,7 +1368,7 @@ test_find_closest_point_to_line ()
x2, y2,
px, py,
&rx, &ry);
g_assert (fabs (rx - answer_x) < EPSILON && fabs (ry - answer_y) < EPSILON);
g_assert (rx == answer_x && ry == answer_y);
/* Test when we the point we want to be closest to is actually on the line */
x1 = 3.0; y1 = 49.0;
@@ -1375,7 +1379,7 @@ test_find_closest_point_to_line ()
x2, y2,
px, py,
&rx, &ry);
g_assert (fabs (rx - answer_x) < EPSILON && fabs (ry - answer_y) < EPSILON);
g_assert (rx == answer_x && ry == answer_y);
printf ("%s passed.\n", G_STRFUNC);
}

View File

@@ -43,6 +43,7 @@
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <clutter/clutter.h>
#include "x11/iconcache.h"
#include "x11/group-private.h"
#include "wayland/meta-wayland-types.h"
@@ -106,6 +107,9 @@ struct _MetaWindow
GdkPixbuf *icon;
GdkPixbuf *mini_icon;
MetaIconCache icon_cache;
Pixmap wm_hints_pixmap;
Pixmap wm_hints_mask;
MetaWindowType type;
@@ -162,7 +166,6 @@ struct _MetaWindow
* that to toggle between normal/tiled or maximized/tiled states. */
guint saved_maximize : 1;
int tile_monitor_number;
int preferred_output_winsys_id;
/* Whether we're shaded */
guint shaded : 1;
@@ -347,6 +350,10 @@ struct _MetaWindow
/* whether or not the window is from a program running on another machine */
guint is_remote : 1;
/* Used for Wayland -- surfaces can behave as if they were unmapped if
* they have a NULL buffer attached... */
guint surface_mapped;
/* if non-NULL, the bounds of the window frame */
cairo_region_t *frame_bounds;
@@ -414,15 +421,6 @@ 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;
@@ -480,9 +478,6 @@ struct _MetaWindowClass
void (*get_default_skip_hints) (MetaWindow *window,
gboolean *skip_taskbar_out,
gboolean *skip_pager_out);
gboolean (*update_icon) (MetaWindow *window,
GdkPixbuf **icon,
GdkPixbuf **mini_icon);
};
/* These differ from window->has_foo_func in that they consider
@@ -580,10 +575,6 @@ 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);
@@ -627,6 +618,8 @@ void meta_window_stack_just_below (MetaWindow *window,
void meta_window_set_user_time (MetaWindow *window,
guint32 timestamp);
void meta_window_update_icon_now (MetaWindow *window);
void meta_window_update_for_monitors_changed (MetaWindow *window);
void meta_window_update_on_all_workspaces (MetaWindow *window);
@@ -668,6 +661,11 @@ void meta_window_handle_leave (MetaWindow *window);
gboolean meta_window_handle_ungrabbed_event (MetaWindow *window,
const ClutterEvent *event);
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,8 +676,9 @@ void meta_window_activate_full (MetaWindow *window,
MetaClientType source_indication,
MetaWorkspace *workspace);
void meta_window_update_monitor (MetaWindow *window,
gboolean user_op);
gboolean meta_window_is_client_decorated (MetaWindow *window);
void meta_window_update_monitor (MetaWindow *window);
void meta_window_set_urgent (MetaWindow *window,
gboolean urgent);
@@ -699,6 +698,4 @@ 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

File diff suppressed because it is too large Load Diff

View File

@@ -1040,45 +1040,6 @@ 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

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -5,9 +5,14 @@ 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
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}

View File

@@ -43,6 +43,8 @@
#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,8 +101,9 @@ void meta_compositor_unmaximize_window (MetaCompositor *compositor,
void meta_compositor_sync_window_geometry (MetaCompositor *compositor,
MetaWindow *window,
gboolean did_placement);
void meta_compositor_sync_updates_frozen (MetaCompositor *compositor,
MetaWindow *window);
void meta_compositor_set_updates_frozen (MetaCompositor *compositor,
MetaWindow *window,
gboolean updates_frozen);
void meta_compositor_queue_frame_drawn (MetaCompositor *compositor,
MetaWindow *window,
gboolean no_delay_frame);
@@ -126,9 +127,5 @@ 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,6 +75,7 @@ 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);
@@ -83,6 +84,7 @@ 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,
@@ -94,6 +96,7 @@ 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

@@ -34,9 +34,6 @@ gboolean meta_get_replace_current_wm (void); /* Actually defined in util
void meta_set_wm_name (const char *wm_name);
void meta_set_gnome_wm_keybindings (const char *wm_keybindings);
void meta_restart (const char *message);
gboolean meta_is_restart (void);
/**
* MetaExitCode:
* @META_EXIT_SUCCESS: Success

View File

@@ -25,7 +25,6 @@
#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>
@@ -171,11 +170,6 @@ 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
@@ -300,10 +294,10 @@ struct _MetaPluginVersion
#define META_PLUGIN_DECLARE(ObjectName, object_name) \
G_MODULE_EXPORT MetaPluginVersion meta_plugin_version = \
{ \
META_MAJOR_VERSION, \
META_MINOR_VERSION, \
META_MICRO_VERSION, \
META_PLUGIN_API_VERSION \
MUTTER_MAJOR_VERSION, \
MUTTER_MINOR_VERSION, \
MUTTER_MICRO_VERSION, \
MUTTER_PLUGIN_API_VERSION \
}; \
\
static GType g_define_type_id = 0; \

View File

@@ -1,28 +0,0 @@
/* -*- 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_buffer_rect (const MetaWindow *window, MetaRectangle *rect);
void meta_window_get_input_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;
@@ -256,7 +256,6 @@ gboolean meta_window_is_always_on_all_workspaces (MetaWindow *window);
gboolean meta_window_is_above (MetaWindow *window);
gboolean meta_window_allows_move (MetaWindow *window);
gboolean meta_window_allows_resize (MetaWindow *window);
gboolean meta_window_is_client_decorated (MetaWindow *window);
gboolean meta_window_titlebar_is_onscreen (MetaWindow *window);
void meta_window_shove_titlebar_onscreen (MetaWindow *window);

View File

@@ -224,6 +224,8 @@ 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);
}
@@ -1136,64 +1138,6 @@ meta_frame_right_click_event(MetaUIFrame *frame,
return meta_frame_titlebar_event (frame, event, action);
}
static gboolean
meta_frames_try_grab_op (MetaFrames *frames,
MetaUIFrame *frame,
MetaGrabOp op,
gdouble grab_x,
gdouble grab_y,
guint32 time)
{
Display *display;
gboolean ret;
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
ret = meta_core_begin_grab_op (display,
frame->xwindow,
op,
FALSE,
TRUE,
frame->grab_button,
0,
time,
grab_x, grab_y);
if (!ret)
{
frames->current_grab_op = op;
frames->grab_frame = frame;
frames->grab_x = grab_x;
frames->grab_y = grab_y;
}
return ret;
}
static gboolean
meta_frames_retry_grab_op (MetaFrames *frames,
guint time)
{
Display *display;
MetaGrabOp op;
if (frames->current_grab_op == META_GRAB_OP_NONE)
return TRUE;
op = frames->current_grab_op;
frames->current_grab_op = META_GRAB_OP_NONE;
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
return meta_core_begin_grab_op (display,
frames->grab_frame->xwindow,
op,
FALSE,
TRUE,
frames->grab_frame->grab_button,
0,
time,
frames->grab_x,
frames->grab_y);
}
static gboolean
meta_frames_button_press_event (GtkWidget *widget,
GdkEventButton *event)
@@ -1248,8 +1192,6 @@ meta_frames_button_press_event (GtkWidget *widget,
if (meta_core_get_grab_op (display) != META_GRAB_OP_NONE)
return FALSE; /* already up to something */
frame->grab_button = event->button;
if (event->button == 1 &&
(control == META_FRAME_CONTROL_MAXIMIZE ||
control == META_FRAME_CONTROL_UNMAXIMIZE ||
@@ -1276,36 +1218,30 @@ meta_frames_button_press_event (GtkWidget *widget,
{
MetaFrameGeometry fgeom;
GdkRectangle *rect;
MetaRectangle root_rect;
MetaWindowMenuType menu;
int win_x, win_y;
int dx, dy;
meta_frames_calc_geometry (frames, frame, &fgeom);
rect = control_rect (control, &fgeom);
/* convert to root coords */
win_x = event->x_root - event->x;
win_y = event->y_root - event->y;
/* get delta to convert to root coords */
dx = event->x_root - event->x;
dy = event->y_root - event->y;
root_rect.x = win_x + rect->x;
root_rect.y = win_y + rect->y;
root_rect.width = rect->width;
root_rect.height = rect->height;
/* Align to the right end of the menu rectangle if RTL */
if (meta_ui_get_direction() == META_UI_DIRECTION_RTL)
dx += rect->width;
menu = control == META_FRAME_CONTROL_MENU ? META_WINDOW_MENU_WM
: META_WINDOW_MENU_APP;
/* 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);
meta_core_show_window_menu (display,
frame->xwindow,
menu,
rect->x + dx,
rect->y + rect->height + dy,
event->time);
}
}
else if (event->button == 1 &&
@@ -1353,9 +1289,16 @@ meta_frames_button_press_event (GtkWidget *widget,
break;
}
meta_frames_try_grab_op (frames, frame, op,
event->x_root, event->y_root,
event->time);
meta_core_begin_grab_op (display,
frame->xwindow,
op,
TRUE,
TRUE,
event->button,
0,
event->time,
event->x_root,
event->y_root);
}
else if (control == META_FRAME_CONTROL_TITLE &&
event->button == 1)
@@ -1368,10 +1311,16 @@ meta_frames_button_press_event (GtkWidget *widget,
if (flags & META_FRAME_ALLOWS_MOVE)
{
meta_frames_try_grab_op (frames, frame,
meta_core_begin_grab_op (display,
frame->xwindow,
META_GRAB_OP_MOVING,
event->x_root, event->y_root,
event->time);
TRUE,
TRUE,
event->button,
0,
event->time,
event->x_root,
event->y_root);
}
}
else if (event->button == 2)
@@ -1396,7 +1345,6 @@ meta_frames_button_release_event (GtkWidget *widget,
frames = META_FRAMES (widget);
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
frames->current_grab_op = META_GRAB_OP_NONE;
frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window));
if (frame == NULL)
@@ -1558,8 +1506,7 @@ meta_frames_update_prelit_control (MetaFrames *frames,
break;
}
if (control == frame->prelit_control &&
frame->button_state == META_BUTTON_STATE_PRELIGHT)
if (control == frame->prelit_control)
return;
/* Save the old control so we can unprelight it */
@@ -1579,6 +1526,7 @@ meta_frames_motion_notify_event (GtkWidget *widget,
MetaUIFrame *frame;
MetaFrames *frames;
MetaFrameControl control;
int x, y;
frames = META_FRAMES (widget);
frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window));
@@ -1587,7 +1535,9 @@ meta_frames_motion_notify_event (GtkWidget *widget,
frames->last_motion_frame = frame;
control = get_control (frames, frame, event->x, event->y);
gdk_window_get_device_position (frame->window, event->device,
&x, &y, NULL);
control = get_control (frames, frame, x, y);
if (frame->button_state == META_BUTTON_STATE_PRESSED)
{
@@ -1605,10 +1555,6 @@ meta_frames_motion_notify_event (GtkWidget *widget,
meta_frames_update_prelit_control (frames, frame, control);
}
if ((event->state & GDK_BUTTON1_MASK) &&
frames->current_grab_op != META_GRAB_OP_NONE)
meta_frames_retry_grab_op (frames, event->time);
return TRUE;
}
@@ -1629,8 +1575,31 @@ meta_frames_destroy_event (GtkWidget *widget,
}
static cairo_region_t *
get_visible_frame_border_region (MetaUIFrame *frame)
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)
{
MetaRectangle frame_rect;
cairo_rectangle_int_t area;
@@ -1668,7 +1637,9 @@ get_visible_frame_border_region (MetaUIFrame *frame)
/* Visible frame border */
cairo_region_subtract_rectangle (frame_border, &area);
return frame_border;
cairo_region_intersect (region, frame_border);
cairo_region_destroy (frame_border);
}
#define TAU (2*M_PI)
@@ -1767,42 +1738,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);
frame = find_frame_to_draw (frames, cr);
g_assert (cairo_surface_get_type (target) == CAIRO_SURFACE_TYPE_XLIB);
frame = meta_frames_lookup_window (frames, cairo_xlib_surface_get_drawable (target));
if (frame == NULL)
return FALSE;
region = get_visible_frame_border_region (frame);
region = cairo_region_create_rectangle (&clip);
clip_region_to_visible_frame_border (region, frame);
if (cairo_region_is_empty (region))
goto out;
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;
@@ -1961,8 +1932,6 @@ 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);
@@ -1975,8 +1944,6 @@ meta_frames_leave_notify_event (GtkWidget *widget,
{
MetaUIFrame *frame;
MetaFrames *frames;
Display *display;
MetaGrabOp grab_op;
frames = META_FRAMES (widget);
@@ -1984,18 +1951,6 @@ 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,7 +80,6 @@ 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;
@@ -100,12 +99,6 @@ struct _MetaFrames
GtkStyleContext *normal_style;
GHashTable *style_variants;
MetaGrabOp current_grab_op;
MetaUIFrame *grab_frame;
guint grab_button;
gdouble grab_x;
gdouble grab_y;
Window grab_xwindow;
};

View File

@@ -65,7 +65,7 @@ free_buffer (guchar *pixels, gpointer data)
}
static GdkPixbuf*
blank_pixbuf (int width, int height)
blank_pixbuf (int width, int height, gboolean no_padding)
{
guchar *buf;
int rowstride;
@@ -73,15 +73,18 @@ blank_pixbuf (int width, int height)
g_return_val_if_fail (width > 0, NULL);
g_return_val_if_fail (height > 0, NULL);
/* Always align rows to 32-bit boundaries */
rowstride = 4 * ((4 * width + 4) / 4);
if (no_padding)
rowstride = width * 3;
else
/* Always align rows to 32-bit boundaries */
rowstride = 4 * ((3 * width + 3) / 4);
buf = g_try_malloc (height * rowstride);
if (!buf)
return NULL;
return gdk_pixbuf_new_from_data (buf, GDK_COLORSPACE_RGB,
TRUE, 8,
FALSE, 8,
width, height, rowstride,
free_buffer, NULL);
}
@@ -193,14 +196,14 @@ meta_gradient_create_interwoven (int width,
{
int i, j, k, l, ll;
long r1, g1, b1, a1, dr1, dg1, db1, da1;
long r2, g2, b2, a2, dr2, dg2, db2, da2;
long r1, g1, b1, dr1, dg1, db1;
long r2, g2, b2, dr2, dg2, db2;
GdkPixbuf *pixbuf;
unsigned char *ptr;
unsigned char *pixels;
int rowstride;
pixbuf = blank_pixbuf (width, height);
pixbuf = blank_pixbuf (width, height, FALSE);
if (pixbuf == NULL)
return NULL;
@@ -210,22 +213,18 @@ meta_gradient_create_interwoven (int width,
r1 = (long)(colors1[0].red*0xffffff);
g1 = (long)(colors1[0].green*0xffffff);
b1 = (long)(colors1[0].blue*0xffffff);
a1 = (long)(colors1[0].alpha*0xffffff);
r2 = (long)(colors2[0].red*0xffffff);
g2 = (long)(colors2[0].green*0xffffff);
b2 = (long)(colors2[0].blue*0xffffff);
a2 = (long)(colors2[0].alpha*0xffffff);
dr1 = ((colors1[1].red-colors1[0].red)*0xffffff)/(int)height;
dg1 = ((colors1[1].green-colors1[0].green)*0xffffff)/(int)height;
db1 = ((colors1[1].blue-colors1[0].blue)*0xffffff)/(int)height;
da1 = ((colors1[1].alpha-colors1[0].alpha)*0xffffff)/(int)height;
dr2 = ((colors2[1].red-colors2[0].red)*0xffffff)/(int)height;
dg2 = ((colors2[1].green-colors2[0].green)*0xffffff)/(int)height;
db2 = ((colors2[1].blue-colors2[0].blue)*0xffffff)/(int)height;
da2 = ((colors2[1].alpha-colors2[0].alpha)*0xffffff)/(int)height;
for (i=0,k=0,l=0,ll=thickness1; i<height; i++)
{
@@ -236,19 +235,17 @@ meta_gradient_create_interwoven (int width,
ptr[0] = (unsigned char) (r1>>16);
ptr[1] = (unsigned char) (g1>>16);
ptr[2] = (unsigned char) (b1>>16);
ptr[3] = (unsigned char) (a1>>16);
}
else
{
ptr[0] = (unsigned char) (r2>>16);
ptr[1] = (unsigned char) (g2>>16);
ptr[2] = (unsigned char) (b2>>16);
ptr[3] = (unsigned char) (a2>>16);
}
for (j=1; j <= width/2; j *= 2)
memcpy (&(ptr[j*4]), ptr, j*4);
memcpy (&(ptr[j*4]), ptr, (width - j)*4);
memcpy (&(ptr[j*3]), ptr, j*3);
memcpy (&(ptr[j*3]), ptr, (width - j)*3);
if (++l == ll)
{
@@ -267,12 +264,10 @@ meta_gradient_create_interwoven (int width,
r1+=dr1;
g1+=dg1;
b1+=db1;
a1+=da1;
r2+=dr2;
g2+=dg2;
b2+=db2;
a2+=da2;
}
return pixbuf;
@@ -297,15 +292,15 @@ meta_gradient_create_horizontal (int width, int height,
const GdkRGBA *to)
{
int i;
long r, g, b, a, dr, dg, db, da;
long r, g, b, dr, dg, db;
GdkPixbuf *pixbuf;
unsigned char *ptr;
unsigned char *pixels;
int r0, g0, b0, a0;
int rf, gf, bf, af;
int r0, g0, b0;
int rf, gf, bf;
int rowstride;
pixbuf = blank_pixbuf (width, height);
pixbuf = blank_pixbuf (width, height, FALSE);
if (pixbuf == NULL)
return NULL;
@@ -316,32 +311,26 @@ meta_gradient_create_horizontal (int width, int height,
r0 = (guchar) (from->red * 0xff);
g0 = (guchar) (from->green * 0xff);
b0 = (guchar) (from->blue * 0xff);
a0 = (guchar) (from->alpha * 0xff);
rf = (guchar) (to->red * 0xff);
gf = (guchar) (to->green * 0xff);
bf = (guchar) (to->blue * 0xff);
af = (guchar) (to->alpha * 0xff);
r = r0 << 16;
g = g0 << 16;
b = b0 << 16;
a = a0 << 16;
dr = ((rf-r0)<<16)/(int)width;
dg = ((gf-g0)<<16)/(int)width;
db = ((bf-b0)<<16)/(int)width;
da = ((af-a0)<<16)/(int)width;
/* render the first line */
for (i=0; i<width; i++)
{
*(ptr++) = (unsigned char)(r>>16);
*(ptr++) = (unsigned char)(g>>16);
*(ptr++) = (unsigned char)(b>>16);
*(ptr++) = (unsigned char)(a>>16);
r += dr;
g += dg;
b += db;
a += da;
}
/* copy the first line to the other lines */
@@ -371,15 +360,15 @@ meta_gradient_create_vertical (int width, int height,
const GdkRGBA *to)
{
int i, j;
long r, g, b, a, dr, dg, db, da;
long r, g, b, dr, dg, db;
GdkPixbuf *pixbuf;
unsigned char *ptr;
int r0, g0, b0, a0;
int rf, gf, bf, af;
int r0, g0, b0;
int rf, gf, bf;
int rowstride;
unsigned char *pixels;
pixbuf = blank_pixbuf (width, height);
pixbuf = blank_pixbuf (width, height, FALSE);
if (pixbuf == NULL)
return NULL;
@@ -389,21 +378,17 @@ meta_gradient_create_vertical (int width, int height,
r0 = (guchar) (from->red * 0xff);
g0 = (guchar) (from->green * 0xff);
b0 = (guchar) (from->blue * 0xff);
a0 = (guchar) (from->alpha * 0xff);
rf = (guchar) (to->red * 0xff);
gf = (guchar) (to->green * 0xff);
bf = (guchar) (to->blue * 0xff);
af = (guchar) (to->alpha * 0xff);
r = r0<<16;
g = g0<<16;
b = b0<<16;
a = a0<<16;
dr = ((rf-r0)<<16)/(int)height;
dg = ((gf-g0)<<16)/(int)height;
db = ((bf-b0)<<16)/(int)height;
da = ((af-a0)<<16)/(int)height;
for (i=0; i<height; i++)
{
@@ -412,16 +397,14 @@ meta_gradient_create_vertical (int width, int height,
ptr[0] = (unsigned char)(r>>16);
ptr[1] = (unsigned char)(g>>16);
ptr[2] = (unsigned char)(b>>16);
ptr[3] = (unsigned char)(a>>16);
for (j=1; j <= width/2; j *= 2)
memcpy (&(ptr[j*4]), ptr, j*4);
memcpy (&(ptr[j*4]), ptr, (width - j)*4);
memcpy (&(ptr[j*3]), ptr, j*3);
memcpy (&(ptr[j*3]), ptr, (width - j)*3);
r+=dr;
g+=dg;
b+=db;
a+=da;
}
return pixbuf;
}
@@ -459,7 +442,7 @@ meta_gradient_create_diagonal (int width, int height,
else if (height == 1)
return meta_gradient_create_horizontal (width, height, from, to);
pixbuf = blank_pixbuf (width, height);
pixbuf = blank_pixbuf (width, height, FALSE);
if (pixbuf == NULL)
return NULL;
@@ -476,12 +459,12 @@ meta_gradient_create_diagonal (int width, int height,
ptr = gdk_pixbuf_get_pixels (tmp);
a = ((float)(width - 1))/((float)(height - 1));
width = width * 4;
width = width * 3;
/* copy the first line to the other lines with corresponding offset */
for (j=0, offset=0.0; j<rowstride*height; j += rowstride)
{
memcpy (&(pixels[j]), &ptr[4*(int)offset], width);
memcpy (&(pixels[j]), &ptr[3*(int)offset], width);
offset += a;
}
@@ -496,7 +479,7 @@ meta_gradient_create_multi_horizontal (int width, int height,
int count)
{
int i, j, k;
long r, g, b, a, dr, dg, db, da;
long r, g, b, dr, dg, db;
GdkPixbuf *pixbuf;
unsigned char *ptr;
unsigned char *pixels;
@@ -505,7 +488,7 @@ meta_gradient_create_multi_horizontal (int width, int height,
g_return_val_if_fail (count > 2, NULL);
pixbuf = blank_pixbuf (width, height);
pixbuf = blank_pixbuf (width, height, FALSE);
if (pixbuf == NULL)
return NULL;
@@ -526,7 +509,6 @@ meta_gradient_create_multi_horizontal (int width, int height,
r = (long)(colors[0].red * 0xffffff);
g = (long)(colors[0].green * 0xffffff);
b = (long)(colors[0].blue * 0xffffff);
a = (long)(colors[0].alpha * 0xffffff);
/* render the first line */
for (i=1; i<count; i++)
@@ -534,30 +516,25 @@ meta_gradient_create_multi_horizontal (int width, int height,
dr = (int)((colors[i].red - colors[i-1].red) *0xffffff)/(int)width2;
dg = (int)((colors[i].green - colors[i-1].green)*0xffffff)/(int)width2;
db = (int)((colors[i].blue - colors[i-1].blue) *0xffffff)/(int)width2;
da = (int)((colors[i].alpha - colors[i-1].alpha) *0xffffff)/(int)width2;
for (j=0; j<width2; j++)
{
*ptr++ = (unsigned char)(r>>16);
*ptr++ = (unsigned char)(g>>16);
*ptr++ = (unsigned char)(b>>16);
*ptr++ = (unsigned char)(a>>16);
r += dr;
g += dg;
b += db;
a += da;
k++;
}
r = (long)(colors[i].red * 0xffffff);
g = (long)(colors[i].green * 0xffffff);
b = (long)(colors[i].blue * 0xffffff);
a = (long)(colors[i].alpha * 0xffffff);
}
for (j=k; j<width; j++)
{
*ptr++ = (unsigned char)(r>>16);
*ptr++ = (unsigned char)(g>>16);
*ptr++ = (unsigned char)(b>>16);
*ptr++ = (unsigned char)(a>>16);
}
/* copy the first line to the other lines */
@@ -574,7 +551,7 @@ meta_gradient_create_multi_vertical (int width, int height,
int count)
{
int i, j, k;
long r, g, b, a, dr, dg, db, da;
long r, g, b, dr, dg, db;
GdkPixbuf *pixbuf;
unsigned char *ptr, *tmp, *pixels;
int height2;
@@ -583,7 +560,7 @@ meta_gradient_create_multi_vertical (int width, int height,
g_return_val_if_fail (count > 2, NULL);
pixbuf = blank_pixbuf (width, height);
pixbuf = blank_pixbuf (width, height, FALSE);
if (pixbuf == NULL)
return NULL;
@@ -604,38 +581,33 @@ meta_gradient_create_multi_vertical (int width, int height,
r = (long)(colors[0].red * 0xffffff);
g = (long)(colors[0].green * 0xffffff);
b = (long)(colors[0].blue * 0xffffff);
a = (long)(colors[0].alpha * 0xffffff);
for (i=1; i<count; i++)
{
dr = (int)((colors[i].red - colors[i-1].red) *0xffffff)/(int)height2;
dg = (int)((colors[i].green - colors[i-1].green)*0xffffff)/(int)height2;
db = (int)((colors[i].blue - colors[i-1].blue) *0xffffff)/(int)height2;
da = (int)((colors[i].alpha - colors[i-1].alpha) *0xffffff)/(int)height2;
for (j=0; j<height2; j++)
{
ptr[0] = (unsigned char)(r>>16);
ptr[1] = (unsigned char)(g>>16);
ptr[2] = (unsigned char)(b>>16);
ptr[3] = (unsigned char)(a>>16);
for (x=1; x <= width/2; x *= 2)
memcpy (&(ptr[x*4]), ptr, x*4);
memcpy (&(ptr[x*4]), ptr, (width - x)*4);
memcpy (&(ptr[x*3]), ptr, x*3);
memcpy (&(ptr[x*3]), ptr, (width - x)*3);
ptr += rowstride;
r += dr;
g += dg;
b += db;
a += da;
k++;
}
r = (long)(colors[i].red * 0xffffff);
g = (long)(colors[i].green * 0xffffff);
b = (long)(colors[i].blue * 0xffffff);
a = (long)(colors[i].alpha * 0xffffff);
}
if (k<height)
@@ -645,11 +617,10 @@ meta_gradient_create_multi_vertical (int width, int height,
ptr[0] = (unsigned char) (r>>16);
ptr[1] = (unsigned char) (g>>16);
ptr[2] = (unsigned char) (b>>16);
ptr[3] = (unsigned char) (a>>16);
for (x=1; x <= width/2; x *= 2)
memcpy (&(ptr[x*4]), ptr, x*4);
memcpy (&(ptr[x*4]), ptr, (width - x)*4);
memcpy (&(ptr[x*3]), ptr, x*3);
memcpy (&(ptr[x*3]), ptr, (width - x)*3);
ptr += rowstride;

View File

@@ -29,8 +29,6 @@
#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,6 +56,8 @@
((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)
@@ -92,8 +94,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;
@@ -163,7 +165,6 @@ color_composite (const GdkRGBA *bg,
color->red = color->red + (fg->red - color->red) * alpha;
color->green = color->green + (fg->green - color->green) * alpha;
color->blue = color->blue + (fg->blue - color->blue) * alpha;
color->alpha = color->alpha + (fg->alpha - color->alpha) * alpha;
}
/**
@@ -794,19 +795,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))
@@ -925,11 +926,12 @@ 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])
@@ -1190,8 +1192,10 @@ meta_color_spec_new_from_string (const char *str,
MetaColorSpec *spec;
spec = NULL;
if (strncmp (str, "gtk:custom", 10) == 0)
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')
{
const char *color_name_start, *fallback_str_start, *end;
char *color_name;
@@ -1266,7 +1270,7 @@ meta_color_spec_new_from_string (const char *str,
spec->data.gtkcustom.color_name = color_name;
spec->data.gtkcustom.fallback = fallback;
}
else if (strncmp (str, "gtk:", 4) == 0)
else if (str[0] == 'g' && str[1] == 't' && str[2] == 'k' && str[3] == ':')
{
/* GTK color */
const char *bracket;
@@ -1333,7 +1337,8 @@ 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 (strncmp (str, "blend/", 6) == 0)
else if (str[0] == 'b' && str[1] == 'l' && str[2] == 'e' && str[3] == 'n' &&
str[4] == 'd' && str[5] == '/')
{
/* blend */
char **split;
@@ -1401,7 +1406,8 @@ meta_color_spec_new_from_string (const char *str,
spec->data.blend.background = bg;
spec->data.blend.foreground = fg;
}
else if (strncmp (str, "shade/", 6) == 0)
else if (str[0] == 's' && str[1] == 'h' && str[2] == 'a' && str[3] == 'd' &&
str[4] == 'e' && str[5] == '/')
{
/* shade */
char **split;
@@ -1698,12 +1704,20 @@ op_from_string (const char *p,
return POS_OP_MOD;
case '`':
if (strncmp (p, "`max`", 5) == 0)
if (p[0] == '`' &&
p[1] == 'm' &&
p[2] == 'a' &&
p[3] == 'x' &&
p[4] == '`')
{
*len = 5;
return POS_OP_MAX;
}
else if (strncmp (p, "`min`", 5) == 0)
else if (p[0] == '`' &&
p[1] == 'm' &&
p[2] == 'i' &&
p[3] == 'n' &&
p[4] == '`')
{
*len = 5;
return POS_OP_MIN;
@@ -3053,7 +3067,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));
@@ -3404,6 +3418,32 @@ 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;
@@ -3462,11 +3502,12 @@ 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);
@@ -3494,18 +3535,24 @@ 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) &&
@@ -3523,15 +3570,12 @@ 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;
}
@@ -4002,7 +4046,8 @@ 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;
@@ -4039,7 +4084,8 @@ 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;
}
@@ -4139,6 +4185,18 @@ meta_draw_op_list_draw_with_style (const MetaDrawOpList *op_list,
fill_env (&env, info, rect);
/* FIXME this can be optimized, potentially a lot, by
* compressing multiple ops when possible. For example,
* anything convertible to a pixbuf can be composited
* client-side, and putting a color tint over a pixbuf
* can be done without creating the solid-color pixbuf.
*
* To implement this my plan is to have the idea of a
* compiled draw op (with the string expressions already
* evaluated), we make an array of those, and then fold
* adjacent items when possible.
*/
cairo_save (cr);
for (i = 0; i < op_list->n_ops; i++)
@@ -6343,7 +6401,6 @@ gtk_style_shade (GdkRGBA *a,
b->red = red;
b->green = green;
b->blue = blue;
b->alpha = a->alpha;
}
/**
@@ -6512,6 +6569,216 @@ 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

@@ -83,31 +83,6 @@ is_input_event (XEvent *event)
event->xcookie.extension == display->xinput_opcode);
}
static gboolean
is_interesting_input_event (XEvent *event)
{
XIEvent *input_event;
if (!is_input_event (event))
return FALSE;
input_event = (XIEvent *) event->xcookie.data;
switch (input_event->evtype)
{
case XI_ButtonPress:
case XI_ButtonRelease:
case XI_Motion:
case XI_Enter:
case XI_Leave:
case XI_TouchBegin:
case XI_TouchUpdate:
case XI_TouchEnd:
return TRUE;
default:
return FALSE;
}
}
/* We do some of our event handling in frames.c, which expects
* GDK events delivered by GTK+. However, since the transition to
* client side windows, we can't let GDK see button events, since the
@@ -123,7 +98,7 @@ is_interesting_input_event (XEvent *event)
* use more fields, more fields need to be filled out below.
*/
static void
static gboolean
maybe_redirect_mouse_event (XEvent *xevent)
{
GdkDisplay *gdisplay;
@@ -137,10 +112,14 @@ maybe_redirect_mouse_event (XEvent *xevent)
XIDeviceEvent *xev_d = NULL;
XIEnterEvent *xev_e = NULL;
if (!is_input_event (xevent))
return FALSE;
xev = (XIEvent *) xevent->xcookie.data;
switch (xev->evtype)
{
case XI_TouchBegin:
case XI_ButtonPress:
case XI_ButtonRelease:
case XI_Motion:
@@ -153,27 +132,34 @@ maybe_redirect_mouse_event (XEvent *xevent)
window = xev_e->event;
break;
default:
/* Not interested in this event. */
return;
return FALSE;
}
gdisplay = gdk_x11_lookup_xdisplay (xev->display);
ui = g_object_get_data (G_OBJECT (gdisplay), "meta-ui");
if (!ui)
return;
return FALSE;
gdk_window = gdk_x11_window_lookup_for_display (gdisplay, window);
if (gdk_window == NULL)
return;
return FALSE;
gmanager = gdk_display_get_device_manager (gdisplay);
gdevice = gdk_x11_device_manager_lookup (gmanager, META_VIRTUAL_CORE_POINTER_ID);
/* If GDK already thinks it has a grab, we better let it see events; this
* is the menu-navigation case and events need to get sent to the appropriate
* (client-side) subwindow for individual menu items.
*/
if (gdk_display_device_is_grabbed (gdisplay, gdevice))
return FALSE;
switch (xev->evtype)
{
case XI_TouchBegin:
case XI_ButtonPress:
case XI_ButtonRelease:
if (xev_d->evtype == XI_ButtonPress)
if (xev_d->evtype == XI_ButtonPress || xev_d->evtype == XI_TouchBegin)
{
GtkSettings *settings = gtk_settings_get_default ();
int double_click_time;
@@ -185,7 +171,10 @@ maybe_redirect_mouse_event (XEvent *xevent)
"gtk-double-click-distance", &double_click_distance,
NULL);
button = xev_d->detail;
if (xev->evtype == XI_TouchBegin)
button = 1;
else
button = xev_d->detail;
if (button == ui->button_click_number &&
xev_d->event == ui->button_click_window &&
@@ -221,24 +210,17 @@ maybe_redirect_mouse_event (XEvent *xevent)
gevent->button.y = xev_d->event_y;
gevent->button.x_root = xev_d->root_x;
gevent->button.y_root = xev_d->root_y;
break;
case XI_Motion:
gevent = gdk_event_new (GDK_MOTION_NOTIFY);
gevent->motion.type = GDK_MOTION_NOTIFY;
gevent->motion.window = g_object_ref (gdk_window);
gevent->motion.time = xev_d->time;
gevent->motion.x = xev_d->event_x;
gevent->motion.y = xev_d->event_y;
gevent->motion.x_root = xev_d->root_x;
gevent->motion.y_root = xev_d->root_y;
if (XIMaskIsSet (xev_d->buttons.mask, 1))
gevent->motion.state |= GDK_BUTTON1_MASK;
break;
case XI_Enter:
case XI_Leave:
gevent = gdk_event_new (xev_e->evtype == XI_Enter ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY);
gevent->crossing.window = g_object_ref (gdk_window);
gevent->crossing.time = xev_e->time;
gevent->crossing.x = xev_e->event_x;
gevent->crossing.y = xev_e->event_y;
break;
@@ -251,6 +233,8 @@ maybe_redirect_mouse_event (XEvent *xevent)
gdk_event_set_device (gevent, gdevice);
gtk_main_do_event (gevent);
gdk_event_free (gevent);
return TRUE;
}
static GdkFilterReturn
@@ -258,11 +242,8 @@ ui_filter_func (GdkXEvent *xevent,
GdkEvent *event,
gpointer data)
{
if (is_interesting_input_event (xevent))
{
maybe_redirect_mouse_event (xevent);
return GDK_FILTER_REMOVE;
}
if (maybe_redirect_mouse_event (xevent))
return GDK_FILTER_REMOVE;
else
return GDK_FILTER_CONTINUE;
}
@@ -555,6 +536,76 @@ meta_gdk_pixbuf_get_from_pixmap (Pixmap xpixmap,
return retval;
}
GdkPixbuf*
meta_ui_get_default_window_icon (MetaUI *ui)
{
static GdkPixbuf *default_icon = NULL;
if (default_icon == NULL)
{
GtkIconTheme *theme;
gboolean icon_exists;
theme = gtk_icon_theme_get_default ();
icon_exists = gtk_icon_theme_has_icon (theme, META_DEFAULT_ICON_NAME);
if (icon_exists)
default_icon = gtk_icon_theme_load_icon (theme,
META_DEFAULT_ICON_NAME,
META_ICON_WIDTH,
0,
NULL);
else
default_icon = gtk_icon_theme_load_icon (theme,
"image-missing",
META_ICON_WIDTH,
0,
NULL);
g_assert (default_icon);
}
g_object_ref (G_OBJECT (default_icon));
return default_icon;
}
GdkPixbuf*
meta_ui_get_default_mini_icon (MetaUI *ui)
{
static GdkPixbuf *default_icon = NULL;
if (default_icon == NULL)
{
GtkIconTheme *theme;
gboolean icon_exists;
theme = gtk_icon_theme_get_default ();
icon_exists = gtk_icon_theme_has_icon (theme, META_DEFAULT_ICON_NAME);
if (icon_exists)
default_icon = gtk_icon_theme_load_icon (theme,
META_DEFAULT_ICON_NAME,
META_MINI_ICON_WIDTH,
0,
NULL);
else
default_icon = gtk_icon_theme_load_icon (theme,
"image-missing",
META_MINI_ICON_WIDTH,
0,
NULL);
g_assert (default_icon);
}
g_object_ref (G_OBJECT (default_icon));
return default_icon;
}
gboolean
meta_ui_window_should_not_cause_focus (Display *xdisplay,
Window xwindow)

View File

@@ -121,6 +121,9 @@ GdkPixbuf* meta_gdk_pixbuf_get_from_pixmap (Pixmap xpixmap,
int width,
int height);
GdkPixbuf* meta_ui_get_default_window_icon (MetaUI *ui);
GdkPixbuf* meta_ui_get_default_mini_icon (MetaUI *ui);
gboolean meta_ui_window_should_not_cause_focus (Display *xdisplay,
Window xwindow);

View File

@@ -35,25 +35,6 @@
#include "meta-wayland-pointer.h"
#include "meta-wayland-private.h"
typedef struct
{
struct wl_resource *resource;
MetaWaylandDataSource *source;
struct wl_listener source_destroy_listener;
} MetaWaylandDataOffer;
struct _MetaWaylandDataSource
{
struct wl_resource *resource;
struct wl_array mime_types;
};
static void
unbind_resource (struct wl_resource *resource)
{
wl_list_remove (wl_resource_get_link (resource));
}
static void
data_offer_accept (struct wl_client *client,
struct wl_resource *resource,
@@ -198,8 +179,7 @@ drag_grab_focus (MetaWaylandPointerGrab *grab,
{
MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab;
MetaWaylandSeat *seat = drag_grab->seat;
struct wl_client *client;
struct wl_resource *data_device_resource, *offer = NULL;
struct wl_resource *resource, *offer = NULL;
struct wl_display *display;
guint32 serial;
wl_fixed_t sx, sy;
@@ -222,28 +202,28 @@ drag_grab_focus (MetaWaylandPointerGrab *grab,
wl_resource_get_client (surface->resource) != drag_grab->drag_client)
return;
client = wl_resource_get_client (surface->resource);
data_device_resource = wl_resource_find_for_client (&seat->data_device.resource_list, client);
if (!data_device_resource)
resource =
wl_resource_find_for_client (&seat->data_device_resource_list,
wl_resource_get_client (surface->resource));
if (!resource)
return;
display = wl_client_get_display (client);
display = wl_client_get_display (wl_resource_get_client (resource));
serial = wl_display_next_serial (display);
if (drag_grab->drag_data_source)
offer = meta_wayland_data_source_send_offer (drag_grab->drag_data_source,
data_device_resource);
resource);
meta_wayland_pointer_get_relative_coordinates (grab->pointer, surface, &sx, &sy);
wl_data_device_send_enter (data_device_resource, serial, surface->resource,
wl_data_device_send_enter (resource, serial, surface->resource,
sx, sy, offer);
drag_grab->drag_focus = surface;
drag_grab->drag_focus_data_device = data_device_resource;
drag_grab->drag_focus_data_device = resource;
drag_grab->drag_focus_listener.notify = destroy_drag_focus;
wl_resource_add_destroy_listener (data_device_resource, &drag_grab->drag_focus_listener);
wl_resource_add_destroy_listener (resource, &drag_grab->drag_focus_listener);
}
static void
@@ -332,8 +312,7 @@ data_device_start_drag (struct wl_client *client,
struct wl_resource *origin_resource,
struct wl_resource *icon_resource, guint32 serial)
{
MetaWaylandDataDevice *data_device = wl_resource_get_user_data (resource);
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
MetaWaylandSeat *seat = wl_resource_get_user_data (resource);
MetaWaylandDragGrab *drag_grab;
if ((seat->pointer.button_count == 0 ||
@@ -378,67 +357,68 @@ data_device_start_drag (struct wl_client *client,
static void
destroy_selection_data_source (struct wl_listener *listener, void *data)
{
MetaWaylandDataDevice *data_device = wl_container_of (listener, data_device, selection_data_source_listener);
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
struct wl_resource *data_device_resource;
MetaWaylandSeat *seat =
wl_container_of (listener, seat, selection_data_source_listener);
struct wl_resource *data_device;
struct wl_client *focus_client = NULL;
data_device->selection_data_source = NULL;
seat->selection_data_source = NULL;
focus_client = meta_wayland_keyboard_get_focus_client (&seat->keyboard);
if (focus_client)
{
data_device_resource = wl_resource_find_for_client (&data_device->resource_list, focus_client);
if (data_device_resource)
wl_data_device_send_selection (data_device_resource, NULL);
data_device = wl_resource_find_for_client (&seat->data_device_resource_list, focus_client);
if (data_device)
wl_data_device_send_selection (data_device, NULL);
}
}
static void
meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
MetaWaylandDataSource *source,
guint32 serial)
meta_wayland_seat_set_selection (MetaWaylandSeat *seat,
MetaWaylandDataSource *source,
guint32 serial)
{
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
struct wl_resource *data_device_resource, *offer;
struct wl_resource *data_device, *offer;
struct wl_client *focus_client;
if (data_device->selection_data_source &&
data_device->selection_serial - serial < UINT32_MAX / 2)
if (seat->selection_data_source &&
seat->selection_serial - serial < UINT32_MAX / 2)
return;
if (data_device->selection_data_source)
if (seat->selection_data_source)
{
wl_data_source_send_cancelled (data_device->selection_data_source->resource);
wl_list_remove (&data_device->selection_data_source_listener.link);
data_device->selection_data_source = NULL;
wl_data_source_send_cancelled (seat->selection_data_source->resource);
wl_list_remove (&seat->selection_data_source_listener.link);
seat->selection_data_source = NULL;
}
data_device->selection_data_source = source;
data_device->selection_serial = serial;
seat->selection_data_source = source;
seat->selection_serial = serial;
focus_client = meta_wayland_keyboard_get_focus_client (&seat->keyboard);
if (focus_client)
{
data_device_resource = wl_resource_find_for_client (&data_device->resource_list, focus_client);
if (data_device_resource)
data_device = wl_resource_find_for_client (&seat->data_device_resource_list, focus_client);
if (data_device)
{
if (data_device->selection_data_source)
if (seat->selection_data_source)
{
offer = meta_wayland_data_source_send_offer (data_device->selection_data_source, data_device_resource);
wl_data_device_send_selection (data_device_resource, offer);
offer = meta_wayland_data_source_send_offer (seat->selection_data_source, data_device);
wl_data_device_send_selection (data_device, offer);
}
else
{
wl_data_device_send_selection (data_device_resource, NULL);
wl_data_device_send_selection (data_device, NULL);
}
}
}
if (source)
{
data_device->selection_data_source_listener.notify = destroy_selection_data_source;
wl_resource_add_destroy_listener (source->resource, &data_device->selection_data_source_listener);
seat->selection_data_source_listener.notify =
destroy_selection_data_source;
wl_resource_add_destroy_listener (source->resource,
&seat->selection_data_source_listener);
}
}
@@ -448,16 +428,13 @@ data_device_set_selection (struct wl_client *client,
struct wl_resource *source_resource,
guint32 serial)
{
MetaWaylandDataDevice *data_device = wl_resource_get_user_data (resource);
MetaWaylandDataSource *source;
if (!source_resource)
return;
source = wl_resource_get_user_data (source_resource);
/* FIXME: Store serial and check against incoming serial here. */
meta_wayland_data_device_set_selection (data_device, source, serial);
meta_wayland_seat_set_selection (wl_resource_get_user_data (resource),
wl_resource_get_user_data (source_resource),
serial);
}
static const struct wl_data_device_interface data_device_interface = {
@@ -493,18 +470,25 @@ create_data_source (struct wl_client *client,
wl_array_init (&source->mime_types);
}
static void
unbind_data_device (struct wl_resource *resource)
{
wl_list_remove (wl_resource_get_link (resource));
}
static void
get_data_device (struct wl_client *client,
struct wl_resource *manager_resource,
guint32 id, struct wl_resource *seat_resource)
{
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
struct wl_resource *cr;
struct wl_resource *resource;
cr = wl_resource_create (client, &wl_data_device_interface,
MIN (META_WL_DATA_DEVICE_VERSION, wl_resource_get_version (manager_resource)), id);
wl_resource_set_implementation (cr, &data_device_interface, &seat->data_device, unbind_resource);
wl_list_insert (&seat->data_device.resource_list, wl_resource_get_link (cr));
resource = wl_resource_create (client, &wl_data_device_interface,
MIN (META_WL_DATA_DEVICE_VERSION,
wl_resource_get_version (manager_resource)), id);
wl_resource_set_implementation (resource, &data_device_interface, seat, unbind_data_device);
wl_list_insert (&seat->data_device_resource_list, wl_resource_get_link (resource));
}
static const struct wl_data_device_manager_interface manager_interface = {
@@ -534,31 +518,24 @@ meta_wayland_data_device_manager_init (MetaWaylandCompositor *compositor)
}
void
meta_wayland_data_device_init (MetaWaylandDataDevice *data_device)
meta_wayland_data_device_set_keyboard_focus (MetaWaylandSeat *seat)
{
wl_list_init (&data_device->resource_list);
}
void
meta_wayland_data_device_set_keyboard_focus (MetaWaylandDataDevice *data_device)
{
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
struct wl_client *focus_client;
struct wl_resource *data_device_resource, *offer;
struct wl_resource *data_device, *offer;
MetaWaylandDataSource *source;
focus_client = meta_wayland_keyboard_get_focus_client (&seat->keyboard);
if (!focus_client)
return;
data_device_resource = wl_resource_find_for_client (&data_device->resource_list, focus_client);
if (!data_device_resource)
data_device = wl_resource_find_for_client (&seat->data_device_resource_list, focus_client);
if (!data_device)
return;
source = data_device->selection_data_source;
source = seat->selection_data_source;
if (source)
{
offer = meta_wayland_data_source_send_offer (source, data_device_resource);
wl_data_device_send_selection (data_device_resource, offer);
offer = meta_wayland_data_source_send_offer (source, data_device);
wl_data_device_send_selection (data_device, offer);
}
}

View File

@@ -25,20 +25,10 @@
#include <wayland-server.h>
#include "meta-wayland-types.h"
struct _MetaWaylandDataDevice
{
uint32_t selection_serial;
MetaWaylandDataSource *selection_data_source;
struct wl_listener selection_data_source_listener;
struct wl_list resource_list;
};
#include "meta-wayland-private.h"
void meta_wayland_data_device_manager_init (MetaWaylandCompositor *compositor);
void meta_wayland_data_device_init (MetaWaylandDataDevice *data_device);
void meta_wayland_data_device_set_keyboard_focus (MetaWaylandDataDevice *data_device);
void meta_wayland_data_device_set_keyboard_focus (MetaWaylandSeat *seat);
#endif /* META_WAYLAND_DATA_DEVICE_H */

View File

@@ -301,7 +301,6 @@ meta_wayland_xkb_info_destroy (MetaWaylandXkbInfo *xkb_info)
void
meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard)
{
meta_wayland_keyboard_set_focus (keyboard, NULL);
meta_wayland_xkb_info_destroy (&keyboard->xkb_info);
xkb_context_unref (keyboard->xkb_context);
@@ -550,7 +549,7 @@ meta_wayland_keyboard_create_new_resource (MetaWaylandKeyboard *keyboard,
cr = wl_resource_create (client, &wl_keyboard_interface,
MIN (META_WL_KEYBOARD_VERSION, wl_resource_get_version (seat_resource)), id);
wl_resource_set_implementation (cr, &keyboard_interface, keyboard, unbind_resource);
wl_resource_set_implementation (cr, NULL, keyboard, unbind_resource);
wl_list_insert (&keyboard->resource_list, wl_resource_get_link (cr));
wl_keyboard_send_keymap (cr,

View File

@@ -168,20 +168,12 @@ wayland_output_destroy_notify (gpointer data)
g_slice_free (MetaWaylandOutput, wayland_output);
}
static inline enum wl_output_transform
wl_output_transform_from_meta_monitor_transform (MetaMonitorTransform transform)
{
/* The enums are the same. */
return (enum wl_output_transform) transform;
}
static void
wayland_output_update_for_output (MetaWaylandOutput *wayland_output,
MetaOutput *output)
{
GList *iter;
guint mode_flags;
enum wl_output_transform wl_transform = wl_output_transform_from_meta_monitor_transform (output->crtc->transform);
g_assert (output->crtc->current_mode != NULL);
@@ -195,7 +187,7 @@ wayland_output_update_for_output (MetaWaylandOutput *wayland_output,
if (wayland_output->x != output->crtc->rect.x ||
wayland_output->y != output->crtc->rect.y ||
wayland_output->transform != wl_transform)
wayland_output->transform != output->crtc->transform)
{
wl_resource_post_event (resource,
WL_OUTPUT_GEOMETRY,
@@ -206,7 +198,7 @@ wayland_output_update_for_output (MetaWaylandOutput *wayland_output,
output->subpixel_order,
output->vendor,
output->product,
wl_transform);
output->crtc->transform);
}
wl_resource_post_event (resource,
@@ -222,7 +214,7 @@ wayland_output_update_for_output (MetaWaylandOutput *wayland_output,
wayland_output->output = output;
wayland_output->x = output->crtc->rect.x;
wayland_output->y = output->crtc->rect.y;
wayland_output->transform = wl_transform;
wayland_output->transform = output->crtc->transform;
}
static GHashTable *
@@ -244,15 +236,15 @@ meta_wayland_compositor_update_outputs (MetaWaylandCompositor *compositor,
/* wayland does not expose disabled outputs */
if (output->crtc == NULL)
{
g_hash_table_remove (compositor->outputs, GSIZE_TO_POINTER (output->winsys_id));
g_hash_table_remove (compositor->outputs, GSIZE_TO_POINTER (output->output_id));
continue;
}
wayland_output = g_hash_table_lookup (compositor->outputs, GSIZE_TO_POINTER (output->winsys_id));
wayland_output = g_hash_table_lookup (compositor->outputs, GSIZE_TO_POINTER (output->output_id));
if (wayland_output)
{
g_hash_table_steal (compositor->outputs, GSIZE_TO_POINTER (output->winsys_id));
g_hash_table_steal (compositor->outputs, GSIZE_TO_POINTER (output->output_id));
}
else
{
@@ -264,7 +256,7 @@ meta_wayland_compositor_update_outputs (MetaWaylandCompositor *compositor,
}
wayland_output_update_for_output (wayland_output, output);
g_hash_table_insert (new_table, GSIZE_TO_POINTER (output->winsys_id), wayland_output);
g_hash_table_insert (new_table, GSIZE_TO_POINTER (output->output_id), wayland_output);
}
g_hash_table_destroy (compositor->outputs);

View File

@@ -200,6 +200,8 @@ 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;
@@ -207,14 +209,11 @@ meta_wayland_pointer_init (MetaWaylandPointer *pointer,
manager = clutter_device_manager_get_default ();
pointer->device = clutter_device_manager_get_core_device (manager, CLUTTER_POINTER_DEVICE);
pointer->cursor_tracker = meta_cursor_tracker_get_for_screen (NULL);
}
void
meta_wayland_pointer_release (MetaWaylandPointer *pointer)
{
meta_wayland_pointer_set_focus (pointer, NULL);
set_cursor_surface (pointer, NULL);
}
@@ -816,7 +815,7 @@ meta_wayland_pointer_can_grab_surface (MetaWaylandPointer *pointer,
MetaWaylandSurface *surface,
uint32_t serial)
{
return (pointer->button_count > 0 &&
return (pointer->button_count == 0 &&
pointer->grab_serial == serial &&
pointer->focus_surface == surface);
}

View File

@@ -50,6 +50,10 @@ typedef struct
typedef struct
{
struct wl_list link;
/* Pointer back to the compositor */
MetaWaylandCompositor *compositor;
struct wl_resource *resource;
} MetaWaylandFrameCallback;
@@ -71,8 +75,10 @@ struct _MetaWaylandCompositor
{
struct wl_display *wayland_display;
char *display_name;
struct wl_event_loop *wayland_loop;
ClutterActor *stage;
GHashTable *outputs;
GSource *wayland_event_source;
struct wl_list frame_callbacks;
MetaXWaylandManager xwayland_manager;

View File

@@ -25,7 +25,6 @@
#include "meta-wayland-private.h"
#include "meta-wayland-versions.h"
#include "meta-wayland-data-device.h"
static void
unbind_resource (struct wl_resource *resource)
@@ -60,10 +59,7 @@ seat_get_touch (struct wl_client *client,
struct wl_resource *resource,
uint32_t id)
{
MetaWaylandSeat *seat = wl_resource_get_user_data (resource);
MetaWaylandTouch *touch = &seat->touch;
meta_wayland_touch_create_new_resource (touch, client, resource, id);
/* Touch not supported */
}
static const struct wl_seat_interface seat_interface = {
@@ -88,8 +84,7 @@ bind_seat (struct wl_client *client,
wl_seat_send_capabilities (resource,
WL_SEAT_CAPABILITY_POINTER |
WL_SEAT_CAPABILITY_KEYBOARD |
WL_SEAT_CAPABILITY_TOUCH);
WL_SEAT_CAPABILITY_KEYBOARD);
if (version >= WL_SEAT_NAME_SINCE_VERSION)
wl_seat_send_name (resource, "seat0");
@@ -100,12 +95,14 @@ meta_wayland_seat_new (struct wl_display *display)
{
MetaWaylandSeat *seat = g_new0 (MetaWaylandSeat, 1);
seat->selection_data_source = NULL;
wl_list_init (&seat->base_resource_list);
wl_list_init (&seat->data_device_resource_list);
meta_wayland_pointer_init (&seat->pointer, display);
meta_wayland_keyboard_init (&seat->keyboard, display);
meta_wayland_touch_init (&seat->touch, display);
meta_wayland_data_device_init (&seat->data_device);
seat->display = display;
wl_global_create (display, &wl_seat_interface, META_WL_SEAT_VERSION, seat, bind_seat);
@@ -123,7 +120,6 @@ 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);
}
@@ -146,12 +142,6 @@ 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;
}
@@ -173,10 +163,6 @@ 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;
@@ -191,14 +177,6 @@ meta_wayland_seat_repick (MetaWaylandSeat *seat)
meta_wayland_pointer_repick (&seat->pointer);
}
void
meta_wayland_seat_set_input_focus (MetaWaylandSeat *seat,
MetaWaylandSurface *surface)
{
meta_wayland_keyboard_set_focus (&seat->keyboard, surface);
meta_wayland_data_device_set_keyboard_focus (&seat->data_device);
}
void
meta_wayland_seat_update_cursor_surface (MetaWaylandSeat *seat)
{

View File

@@ -26,19 +26,35 @@
#include <clutter/clutter.h>
#include "meta-wayland-types.h"
#include "meta-wayland-pointer.h"
#include "meta-wayland-keyboard.h"
#include "meta-wayland-touch.h"
#include "meta-wayland-data-device.h"
#include "meta-wayland-pointer.h"
struct _MetaWaylandDataOffer
{
struct wl_resource *resource;
MetaWaylandDataSource *source;
struct wl_listener source_destroy_listener;
};
struct _MetaWaylandDataSource
{
struct wl_resource *resource;
struct wl_array mime_types;
};
struct _MetaWaylandSeat
{
struct wl_list base_resource_list;
uint32_t selection_serial;
MetaWaylandDataSource *selection_data_source;
struct wl_listener selection_data_source_listener;
struct wl_list data_device_resource_list;
MetaWaylandPointer pointer;
MetaWaylandKeyboard keyboard;
MetaWaylandTouch touch;
MetaWaylandDataDevice data_device;
struct wl_display *display;
};
void meta_wayland_seat_init (MetaWaylandCompositor *compositor);
@@ -51,9 +67,6 @@ void meta_wayland_seat_update (MetaWaylandSeat *seat,
gboolean meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
const ClutterEvent *event);
void meta_wayland_seat_set_input_focus (MetaWaylandSeat *seat,
MetaWaylandSurface *surface);
void meta_wayland_seat_repick (MetaWaylandSeat *seat);
void meta_wayland_seat_update_cursor_surface (MetaWaylandSeat *seat);

View File

@@ -163,88 +163,33 @@ cursor_surface_commit (MetaWaylandSurface *surface,
}
static void
calculate_surface_window_geometry (MetaWaylandSurface *surface,
MetaRectangle *total_geometry,
float parent_x,
float parent_y)
{
ClutterActor *surface_actor = CLUTTER_ACTOR (surface->surface_actor);
MetaRectangle geom;
float x, y;
GList *l;
/* Unmapped surfaces don't count. */
if (!CLUTTER_ACTOR_IS_VISIBLE (surface_actor))
return;
/* XXX: Is there a better way to do this using Clutter APIs? */
clutter_actor_get_position (surface_actor, &x, &y);
geom.x = parent_x + x;
geom.y = parent_x + y;
geom.width = cogl_texture_get_width (surface->buffer->texture);
geom.height = cogl_texture_get_height (surface->buffer->texture);
meta_rectangle_union (total_geometry, &geom, total_geometry);
for (l = surface->subsurfaces; l != NULL; l = l->next)
{
MetaWaylandSurface *subsurface = l->data;
calculate_surface_window_geometry (subsurface, total_geometry, x, y);
}
}
static void
toplevel_surface_commit (MetaWaylandSurface *surface,
toplevel_surface_commit (MetaWaylandSurface *surface,
MetaWaylandPendingState *pending)
{
MetaWindow *window = surface->window;
/* Sanity check. */
if (surface->buffer == NULL)
if (pending->newly_attached)
{
wl_resource_post_error (surface->resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"Cannot commit a NULL buffer to an xdg_surface");
return;
MetaWindow *window = surface->window;
MetaWaylandBuffer *buffer = pending->buffer;
meta_window_set_surface_mapped (window, buffer != NULL);
/* We resize X based surfaces according to X events */
if (buffer != NULL && window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
{
int new_width, new_height;
new_width = cogl_texture_get_width (buffer->texture);
new_height = cogl_texture_get_height (buffer->texture);
if (new_width != window->rect.width ||
new_height != window->rect.height ||
pending->dx != 0 ||
pending->dy != 0)
meta_window_wayland_move_resize (window, new_width, new_height, pending->dx, pending->dy);
}
}
/* We resize X based surfaces according to X events */
if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
{
MetaRectangle geom;
if (pending->has_new_geometry)
{
/* If we have new geometry, use it. */
geom = pending->new_geometry;
surface->has_set_geometry = TRUE;
}
else if (!surface->has_set_geometry)
{
/* If the surface has never set any geometry, calculate
* a default one unioning the surface and all subsurfaces together. */
calculate_surface_window_geometry (surface, &geom, 0, 0);
}
else
{
/* Otherwise, keep the geometry the same. */
/* XXX: We don't store the geometry in any consistent place
* right now, so we can't re-fetch it. We should change
* meta_window_wayland_move_resize. */
/* XXX: This is the common case. Recognize it to prevent
* a warning. */
if (pending->dx == 0 && pending->dy == 0)
return;
g_warning ("XXX: Attach-initiated move without a new geometry. This is unimplemented right now.");
return;
}
meta_window_wayland_move_resize (window, geom, pending->dx, pending->dy);
}
if (pending->frame_extents_changed)
meta_window_set_custom_frame_extents (surface->window, &pending->frame_extents);
}
static void
@@ -271,7 +216,7 @@ pending_state_init (MetaWaylandPendingState *state)
state->buffer_destroy_listener.notify = surface_handle_pending_buffer_destroy;
wl_list_init (&state->frame_callback_list);
state->has_new_geometry = FALSE;
state->frame_extents_changed = FALSE;
}
static void
@@ -317,18 +262,22 @@ static void
subsurface_surface_commit (MetaWaylandSurface *surface,
MetaWaylandPendingState *pending)
{
MetaSurfaceActor *surface_actor = surface->surface_actor;
float x, y;
if (pending->newly_attached)
{
MetaSurfaceActor *surface_actor = surface->surface_actor;
MetaWaylandBuffer *buffer = pending->buffer;
float x, y;
if (surface->buffer != NULL)
clutter_actor_show (CLUTTER_ACTOR (surface_actor));
else
clutter_actor_hide (CLUTTER_ACTOR (surface_actor));
if (buffer != NULL)
clutter_actor_show (CLUTTER_ACTOR (surface_actor));
else
clutter_actor_hide (CLUTTER_ACTOR (surface_actor));
clutter_actor_get_position (CLUTTER_ACTOR (surface_actor), &x, &y);
x += pending->dx;
y += pending->dy;
clutter_actor_set_position (CLUTTER_ACTOR (surface_actor), x, y);
clutter_actor_get_position (CLUTTER_ACTOR (surface_actor), &x, &y);
x += pending->dx;
y += pending->dy;
clutter_actor_set_position (CLUTTER_ACTOR (surface_actor), x, y);
}
}
static void
@@ -467,13 +416,16 @@ wl_surface_attach (struct wl_client *client,
else
buffer = NULL;
if (surface->buffer == buffer)
return;
if (surface->pending.buffer)
wl_list_remove (&surface->pending.buffer_destroy_listener.link);
surface->pending.newly_attached = TRUE;
surface->pending.buffer = buffer;
surface->pending.dx = dx;
surface->pending.dy = dy;
surface->pending.buffer = buffer;
surface->pending.newly_attached = TRUE;
if (buffer)
wl_signal_add (&buffer->destroy_signal,
@@ -521,6 +473,7 @@ wl_surface_frame (struct wl_client *client,
return;
callback = g_slice_new0 (MetaWaylandFrameCallback);
callback->compositor = surface->compositor;
callback->resource = wl_resource_create (client, &wl_callback_interface, META_WL_CALLBACK_VERSION, callback_id);
wl_resource_set_implementation (callback->resource, NULL, callback, destroy_frame_callback);
@@ -780,6 +733,23 @@ xdg_surface_set_parent (struct wl_client *client,
meta_window_set_transient_for (surface->window, transient_for);
}
static void
xdg_surface_set_margin (struct wl_client *client,
struct wl_resource *resource,
int32_t left_margin,
int32_t right_margin,
int32_t top_margin,
int32_t bottom_margin)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
surface->pending.frame_extents_changed = TRUE;
surface->pending.frame_extents.left = left_margin;
surface->pending.frame_extents.right = right_margin;
surface->pending.frame_extents.top = top_margin;
surface->pending.frame_extents.bottom = bottom_margin;
}
static void
xdg_surface_set_title (struct wl_client *client,
struct wl_resource *resource,
@@ -805,8 +775,8 @@ xdg_surface_show_window_menu (struct wl_client *client,
struct wl_resource *resource,
struct wl_resource *seat_resource,
uint32_t serial,
int32_t x,
int32_t y)
uint32_t x,
uint32_t y)
{
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
@@ -910,20 +880,6 @@ xdg_surface_ack_configure (struct wl_client *client,
* client gets the new state. */
}
static void
xdg_surface_set_window_geometry (struct wl_client *client,
struct wl_resource *resource,
int32_t x, int32_t y, int32_t width, int32_t height)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
surface->pending.has_new_geometry = TRUE;
surface->pending.new_geometry.x = x;
surface->pending.new_geometry.y = y;
surface->pending.new_geometry.width = width;
surface->pending.new_geometry.height = height;
}
static void
xdg_surface_set_maximized (struct wl_client *client,
struct wl_resource *resource)
@@ -968,13 +924,13 @@ xdg_surface_set_minimized (struct wl_client *client,
static const struct xdg_surface_interface meta_wayland_xdg_surface_interface = {
xdg_surface_destroy,
xdg_surface_set_parent,
xdg_surface_set_margin,
xdg_surface_set_title,
xdg_surface_set_app_id,
xdg_surface_show_window_menu,
xdg_surface_move,
xdg_surface_resize,
xdg_surface_ack_configure,
xdg_surface_set_window_geometry,
xdg_surface_set_maximized,
xdg_surface_unset_maximized,
xdg_surface_set_fullscreen,
@@ -1116,17 +1072,20 @@ bind_xdg_shell (struct wl_client *client,
guint32 version,
guint32 id)
{
struct wl_resource *resource;
XdgShell *xdg_shell;
if (version != META_XDG_SHELL_VERSION)
if (version != 1)
{
g_warning ("using xdg-shell without stable version %d\n", META_XDG_SHELL_VERSION);
g_warning ("using xdg-shell without stable version 1\n");
return;
}
xdg_shell = g_slice_new (XdgShell);
xdg_shell->resource = wl_resource_create (client, &xdg_shell_interface, META_XDG_SHELL_VERSION, id);
resource = wl_resource_create (client, &xdg_shell_interface, 1, id);
wl_resource_set_implementation (resource, &meta_wayland_xdg_shell_interface, data, NULL);
xdg_shell->resource = wl_resource_create (client, &xdg_shell_interface, 1, id);
wl_resource_set_implementation (xdg_shell->resource, &meta_wayland_xdg_shell_interface, data, NULL);
xdg_shell->client_destroy_listener.notify = xdg_shell_handle_client_destroy;
@@ -1392,13 +1351,13 @@ gtk_surface_destructor (struct wl_resource *resource)
static void
set_dbus_properties (struct wl_client *client,
struct wl_resource *resource,
const char *application_id,
const char *app_menu_path,
const char *menubar_path,
const char *window_object_path,
const char *application_object_path,
const char *unique_bus_name)
struct wl_resource *resource,
const char *application_id,
const char *app_menu_path,
const char *menubar_path,
const char *window_object_path,
const char *application_object_path,
const char *unique_bus_name)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
@@ -1424,9 +1383,9 @@ static const struct gtk_surface_interface meta_wayland_gtk_surface_interface = {
static void
get_gtk_surface (struct wl_client *client,
struct wl_resource *resource,
guint32 id,
struct wl_resource *surface_resource)
struct wl_resource *resource,
guint32 id,
struct wl_resource *surface_resource)
{
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
@@ -1450,14 +1409,14 @@ static const struct gtk_shell_interface meta_wayland_gtk_shell_interface = {
static void
bind_gtk_shell (struct wl_client *client,
void *data,
guint32 version,
guint32 id)
void *data,
guint32 version,
guint32 id)
{
struct wl_resource *resource;
resource = wl_resource_create (client, &gtk_shell_interface,
MIN (META_GTK_SHELL_VERSION, version), id);
MIN (META_GTK_SHELL_VERSION, version), id);
wl_resource_set_implementation (resource, &meta_wayland_gtk_shell_interface, data, NULL);
/* FIXME: ask the plugin */
@@ -1718,10 +1677,11 @@ 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),
@@ -1744,7 +1704,7 @@ bind_subcompositor (struct wl_client *client,
struct wl_resource *resource;
resource = wl_resource_create (client, &wl_subcompositor_interface,
MIN (META_WL_SUBCOMPOSITOR_VERSION, version), id);
MIN (META_WL_SUBCOMPOSITOR_VERSION, version), id);
wl_resource_set_implementation (resource, &meta_wayland_subcompositor_interface, data, NULL);
}
@@ -1752,21 +1712,19 @@ void
meta_wayland_shell_init (MetaWaylandCompositor *compositor)
{
if (wl_global_create (compositor->wayland_display,
&xdg_shell_interface,
META_XDG_SHELL_VERSION,
compositor, bind_xdg_shell) == NULL)
&xdg_shell_interface, 1,
compositor, bind_xdg_shell) == NULL)
g_error ("Failed to register a global xdg-shell object");
if (wl_global_create (compositor->wayland_display,
&wl_shell_interface,
META_WL_SHELL_VERSION,
compositor, bind_wl_shell) == NULL)
&wl_shell_interface, 1,
compositor, bind_wl_shell) == NULL)
g_error ("Failed to register a global wl-shell object");
if (wl_global_create (compositor->wayland_display,
&gtk_shell_interface,
META_GTK_SHELL_VERSION,
compositor, bind_gtk_shell) == NULL)
&gtk_shell_interface,
META_GTK_SHELL_VERSION,
compositor, bind_gtk_shell) == NULL)
g_error ("Failed to register a global gtk-shell object");
if (wl_global_create (compositor->wayland_display,
@@ -1805,8 +1763,8 @@ fill_states (struct wl_array *states, MetaWindow *window)
void
meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
int new_width,
int new_height)
int new_width,
int new_height)
{
if (surface->xdg_surface.resource)
{

View File

@@ -61,8 +61,8 @@ typedef struct
/* wl_surface.frame */
struct wl_list frame_callback_list;
MetaRectangle new_geometry;
gboolean has_new_geometry;
gboolean frame_extents_changed;
GtkBorder frame_extents;
} MetaWaylandPendingState;
typedef struct
@@ -109,8 +109,6 @@ struct _MetaWaylandSurface
GSList *pending_placement_ops;
} sub;
gboolean has_set_geometry;
/* All the pending state that wl_surface.commit will apply. */
MetaWaylandPendingState pending;
};

View File

@@ -1,548 +0,0 @@
/*
* 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, &touch_interface, touch, unbind_resource);
wl_list_insert (&touch->resource_list, wl_resource_get_link (cr));
}

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