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
227 changed files with 46252 additions and 41464 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

35
.gitignore vendored
View File

@@ -3,7 +3,6 @@ Makefile.in
Makefile.in.in Makefile.in.in
aclocal.m4 aclocal.m4
autom4te.cache autom4te.cache
build-aux
compile compile
config.guess config.guess
config.h config.h
@@ -20,11 +19,11 @@ libtool
ltmain.sh ltmain.sh
missing missing
.deps .deps
50-mutter-navigation.xml src/50-mutter-navigation.xml
50-mutter-system.xml src/50-mutter-system.xml
50-mutter-windows.xml src/50-mutter-windows.xml
mutter.desktop src/mutter.desktop
mutter-wayland.desktop src/mutter-wayland.desktop
*.o *.o
*.a *.a
*.lo *.lo
@@ -33,6 +32,10 @@ mutter-wayland.desktop
*.swp *.swp
*.gir *.gir
*.typelib *.typelib
tidy-enum-types.[ch]
tidy-marshal.[ch]
stamp-tidy-enum-types.h
stamp-tidy-marshal.h
stamp-h1 stamp-h1
*.gmo *.gmo
*.make *.make
@@ -41,12 +44,10 @@ stamp-it
.intltool-merge-cache .intltool-merge-cache
POTFILES POTFILES
po/*.pot po/*.pot
50-metacity-desktop-key.xml
50-metacity-key.xml
libmutter.pc libmutter.pc
mutter mutter
mutter-restart-helper
mutter-test-client
mutter-test-runner
mutter-all.test
org.gnome.mutter.gschema.valid org.gnome.mutter.gschema.valid
org.gnome.mutter.gschema.xml org.gnome.mutter.gschema.xml
org.gnome.mutter.wayland.gschema.valid org.gnome.mutter.wayland.gschema.valid
@@ -55,6 +56,19 @@ testasyncgetprop
testboxes testboxes
testgradient testgradient
m4/* 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 INSTALL
mkinstalldirs mkinstalldirs
src/mutter-enum-types.[ch] src/mutter-enum-types.[ch]
@@ -70,7 +84,6 @@ src/xdg-shell-protocol.c
src/xdg-shell-server-protocol.h src/xdg-shell-server-protocol.h
src/xserver-protocol.c src/xserver-protocol.c
src/xserver-server-protocol.h src/xserver-server-protocol.h
src/meta/meta-version.h
doc/reference/*.args doc/reference/*.args
doc/reference/*.bak doc/reference/*.bak
doc/reference/*.hierarchy doc/reference/*.hierarchy

View File

@@ -1,13 +1,10 @@
SUBDIRS = data src po doc SUBDIRS=src po doc
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
DISTCLEANFILES = \ DISTCLEANFILES = intltool-extract intltool-merge intltool-update po/stamp-it po/.intltool-merge-cache
intltool-extract \
intltool-merge \
intltool-update \
po/stamp-it \
po/.intltool-merge-cache
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}

159
NEWS
View File

@@ -1,162 +1,3 @@
3.15.2
======
* Don't enable hiDPI on monitors with broken EDID [Bastien; #734839]
* Prevent crash applying monitor config for a closed lid [Rui; #739450]
* Fix "flicker" during startup transition [Ray; #740377]
* Misc. bug fixes [Lan, Florian, Carlos; #731521, #740133, #738890]
Contributors:
Emmanuele Bassi, Carlos Garnacho, Jonathon Jongsma, Ting-Wei Lan, Rui Matos,
Florian Müllner, Bastien Nocera, Jasper St. Pierre, Ray Strode
Translations:
Kjartan Maraas [nb]
3.15.1
======
* Use GResources for theme loading [Cosimo; #736936]
* Fix headerbar drag getting stuck on xwayland [Carlos; #738411]
* Fix wayland hiDPI regressions [Adel; #739161]
* Misc bug fixes and cleanups [Jasper, Rui, Carlos; #662962, #738630, #738888,
#738890]
Contributors:
Cosimo Cecchi, Adel Gadllah, Carlos Garnacho, Rui Matos, Florian Müllner,
Jasper St. Pierre
3.14.1
======
* Fix move-titlebar-onscreen function [Florian; #736915]
* Fix stacking of the guard window [Owen; #737233]
* Fix keycode lookup for non-default layouts [Rui; #737134]
* Fix workspaces-only-on-primary handling [Florian; #737178]
* Don't unstick sticky windows on workspace removal [Florian; #737625]
* Do not auto-minimize fullscreen windows [Jasper; #705177]
* Upload keymap to newly added keyboard devices [Rui; #737673]
* Apply keyboard repeat settings [Rui; #728055]
* Don't send pressed keys on enter [Rui; #727178]
* Fix build without wayland/native [Rico; #738225]
* Send modifiers after the key event [Rui; #738238]
* Fix unredirect heuristic [Adel; #738271]
* Do not show system chrome over fullscreen windows [Florian; #693991]
* Misc. bug fixes [Florian, Adel, Tom; #737135, #737581, #738146, #738384]
Contributors:
Tom Beckmann, Adel Gadllah, Carlos Garnacho, Rui Matos, Florian Müllner,
Jasper St. Pierre, Rico Tzschichholz, Owen W. Taylor
Translations:
Krishnababu Krothapalli [te], Мирослав Николић [sr, sr@latin],
Alexander Shopov [bg], Saibal Ray [bn_IN], Milo Casagrande [it],
Rūdolfs Mazurs [lv]
3.14.0
======
* Fix placement of popup windows on wayland [Jasper; #736812]
* Only increment serial once per event [Jasper; #736840]
* Fix window positioning regression with non-GTK+ toolkits [Owen; #736719]
Contributors:
Jasper St. Pierre, Owen W. Taylor
Translations:
Saibal Ray [bn_IN], Dušan Kazik [sk], Manoj Kumar Giri [or],
Christian Kirbach [de], Ask H. Larsen [da], YunQiang Su [zh_CN],
Bernd Homuth [de], Shankar Prasad [kn], Petr Kovar [cs], Rajesh Ranjan [hi]
3.13.92
=======
* Rewrite background code [Owen; #735637, #736568]
* Fix size in nested mode [Owen; #736279]
* Fix destroy animation of background windows [Florian; #735927]
* Wire keymap changes up to the wayland frontend [Rui; #736433]
* Add a test framework and stacking tests [Owen; #736505]
* Simplify handling of the merged X and wayland stack [Owen; #736559]
* Fix cursor size on HiDPI [Adel; #729337]
* Misc. bug fixes [Owen; #735632, #736589, #736694]
Contributors:
Adel Gadllah, Rui Matos, Florian Müllner, Jasper St. Pierre, Owen W. Taylor
Translations:
Andika Triwidada [id], Piotr Drąg [pl], Changwoo Ryu [ko],
Kjartan Maraas [nb], Ville-Pekka Vainio [fi], Yuri Myasoedov [ru],
Aurimas Černius [lt], Balázs Úr [hu], Sweta Kothari [gu], A S Alam [pa],
Sandeep Sheshrao Shedmake [mr], Shantha kumar [ta], Gil Forcada [ca],
Carles Ferrando [ca@valencia], Mattias Eriksson [sv]
3.13.91
=======
* Misc. bug fixes [Carlos; #735452]
Contributors:
Adel Gadllah, Carlos Garnacho, Rui Matos, Jasper St. Pierre,
Rico Tzschichholz
Translations:
Chao-Hsiung Liao po/zh_HK, zh_TW.po, Enrico Nicoletto [pt_BR],
Kjartan Maraas [nb], Fran Diéguez [gl], Yosef Or Boczko [he],
Maria Mavridou [el], Claude Paroz [fr]
3.13.90
=======
* Only call XSync() once per frame [Rui; #728464]
* Update capabilities on device list changes [Carlos; #733563]
* Make use of GLSL optional [Adel; #733623]
* Handle gestures and touch events on wayland [Carlos; #733631]
* Add support for unminimize compositor effects [Cosimo; #733789]
* Always set the frame background to None [Giovanni; #734054]
* Add backend methods to handle keymaps [Rui; #734301]
* Actually mark revalidated MetaTextureTower levels as valid [Owen; #734400]
* Rely on explicit -backward switcher keybindings instead of <shift>-magic
[Christophe; #732295, #732385]
* Misc. bug fixes and cleanups [Rui, Adel, Christophe; #727178, #734852,
#734960]
Contributors:
Emmanuele Bassi, Giovanni Campagna, Cosimo Cecchi, Piotr Drąg,
Christophe Fergeau, Adel Gadllah, Carlos Garnacho, Rui Matos,
Florian Müllner, Jasper St. Pierre, Rico Tzschichholz, Olav Vitters,
Owen W. Taylor
Translations:
Kjartan Maraas [nb], Inaki Larranaga Murgoitio [eu], Lasse Liehu [fi],
ngoswami [as], Daniel Mustieles [es]
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 3.13.2
====== ======
* Add basic HiDPI support on wayland [Adel; #728902] * Add basic HiDPI support on wayland [Adel; #728902]

View File

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

View File

@@ -1,7 +1,8 @@
AC_PREREQ(2.62) AC_PREREQ(2.50)
AC_CONFIG_MACRO_DIR([m4])
m4_define([mutter_major_version], [3]) m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [15]) m4_define([mutter_minor_version], [13])
m4_define([mutter_micro_version], [2]) m4_define([mutter_micro_version], [2])
m4_define([mutter_version], m4_define([mutter_version],
@@ -13,7 +14,6 @@ AC_INIT([mutter], [mutter_version],
[http://bugzilla.gnome.org/enter_bug.cgi?product=mutter]) [http://bugzilla.gnome.org/enter_bug.cgi?product=mutter])
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_SRCDIR(src/core/display.c) AC_CONFIG_SRCDIR(src/core/display.c)
AC_CONFIG_HEADERS(config.h) AC_CONFIG_HEADERS(config.h)
@@ -40,14 +40,12 @@ GETTEXT_PACKAGE=mutter
AC_SUBST(GETTEXT_PACKAGE) AC_SUBST(GETTEXT_PACKAGE)
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[Name of default gettext domain]) AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[Name of default gettext domain])
LT_PREREQ([2.2.6]) IT_PROG_INTLTOOL([0.34.90])
LT_INIT([disable-static])
IT_PROG_INTLTOOL([0.41])
AC_PROG_CC AC_PROG_CC
AC_PROG_CC_C_O AC_ISC_POSIX
AC_PROG_INSTALL
AC_HEADER_STDC AC_HEADER_STDC
PKG_PROG_PKG_CONFIG([0.21]) AC_LIBTOOL_WIN32_DLL
AM_PROG_LIBTOOL
# Sets GLIB_GENMARSHAL and GLIB_MKENUMS # Sets GLIB_GENMARSHAL and GLIB_MKENUMS
AM_PATH_GLIB_2_0() AM_PATH_GLIB_2_0()
@@ -72,26 +70,15 @@ CLUTTER_PACKAGE=clutter-1.0
MUTTER_PC_MODULES=" MUTTER_PC_MODULES="
gtk+-3.0 >= 3.9.11 gtk+-3.0 >= 3.9.11
gio-unix-2.0 >= 2.25.10 gio-2.0 >= 2.25.10
pango >= 1.2.0 pango >= 1.2.0
cairo >= 1.10.0 cairo >= 1.10.0
gsettings-desktop-schemas >= 3.7.3 gsettings-desktop-schemas >= 3.7.3
$CLUTTER_PACKAGE >= 1.19.5 xcomposite >= 0.2 xfixes xext xdamage xi >= 1.6.0
$CLUTTER_PACKAGE >= 1.17.5
cogl-1.0 >= 1.17.1 cogl-1.0 >= 1.17.1
upower-glib >= 0.99.0 upower-glib >= 0.99.0
gnome-desktop-3.0 gnome-desktop-3.0
xcomposite >= 0.2
xcursor
xdamage
xext
xfixes
xi >= 1.6.0
xkbfile
xkeyboard-config
xkbcommon >= 0.4.3
xkbcommon-x11
x11-xcb
xcb-randr
" "
GLIB_GSETTINGS GLIB_GSETTINGS
@@ -120,18 +107,26 @@ AC_ARG_WITH(libcanberra,
[disable the use of libcanberra for playing sounds]),, [disable the use of libcanberra for playing sounds]),,
with_libcanberra=auto) 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], AC_ARG_WITH([xwayland-path],
[AS_HELP_STRING([--with-xwayland-path], [Absolute path for an X Wayland server])], [AS_HELP_STRING([--with-xwayland-path], [Absolute path for an X Wayland server])],
[XWAYLAND_PATH="$withval"], [XWAYLAND_PATH="$withval"],
[XWAYLAND_PATH="$bindir/Xwayland"]) [XWAYLAND_PATH="$bindir/Xwayland"])
AC_ARG_ENABLE(installed_tests, AM_GLIB_GNU_GETTEXT
AS_HELP_STRING([--enable-installed-tests],
[Install test programs (default: no)]),,
[enable_installed_tests=no])
AM_CONDITIONAL(BUILDOPT_INSTALL_TESTS, test x$enable_installed_tests = xyes)
## here we get the flags we'll actually use ## 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 # Unconditionally use this dir to avoid a circular dep with gnomecc
GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings" GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings"
@@ -196,27 +191,23 @@ if test x$found_introspection != xno; then
AC_SUBST(META_GIR) AC_SUBST(META_GIR)
fi 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) 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, $MUTTER_PC_MODULES)
PKG_CHECK_MODULES(MUTTER_NATIVE_BACKEND, [clutter-egl-1.0 libdrm libsystemd libinput gudev-1.0 gbm >= 10.3], [have_native_backend=yes], [have_native_backend=no]) PKG_CHECK_MODULES(MUTTER_NATIVE_BACKEND, [libdrm libsystemd], [have_native_backend=yes], [have_native_backend=no])
if test $have_native_backend = yes; then if test $have_native_backend = yes; then
AC_DEFINE([HAVE_NATIVE_BACKEND],[1],[Define if you want to enable the native (KMS) backend based on systemd]) AC_DEFINE([HAVE_NATIVE_BACKEND],[1],[Define if you want to enable the native (KMS) backend based on systemd])
fi fi
AM_CONDITIONAL([HAVE_NATIVE_BACKEND],[test $have_native_backend = yes]) AM_CONDITIONAL([HAVE_NATIVE_BACKEND],[test $have_native_backend = yes])
PKG_CHECK_MODULES(MUTTER_WAYLAND, [clutter-wayland-1.0 clutter-wayland-compositor-1.0 wayland-server >= 1.5.90], [have_wayland=yes], [have_wayland=no])
if test $have_wayland = yes; then
AC_PATH_PROG([WAYLAND_SCANNER],[wayland-scanner],[no])
AS_IF([test $WAYLAND_SCANNER = "no"],
AC_MSG_ERROR([Could not find wayland-scanner in your PATH, required for parsing wayland extension protocols]))
AC_SUBST([WAYLAND_SCANNER])
AC_DEFINE([HAVE_WAYLAND],[1],[Define if you want to enable Wayland support])
fi
AM_CONDITIONAL([HAVE_WAYLAND],[test $have_wayland = yes])
PKG_CHECK_EXISTS([xi >= 1.6.99.1], PKG_CHECK_EXISTS([xi >= 1.6.99.1],
AC_DEFINE([HAVE_XI23],[1],[Define if you have support for XInput 2.3 or greater])) AC_DEFINE([HAVE_XI23],[1],[Define if you have support for XInput 2.3 or greater]))
@@ -253,8 +244,16 @@ if test x$have_xinerama = xno; then
AC_MSG_ERROR([Xinerama extension was not found]) AC_MSG_ERROR([Xinerama extension was not found])
fi fi
AC_DEFINE_UNQUOTED([XKB_BASE], ["`$PKG_CONFIG --variable xkb_base xkeyboard-config`"], found_xkb=no
[XKB base dir]) AC_CHECK_LIB(X11, XkbQueryExtension,
[AC_CHECK_HEADER(X11/XKBlib.h,
found_xkb=yes)],
, $ALL_X_LIBS)
if test "x$found_xkb" = "xyes"; then
AC_DEFINE(HAVE_XKB, , [Have keyboard extension library])
fi
RANDR_LIBS= RANDR_LIBS=
found_randr=no found_randr=no
@@ -300,6 +299,17 @@ fi
AM_CONDITIONAL(HAVE_SM, test "$found_sm" = "yes") 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) AC_PATH_PROG(ZENITY, zenity, no)
if test x"$ZENITY" = xno; then if test x"$ZENITY" = xno; then
AC_MSG_ERROR([zenity not found in your path - needed for dialogs]) AC_MSG_ERROR([zenity not found in your path - needed for dialogs])
@@ -314,6 +324,11 @@ fi
GTK_DOC_CHECK([1.15], [--flavour no-tmpl]) 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) #### Warnings (last since -Werror can disturb other tests)
# Stay command-line compatible with the gnome-common configure option. Here # Stay command-line compatible with the gnome-common configure option. Here
@@ -382,7 +397,6 @@ changequote([,])dnl
AC_CONFIG_FILES([ AC_CONFIG_FILES([
Makefile Makefile
data/Makefile
doc/Makefile doc/Makefile
doc/man/Makefile doc/man/Makefile
doc/reference/Makefile doc/reference/Makefile
@@ -390,7 +404,6 @@ doc/reference/meta-docs.sgml
src/Makefile src/Makefile
src/libmutter.pc src/libmutter.pc
src/compositor/plugins/Makefile src/compositor/plugins/Makefile
src/meta/meta-version.h
po/Makefile.in po/Makefile.in
]) ])

View File

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

View File

@@ -111,22 +111,6 @@ IGNORE_HFILES= \
xprops.h \ xprops.h \
$(NULL) $(NULL)
if !HAVE_NATIVE_BACKEND
IGNORE_HFILES+= \
meta-backend-native.h \
meta-cursor-renderer-native.h \
meta-idle-monitor-native.h \
meta-monitor-manager-kms.h \
$(NULL)
endif
if !HAVE_WAYLAND
IGNORE_HFILES += \
meta-surface-actor-wayland.h \
wayland \
$(NULL)
endif
MKDB_OPTIONS+=--ignore-files="$(IGNORE_HFILES)" MKDB_OPTIONS+=--ignore-files="$(IGNORE_HFILES)"
# Images to copy into HTML directory. # Images to copy into HTML directory.

View File

@@ -300,7 +300,6 @@ MetaPluginVersion
META_PLUGIN_DECLARE META_PLUGIN_DECLARE
meta_plugin_switch_workspace_completed meta_plugin_switch_workspace_completed
meta_plugin_minimize_completed meta_plugin_minimize_completed
meta_plugin_unminimize_completed
meta_plugin_maximize_completed meta_plugin_maximize_completed
meta_plugin_unmaximize_completed meta_plugin_unmaximize_completed
meta_plugin_map_completed meta_plugin_map_completed
@@ -556,7 +555,7 @@ meta_window_is_monitor_sized
meta_window_is_override_redirect meta_window_is_override_redirect
meta_window_is_skip_taskbar meta_window_is_skip_taskbar
meta_window_get_rect meta_window_get_rect
meta_window_get_buffer_rect meta_window_get_input_rect
meta_window_get_frame_rect meta_window_get_frame_rect
meta_window_get_outer_rect meta_window_get_outer_rect
meta_window_client_rect_to_frame_rect meta_window_client_rect_to_frame_rect

View File

@@ -259,6 +259,8 @@ Overview of Theme Format Version 1
<!-- color obtained by a 0.5 alpha composite of the second color onto the first --> <!-- color obtained by a 0.5 alpha composite of the second color onto the first -->
<color value="blend/gtk:bg[SELECTED]/gtk:fg[SELECTED]/0.5"/> <color value="blend/gtk:bg[SELECTED]/gtk:fg[SELECTED]/0.5"/>
</gradient> </gradient>
<!-- image has an optional colorize="#color" attribute to give the
image a certain color -->
<image filename="foo.png" alpha="0.7" <image filename="foo.png" alpha="0.7"
x="10" y="30" width="width / 3" height="height / 4"/> x="10" y="30" width="width / 3" height="height / 4"/>
<gtk_arrow state="normal" shadow="in" arrow="up" <gtk_arrow state="normal" shadow="in" arrow="up"

View File

@@ -23,8 +23,7 @@ environment.</description>
<download-page rdf:resource="http://download.gnome.org/sources/mutter/" /> <download-page rdf:resource="http://download.gnome.org/sources/mutter/" />
<bug-database rdf:resource="http://bugzilla.gnome.org/browse.cgi?product=mutter" /> <bug-database rdf:resource="http://bugzilla.gnome.org/browse.cgi?product=mutter" />
<category rdf:resource="http://api.gnome.org/doap-extensions#core" /> <category rdf:resource="http://api.gnome.org/doap-extensions#desktop" />
<programming-language>C</programming-language>
<maintainer> <maintainer>
<foaf:Person> <foaf:Person>

View File

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

View File

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

1520
po/as.po

File diff suppressed because it is too large Load Diff

1503
po/bg.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1068
po/ca.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1284
po/cs.po

File diff suppressed because it is too large Load Diff

1298
po/da.po

File diff suppressed because it is too large Load Diff

1530
po/de.po

File diff suppressed because it is too large Load Diff

3490
po/el.po

File diff suppressed because it is too large Load Diff

895
po/es.po

File diff suppressed because it is too large Load Diff

1259
po/eu.po

File diff suppressed because it is too large Load Diff

1431
po/fi.po

File diff suppressed because it is too large Load Diff

1056
po/fr.po

File diff suppressed because it is too large Load Diff

886
po/gl.po

File diff suppressed because it is too large Load Diff

1759
po/gu.po

File diff suppressed because it is too large Load Diff

880
po/he.po

File diff suppressed because it is too large Load Diff

1952
po/hi.po

File diff suppressed because it is too large Load Diff

1333
po/hu.po

File diff suppressed because it is too large Load Diff

926
po/id.po

File diff suppressed because it is too large Load Diff

1346
po/it.po

File diff suppressed because it is too large Load Diff

1978
po/kn.po

File diff suppressed because it is too large Load Diff

1022
po/ko.po

File diff suppressed because it is too large Load Diff

1057
po/lt.po

File diff suppressed because it is too large Load Diff

1297
po/lv.po

File diff suppressed because it is too large Load Diff

1810
po/mr.po

File diff suppressed because it is too large Load Diff

1202
po/nb.po

File diff suppressed because it is too large Load Diff

1808
po/or.po

File diff suppressed because it is too large Load Diff

1299
po/pa.po

File diff suppressed because it is too large Load Diff

1052
po/pl.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1193
po/ru.po

File diff suppressed because it is too large Load Diff

502
po/sk.po

File diff suppressed because it is too large Load Diff

1300
po/sr.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

2200
po/sv.po

File diff suppressed because it is too large Load Diff

1846
po/ta.po

File diff suppressed because it is too large Load Diff

1877
po/te.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -45,68 +45,26 @@
_description="Move window one monitor down" /> _description="Move window one monitor down" />
<KeyListEntry name="switch-applications" <KeyListEntry name="switch-applications"
reverse-entry="switch-applications-backward"
_description="Switch applications"/> _description="Switch applications"/>
<KeyListEntry name="switch-applications-backward"
reverse-entry="switch-applications"
hidden="true"
_description="Switch to previous application"/>
<KeyListEntry name="switch-windows" <KeyListEntry name="switch-windows"
reverse-entry="switch-windows-backward"
_description="Switch windows"/> _description="Switch windows"/>
<KeyListEntry name="switch-windows-backward"
reverse-entry="switch-windows"
hidden="true"
_description="Switch to previous window"/>
<KeyListEntry name="switch-group" <KeyListEntry name="switch-group"
reverse-entry="switch-group-backward"
_description="Switch windows of an application"/> _description="Switch windows of an application"/>
<KeyListEntry name="switch-group-backward"
reverse-entry="switch-group"
hidden="true"
_description="Switch to previous window of an application"/>
<KeyListEntry name="switch-panels" <KeyListEntry name="switch-panels"
reverse-entry="switch-panels-backward"
_description="Switch system controls"/> _description="Switch system controls"/>
<KeyListEntry name="switch-panels-backward"
reverse-entry="switch-panels"
hidden="true"
_description="Switch to previous system control"/>
<KeyListEntry name="cycle-windows" <KeyListEntry name="cycle-windows"
reverse-entry="cycle-windows-backward"
_description="Switch windows directly"/> _description="Switch windows directly"/>
<KeyListEntry name="cycle-windows-backward"
reverse-entry="cycle-windows"
hidden="true"
_description="Switch directly to previous window"/>
<KeyListEntry name="cycle-group" <KeyListEntry name="cycle-group"
reverse-entry="cycle-group-backward"
_description="Switch windows of an app directly"/> _description="Switch windows of an app directly"/>
<KeyListEntry name="cycle-group-backward"
reverse-entry="cycle-group"
hidden="true"
_description="Switch directly to previous window of an app"/>
<KeyListEntry name="cycle-panels" <KeyListEntry name="cycle-panels"
reverse-entry="cycle-panels-backward"
_description="Switch system controls directly"/> _description="Switch system controls directly"/>
<KeyListEntry name="cycle-panels-backward"
reverse-entry="cycle-panels"
hidden="true"
_description="Switch directly to previous system control"/>
<KeyListEntry name="show-desktop" <KeyListEntry name="show-desktop"
_description="Hide all normal windows"/> _description="Hide all normal windows"/>

View File

@@ -1,49 +0,0 @@
# A framework for running scripted tests
if HAVE_WAYLAND
if BUILDOPT_INSTALL_TESTS
stackingdir = $(pkgdatadir)/tests/stacking
dist_stacking_DATA = \
tests/stacking/basic-x11.metatest \
tests/stacking/basic-wayland.metatest \
tests/stacking/minimized.metatest \
tests/stacking/mixed-windows.metatest \
tests/stacking/override-redirect.metatest
mutter-all.test: tests/mutter-all.test.in
$(AM_V_GEN) sed -e "s|@libexecdir[@]|$(libexecdir)|g" $< > $@.tmp && mv $@.tmp $@
installedtestsdir = $(datadir)/installed-tests/mutter
installedtests_DATA = mutter-all.test
installedtestsbindir = $(libexecdir)/installed-tests/mutter
installedtestsbin_PROGRAMS = mutter-test-client mutter-test-runner
else
noinst_PROGRAMS += mutter-test-client mutter-test-runner
endif
EXTRA_DIST += tests/mutter-all.test.in
mutter_test_client_SOURCES = tests/test-client.c
mutter_test_client_LDADD = $(MUTTER_LIBS) libmutter.la
mutter_test_runner_SOURCES = tests/test-runner.c
mutter_test_runner_LDADD = $(MUTTER_LIBS) libmutter.la
.PHONY: run-tests
run-tests: mutter-test-client mutter-test-runner
./mutter-test-runner $(dist_stacking_DATA)
endif
# Some random test programs for bits of the code
testboxes_SOURCES = core/testboxes.c
testasyncgetprop_SOURCES = x11/testasyncgetprop.c
noinst_PROGRAMS+=testboxes testasyncgetprop
testboxes_LDADD = $(MUTTER_LIBS) libmutter.la
testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter.la

View File

@@ -5,35 +5,33 @@ lib_LTLIBRARIES = libmutter.la
SUBDIRS=compositor/plugins SUBDIRS=compositor/plugins
EXTRA_DIST = INCLUDES= \
NULL =
AM_CPPFLAGS = \
-DCLUTTER_ENABLE_COMPOSITOR_API \ -DCLUTTER_ENABLE_COMPOSITOR_API \
-DCLUTTER_ENABLE_EXPERIMENTAL_API \ -DCLUTTER_ENABLE_EXPERIMENTAL_API \
-DCOGL_ENABLE_EXPERIMENTAL_API \ -DCOGL_ENABLE_EXPERIMENTAL_API \
-DCOGL_ENABLE_EXPERIMENTAL_2_0_API \ -DCOGL_ENABLE_EXPERIMENTAL_2_0_API \
-DCLUTTER_DISABLE_DEPRECATION_WARNINGS \
-DCOGL_DISABLE_DEPRECATION_WARNINGS \
$(MUTTER_CFLAGS) \ $(MUTTER_CFLAGS) \
$(MUTTER_NATIVE_BACKEND_CFLAGS) \ $(MUTTER_NATIVE_BACKEND_CFLAGS) \
-I$(builddir) \
-I$(srcdir) \ -I$(srcdir) \
-I$(srcdir)/backends \ -I$(srcdir)/backends \
-I$(srcdir)/core \ -I$(srcdir)/core \
-I$(srcdir)/ui \ -I$(srcdir)/ui \
-I$(srcdir)/compositor \ -I$(srcdir)/compositor \
-DMUTTER_LIBEXECDIR=\"$(libexecdir)\" \ -DMUTTER_LIBEXECDIR=\"$(libexecdir)\" \
-DMUTTER_LOCALEDIR=\"$(localedir)\" \ -DHOST_ALIAS=\"@HOST_ALIAS@\" \
-DMUTTER_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\" \
-DMUTTER_PKGDATADIR=\"$(pkgdatadir)\" \ -DMUTTER_PKGDATADIR=\"$(pkgdatadir)\" \
-DMUTTER_DATADIR=\"$(datadir)\" \ -DMUTTER_DATADIR=\"$(datadir)\" \
-DG_LOG_DOMAIN=\"mutter\" \ -DG_LOG_DOMAIN=\"mutter\" \
-DSN_API_NOT_YET_FROZEN=1 \ -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_PKGLIBDIR=\"$(pkglibdir)\" \
-DMUTTER_PLUGIN_DIR=\"$(MUTTER_PLUGIN_DIR)\" \ -DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\" \
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \ -DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \
-DXWAYLAND_PATH=\"$(XWAYLAND_PATH)\" \ -DXWAYLAND_PATH='"@XWAYLAND_PATH@"'
$(NULL)
mutter_built_sources = \ mutter_built_sources = \
$(dbus_idle_built_sources) \ $(dbus_idle_built_sources) \
@@ -41,25 +39,18 @@ mutter_built_sources = \
$(dbus_login1_built_sources) \ $(dbus_login1_built_sources) \
mutter-enum-types.h \ mutter-enum-types.h \
mutter-enum-types.c \ mutter-enum-types.c \
$(NULL)
if HAVE_WAYLAND
mutter_built_sources += \
gtk-shell-protocol.c \ gtk-shell-protocol.c \
gtk-shell-server-protocol.h \ gtk-shell-server-protocol.h \
xdg-shell-protocol.c \ xdg-shell-protocol.c \
xdg-shell-server-protocol.h \ xdg-shell-server-protocol.h
$(NULL)
endif
wayland_protocols = \ wayland_protocols = \
wayland/protocol/gtk-shell.xml \ wayland/protocol/gtk-shell.xml \
wayland/protocol/xdg-shell.xml \ wayland/protocol/xdg-shell.xml
$(NULL)
libmutter_la_SOURCES = \ libmutter_la_SOURCES = \
backends/meta-backend.c \ backends/meta-backend.c \
meta/meta-backend.h \ backends/meta-backend.h \
backends/meta-backend-private.h \ backends/meta-backend-private.h \
backends/meta-cursor.c \ backends/meta-cursor.c \
backends/meta-cursor.h \ backends/meta-cursor.h \
@@ -79,8 +70,6 @@ libmutter_la_SOURCES = \
backends/meta-monitor-manager.h \ backends/meta-monitor-manager.h \
backends/meta-monitor-manager-dummy.c \ backends/meta-monitor-manager-dummy.c \
backends/meta-monitor-manager-dummy.h \ backends/meta-monitor-manager-dummy.h \
backends/meta-stage.h \
backends/meta-stage.c \
backends/edid-parse.c \ backends/edid-parse.c \
backends/edid.h \ backends/edid.h \
backends/x11/meta-backend-x11.c \ backends/x11/meta-backend-x11.c \
@@ -107,17 +96,11 @@ libmutter_la_SOURCES = \
compositor/compositor.c \ compositor/compositor.c \
compositor/compositor-private.h \ compositor/compositor-private.h \
compositor/meta-background.c \ compositor/meta-background.c \
compositor/meta-background-private.h \
compositor/meta-background-actor.c \ compositor/meta-background-actor.c \
compositor/meta-background-actor-private.h \ compositor/meta-background-actor-private.h \
compositor/meta-background-image.c \
compositor/meta-background-group.c \ compositor/meta-background-group.c \
compositor/meta-cullable.c \ compositor/meta-cullable.c \
compositor/meta-cullable.h \ compositor/meta-cullable.h \
compositor/meta-dnd-actor.c \
compositor/meta-dnd-actor-private.h \
compositor/meta-feedback-actor.c \
compositor/meta-feedback-actor-private.h \
compositor/meta-module.c \ compositor/meta-module.c \
compositor/meta-module.h \ compositor/meta-module.h \
compositor/meta-plugin.c \ compositor/meta-plugin.c \
@@ -131,6 +114,12 @@ libmutter_la_SOURCES = \
compositor/meta-surface-actor.h \ compositor/meta-surface-actor.h \
compositor/meta-surface-actor-x11.c \ compositor/meta-surface-actor-x11.c \
compositor/meta-surface-actor-x11.h \ compositor/meta-surface-actor-x11.h \
compositor/meta-surface-actor-wayland.c \
compositor/meta-surface-actor-wayland.h \
compositor/meta-stage.h \
compositor/meta-stage.c \
compositor/meta-sync-ring.c \
compositor/meta-sync-ring.h \
compositor/meta-texture-rectangle.c \ compositor/meta-texture-rectangle.c \
compositor/meta-texture-rectangle.h \ compositor/meta-texture-rectangle.h \
compositor/meta-texture-tower.c \ compositor/meta-texture-tower.c \
@@ -146,7 +135,6 @@ libmutter_la_SOURCES = \
meta/compositor.h \ meta/compositor.h \
meta/meta-background.h \ meta/meta-background.h \
meta/meta-background-actor.h \ meta/meta-background-actor.h \
meta/meta-background-image.h \
meta/meta-background-group.h \ meta/meta-background-group.h \
meta/meta-plugin.h \ meta/meta-plugin.h \
meta/meta-shadow-factory.h \ meta/meta-shadow-factory.h \
@@ -167,8 +155,8 @@ libmutter_la_SOURCES = \
meta/errors.h \ meta/errors.h \
core/frame.c \ core/frame.c \
core/frame.h \ core/frame.h \
core/meta-gesture-tracker.c \ ui/gradient.c \
core/meta-gesture-tracker-private.h \ meta/gradient.h \
core/keybindings.c \ core/keybindings.c \
core/keybindings-private.h \ core/keybindings-private.h \
core/main.c \ core/main.c \
@@ -180,7 +168,6 @@ libmutter_la_SOURCES = \
core/screen-private.h \ core/screen-private.h \
meta/screen.h \ meta/screen.h \
meta/types.h \ meta/types.h \
core/restart.c \
core/stack.c \ core/stack.c \
core/stack.h \ core/stack.h \
core/stack-tracker.c \ core/stack-tracker.c \
@@ -209,8 +196,6 @@ libmutter_la_SOURCES = \
x11/iconcache.h \ x11/iconcache.h \
x11/async-getprop.c \ x11/async-getprop.c \
x11/async-getprop.h \ x11/async-getprop.h \
x11/events.c \
x11/events.h \
x11/group-private.h \ x11/group-private.h \
x11/group-props.c \ x11/group-props.c \
x11/group-props.h \ x11/group-props.h \
@@ -226,22 +211,12 @@ libmutter_la_SOURCES = \
x11/xprops.c \ x11/xprops.c \
x11/xprops.h \ x11/xprops.h \
x11/mutter-Xatomtype.h \ x11/mutter-Xatomtype.h \
$(NULL)
if HAVE_WAYLAND
libmutter_la_SOURCES += \
compositor/meta-surface-actor-wayland.c \
compositor/meta-surface-actor-wayland.h \
wayland/meta-wayland.c \ wayland/meta-wayland.c \
wayland/meta-wayland.h \ wayland/meta-wayland.h \
wayland/meta-wayland-private.h \ wayland/meta-wayland-private.h \
wayland/meta-xwayland.c \ wayland/meta-xwayland.c \
wayland/meta-xwayland.h \ wayland/meta-xwayland.h \
wayland/meta-xwayland-private.h \ wayland/meta-xwayland-private.h \
wayland/meta-wayland-buffer.c \
wayland/meta-wayland-buffer.h \
wayland/meta-wayland-region.c \
wayland/meta-wayland-region.h \
wayland/meta-wayland-data-device.c \ wayland/meta-wayland-data-device.c \
wayland/meta-wayland-data-device.h \ wayland/meta-wayland-data-device.h \
wayland/meta-wayland-keyboard.c \ wayland/meta-wayland-keyboard.c \
@@ -250,8 +225,6 @@ libmutter_la_SOURCES += \
wayland/meta-wayland-pointer.h \ wayland/meta-wayland-pointer.h \
wayland/meta-wayland-seat.c \ wayland/meta-wayland-seat.c \
wayland/meta-wayland-seat.h \ wayland/meta-wayland-seat.h \
wayland/meta-wayland-touch.c \
wayland/meta-wayland-touch.h \
wayland/meta-wayland-surface.c \ wayland/meta-wayland-surface.c \
wayland/meta-wayland-surface.h \ wayland/meta-wayland-surface.h \
wayland/meta-wayland-types.h \ wayland/meta-wayland-types.h \
@@ -259,9 +232,7 @@ libmutter_la_SOURCES += \
wayland/meta-wayland-outputs.c \ wayland/meta-wayland-outputs.c \
wayland/meta-wayland-outputs.h \ wayland/meta-wayland-outputs.h \
wayland/window-wayland.c \ wayland/window-wayland.c \
wayland/window-wayland.h \ wayland/window-wayland.h
$(NULL)
endif
if HAVE_NATIVE_BACKEND if HAVE_NATIVE_BACKEND
libmutter_la_SOURCES += \ libmutter_la_SOURCES += \
@@ -276,18 +247,18 @@ libmutter_la_SOURCES += \
backends/native/meta-launcher.c \ backends/native/meta-launcher.c \
backends/native/meta-launcher.h \ backends/native/meta-launcher.h \
backends/native/dbus-utils.c \ backends/native/dbus-utils.c \
backends/native/dbus-utils.h \ backends/native/dbus-utils.h
$(NULL)
endif endif
nodist_libmutter_la_SOURCES = $(mutter_built_sources) nodist_libmutter_la_SOURCES = \
$(mutter_built_sources)
libmutter_la_LDFLAGS = -no-undefined libmutter_la_LDFLAGS = -no-undefined
libmutter_la_LIBADD = $(MUTTER_LIBS) $(MUTTER_NATIVE_BACKEND_LIBS) libmutter_la_LIBADD = $(MUTTER_LIBS) $(MUTTER_NATIVE_BACKEND_LIBS)
# Headers installed for plugins; introspected information will # Headers installed for plugins; introspected information will
# be extracted into Mutter-<version>.gir # be extracted into Mutter-<version>.gir
libmutterinclude_headers = \ libmutterinclude_base_headers = \
meta/barrier.h \ meta/barrier.h \
meta/boxes.h \ meta/boxes.h \
meta/common.h \ meta/common.h \
@@ -295,14 +266,13 @@ libmutterinclude_headers = \
meta/compositor.h \ meta/compositor.h \
meta/display.h \ meta/display.h \
meta/errors.h \ meta/errors.h \
meta/gradient.h \
meta/group.h \ meta/group.h \
meta/keybindings.h \ meta/keybindings.h \
meta/main.h \ meta/main.h \
meta/meta-backend.h \
meta/meta-background.h \
meta/meta-background-actor.h \ meta/meta-background-actor.h \
meta/meta-background-image.h \
meta/meta-background-group.h \ meta/meta-background-group.h \
meta/meta-background.h \
meta/meta-cursor-tracker.h \ meta/meta-cursor-tracker.h \
meta/meta-idle-monitor.h \ meta/meta-idle-monitor.h \
meta/meta-plugin.h \ meta/meta-plugin.h \
@@ -315,15 +285,7 @@ libmutterinclude_headers = \
meta/types.h \ meta/types.h \
meta/util.h \ meta/util.h \
meta/window.h \ meta/window.h \
meta/workspace.h \ meta/workspace.h
$(NULL)
libmutterinclude_built_headers = \
meta/meta-version.h
libmutterinclude_base_headers = \
$(libmutterinclude_headers) \
$(libmutterinclude_built_headers)
# Excluded from scanning for introspection but installed # Excluded from scanning for introspection but installed
# atomnames.h: macros cause problems for scanning process # atomnames.h: macros cause problems for scanning process
@@ -333,24 +295,14 @@ libmutterinclude_extra_headers = \
libmutterincludedir = $(includedir)/mutter/meta libmutterincludedir = $(includedir)/mutter/meta
libmutterinclude_HEADERS = \ libmutterinclude_HEADERS = \
$(libmutterinclude_headers) \ $(libmutterinclude_base_headers) \
$(libmutterinclude_extra_headers) $(libmutterinclude_extra_headers)
nodist_libmutterinclude_HEADERS = \
$(libmutterinclude_built_headers)
bin_PROGRAMS=mutter bin_PROGRAMS=mutter
noinst_PROGRAMS=
mutter_SOURCES = core/mutter.c mutter_SOURCES = core/mutter.c
mutter_LDADD = $(MUTTER_LIBS) libmutter.la 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)
include Makefile-tests.am
if HAVE_INTROSPECTION if HAVE_INTROSPECTION
include $(INTROSPECTION_MAKEFILE) include $(INTROSPECTION_MAKEFILE)
@@ -374,7 +326,7 @@ INTROSPECTION_GIRS = Meta-$(api_version).gir
Meta-$(api_version).gir: libmutter.la 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@_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@_EXPORT_PACKAGES = libmutter
@META_GIR@_CFLAGS = $(AM_CPPFLAGS) @META_GIR@_CFLAGS = $(INCLUDES)
@META_GIR@_LIBS = libmutter.la @META_GIR@_LIBS = libmutter.la
@META_GIR@_FILES = \ @META_GIR@_FILES = \
mutter-enum-types.h \ mutter-enum-types.h \
@@ -384,33 +336,71 @@ Meta-$(api_version).gir: libmutter.la
endif endif
testboxes_SOURCES = core/testboxes.c
testgradient_SOURCES = ui/testgradient.c
testasyncgetprop_SOURCES = x11/testasyncgetprop.c
noinst_PROGRAMS=testboxes testgradient testasyncgetprop
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 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 = \ CLEANFILES = \
mutter.desktop \
mutter-wm.desktop \
org.gnome.mutter.gschema.xml \
org.gnome.mutter.wayland.gschema.xml \
$(xml_DATA) \
$(mutter_built_sources) \ $(mutter_built_sources) \
$(typelib_DATA) \ $(typelib_DATA) \
$(gir_DATA) $(gir_DATA)
DISTCLEANFILES = \
$(libmutterinclude_built_headers)
pkgconfigdir = $(libdir)/pkgconfig pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libmutter.pc pkgconfig_DATA = libmutter.pc
EXTRA_DIST += \ EXTRA_DIST=$(desktopfiles_files) \
$(wayland_protocols) \ $(wmproperties_files) \
libmutter.pc.in \ $(IMAGES) \
mutter-enum-types.h.in \ $(desktopfiles_in_files) \
mutter-enum-types.c.in \ $(wmproperties_in_files) \
org.freedesktop.login1.xml \ $(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 \
org.freedesktop.login1.xml \
org.gnome.Mutter.DisplayConfig.xml \ org.gnome.Mutter.DisplayConfig.xml \
org.gnome.Mutter.IdleMonitor.xml \ org.gnome.Mutter.IdleMonitor.xml
$(NULL)
BUILT_SOURCES = \
$(mutter_built_sources) \
$(libmutterinclude_built_headers)
BUILT_SOURCES = $(mutter_built_sources)
MUTTER_STAMP_FILES = stamp-mutter-enum-types.h MUTTER_STAMP_FILES = stamp-mutter-enum-types.h
CLEANFILES += $(MUTTER_STAMP_FILES) CLEANFILES += $(MUTTER_STAMP_FILES)

View File

@@ -189,5 +189,7 @@ struct MonitorInfo
}; };
MonitorInfo *decode_edid (const uchar *data); MonitorInfo *decode_edid (const uchar *data);
char *make_display_name (const MonitorInfo *info);
char *make_display_size_string (int width_mm, int height_mm);
#endif #endif

View File

@@ -28,15 +28,7 @@
#include <glib-object.h> #include <glib-object.h>
#include <xkbcommon/xkbcommon.h> #include "meta-backend.h"
#include <meta/meta-backend.h>
#include <meta/meta-idle-monitor.h>
#include "meta-cursor-renderer.h"
#include "meta-monitor-manager.h"
#define DEFAULT_XKB_RULES_FILE "evdev"
#define DEFAULT_XKB_MODEL "pc105+inet"
#define META_TYPE_BACKEND (meta_backend_get_type ()) #define META_TYPE_BACKEND (meta_backend_get_type ())
#define META_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BACKEND, MetaBackend)) #define META_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BACKEND, MetaBackend))
@@ -74,37 +66,6 @@ struct _MetaBackendClass
void (* warp_pointer) (MetaBackend *backend, void (* warp_pointer) (MetaBackend *backend,
int x, int x,
int y); int y);
void (* set_keymap) (MetaBackend *backend,
const char *layouts,
const char *variants,
const char *options);
struct xkb_keymap * (* get_keymap) (MetaBackend *backend);
void (* lock_layout_group) (MetaBackend *backend,
guint idx);
void (* update_screen_size) (MetaBackend *backend, int width, int height);
void (* select_stage_events) (MetaBackend *backend);
}; };
MetaIdleMonitor * meta_backend_get_idle_monitor (MetaBackend *backend,
int device_id);
MetaMonitorManager * meta_backend_get_monitor_manager (MetaBackend *backend);
MetaCursorRenderer * meta_backend_get_cursor_renderer (MetaBackend *backend);
gboolean meta_backend_grab_device (MetaBackend *backend,
int device_id,
uint32_t timestamp);
gboolean meta_backend_ungrab_device (MetaBackend *backend,
int device_id,
uint32_t timestamp);
void meta_backend_warp_pointer (MetaBackend *backend,
int x,
int y);
struct xkb_keymap * meta_backend_get_keymap (MetaBackend *backend);
#endif /* META_BACKEND_PRIVATE_H */ #endif /* META_BACKEND_PRIVATE_H */

View File

@@ -24,11 +24,12 @@
#include "config.h" #include "config.h"
#include <meta/meta-backend.h> #include "meta-backend.h"
#include "meta-backend-private.h" #include "meta-backend-private.h"
#include <clutter/clutter.h>
#include "backends/x11/meta-backend-x11.h" #include "backends/x11/meta-backend-x11.h"
#include "meta-stage.h"
#ifdef HAVE_NATIVE_BACKEND #ifdef HAVE_NATIVE_BACKEND
#include "backends/native/meta-backend-native.h" #include "backends/native/meta-backend-native.h"
@@ -36,13 +37,6 @@
static MetaBackend *_backend; static MetaBackend *_backend;
/**
* meta_get_backend:
*
* Accessor for the singleton MetaBackend.
*
* Returns: (transfer none): The only #MetaBackend there is.
*/
MetaBackend * MetaBackend *
meta_get_backend (void) meta_get_backend (void)
{ {
@@ -53,8 +47,6 @@ struct _MetaBackendPrivate
{ {
MetaMonitorManager *monitor_manager; MetaMonitorManager *monitor_manager;
MetaCursorRenderer *cursor_renderer; MetaCursorRenderer *cursor_renderer;
ClutterActor *stage;
}; };
typedef struct _MetaBackendPrivate MetaBackendPrivate; typedef struct _MetaBackendPrivate MetaBackendPrivate;
@@ -78,121 +70,13 @@ meta_backend_finalize (GObject *object)
G_OBJECT_CLASS (meta_backend_parent_class)->finalize (object); G_OBJECT_CLASS (meta_backend_parent_class)->finalize (object);
} }
static void
meta_backend_sync_screen_size (MetaBackend *backend)
{
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
int width, height;
meta_monitor_manager_get_screen_size (priv->monitor_manager, &width, &height);
META_BACKEND_GET_CLASS (backend)->update_screen_size (backend, width, height);
}
static void
on_monitors_changed (MetaMonitorManager *monitors,
gpointer user_data)
{
MetaBackend *backend = META_BACKEND (user_data);
meta_backend_sync_screen_size (backend);
}
static MetaIdleMonitor *
meta_backend_create_idle_monitor (MetaBackend *backend,
int device_id)
{
return META_BACKEND_GET_CLASS (backend)->create_idle_monitor (backend, device_id);
}
static void
create_device_monitor (MetaBackend *backend,
int device_id)
{
g_assert (backend->device_monitors[device_id] == NULL);
backend->device_monitors[device_id] = meta_backend_create_idle_monitor (backend, device_id);
backend->device_id_max = MAX (backend->device_id_max, device_id);
}
static void
destroy_device_monitor (MetaBackend *backend,
int device_id)
{
g_clear_object (&backend->device_monitors[device_id]);
if (device_id == backend->device_id_max)
{
/* Reset the max device ID */
int i, new_max = 0;
for (i = 0; i < backend->device_id_max; i++)
if (backend->device_monitors[i] != NULL)
new_max = i;
backend->device_id_max = new_max;
}
}
static void
on_device_added (ClutterDeviceManager *device_manager,
ClutterInputDevice *device,
gpointer user_data)
{
MetaBackend *backend = META_BACKEND (user_data);
int device_id = clutter_input_device_get_device_id (device);
create_device_monitor (backend, device_id);
}
static void
on_device_removed (ClutterDeviceManager *device_manager,
ClutterInputDevice *device,
gpointer user_data)
{
MetaBackend *backend = META_BACKEND (user_data);
int device_id = clutter_input_device_get_device_id (device);
destroy_device_monitor (backend, device_id);
}
static void static void
meta_backend_real_post_init (MetaBackend *backend) meta_backend_real_post_init (MetaBackend *backend)
{ {
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
priv->stage = meta_stage_new ();
clutter_actor_realize (priv->stage);
META_BACKEND_GET_CLASS (backend)->select_stage_events (backend);
priv->monitor_manager = META_BACKEND_GET_CLASS (backend)->create_monitor_manager (backend); priv->monitor_manager = META_BACKEND_GET_CLASS (backend)->create_monitor_manager (backend);
g_signal_connect (priv->monitor_manager, "monitors-changed",
G_CALLBACK (on_monitors_changed), backend);
meta_backend_sync_screen_size (backend);
priv->cursor_renderer = META_BACKEND_GET_CLASS (backend)->create_cursor_renderer (backend); priv->cursor_renderer = META_BACKEND_GET_CLASS (backend)->create_cursor_renderer (backend);
{
ClutterDeviceManager *manager;
GSList *devices, *l;
/* Create the core device monitor. */
create_device_monitor (backend, 0);
manager = clutter_device_manager_get_default ();
g_signal_connect_object (manager, "device-added",
G_CALLBACK (on_device_added), backend, 0);
g_signal_connect_object (manager, "device-removed",
G_CALLBACK (on_device_removed), backend, 0);
devices = clutter_device_manager_list_devices (manager);
for (l = devices; l != NULL; l = l->next)
{
ClutterInputDevice *device = l->data;
on_device_added (manager, device, backend);
}
g_slist_free (devices);
}
} }
static MetaCursorRenderer * static MetaCursorRenderer *
@@ -220,16 +104,9 @@ meta_backend_real_ungrab_device (MetaBackend *backend,
} }
static void static void
meta_backend_real_update_screen_size (MetaBackend *backend, meta_backend_real_warp_pointer (MetaBackend *backend,
int width, int height) int x,
{ int y)
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
clutter_actor_set_size (priv->stage, width, height);
}
static void
meta_backend_real_select_stage_events (MetaBackend *backend)
{ {
/* Do nothing */ /* Do nothing */
} }
@@ -245,21 +122,7 @@ meta_backend_class_init (MetaBackendClass *klass)
klass->create_cursor_renderer = meta_backend_real_create_cursor_renderer; klass->create_cursor_renderer = meta_backend_real_create_cursor_renderer;
klass->grab_device = meta_backend_real_grab_device; klass->grab_device = meta_backend_real_grab_device;
klass->ungrab_device = meta_backend_real_ungrab_device; klass->ungrab_device = meta_backend_real_ungrab_device;
klass->update_screen_size = meta_backend_real_update_screen_size; klass->warp_pointer = meta_backend_real_warp_pointer;
klass->select_stage_events = meta_backend_real_select_stage_events;
g_signal_new ("keymap-changed",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 0);
g_signal_new ("keymap-layout-group-changed",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 1, G_TYPE_UINT);
} }
static void static void
@@ -268,27 +131,44 @@ meta_backend_init (MetaBackend *backend)
_backend = backend; _backend = backend;
} }
/* FIXME -- destroy device monitors at some point */
G_GNUC_UNUSED static void
destroy_device_monitor (MetaBackend *backend,
int device_id)
{
g_clear_object (&backend->device_monitors[device_id]);
if (device_id == backend->device_id_max)
backend->device_id_max--;
}
static MetaIdleMonitor *
meta_backend_create_idle_monitor (MetaBackend *backend,
int device_id)
{
return META_BACKEND_GET_CLASS (backend)->create_idle_monitor (backend, device_id);
}
static void static void
meta_backend_post_init (MetaBackend *backend) meta_backend_post_init (MetaBackend *backend)
{ {
META_BACKEND_GET_CLASS (backend)->post_init (backend); META_BACKEND_GET_CLASS (backend)->post_init (backend);
} }
/**
* meta_backend_get_idle_monitor: (skip)
*/
MetaIdleMonitor * MetaIdleMonitor *
meta_backend_get_idle_monitor (MetaBackend *backend, meta_backend_get_idle_monitor (MetaBackend *backend,
int device_id) int device_id)
{ {
g_return_val_if_fail (device_id >= 0 && device_id < 256, NULL); g_return_val_if_fail (device_id >= 0 && device_id < 256, NULL);
if (!backend->device_monitors[device_id])
{
backend->device_monitors[device_id] = meta_backend_create_idle_monitor (backend, device_id);
backend->device_id_max = MAX (backend->device_id_max, device_id);
}
return backend->device_monitors[device_id]; return backend->device_monitors[device_id];
} }
/**
* meta_backend_get_monitor_manager: (skip)
*/
MetaMonitorManager * MetaMonitorManager *
meta_backend_get_monitor_manager (MetaBackend *backend) meta_backend_get_monitor_manager (MetaBackend *backend)
{ {
@@ -297,9 +177,6 @@ meta_backend_get_monitor_manager (MetaBackend *backend)
return priv->monitor_manager; return priv->monitor_manager;
} }
/**
* meta_backend_get_cursor_renderer: (skip)
*/
MetaCursorRenderer * MetaCursorRenderer *
meta_backend_get_cursor_renderer (MetaBackend *backend) meta_backend_get_cursor_renderer (MetaBackend *backend)
{ {
@@ -308,9 +185,6 @@ meta_backend_get_cursor_renderer (MetaBackend *backend)
return priv->cursor_renderer; return priv->cursor_renderer;
} }
/**
* meta_backend_grab_device: (skip)
*/
gboolean gboolean
meta_backend_grab_device (MetaBackend *backend, meta_backend_grab_device (MetaBackend *backend,
int device_id, int device_id,
@@ -319,9 +193,6 @@ meta_backend_grab_device (MetaBackend *backend,
return META_BACKEND_GET_CLASS (backend)->grab_device (backend, device_id, timestamp); return META_BACKEND_GET_CLASS (backend)->grab_device (backend, device_id, timestamp);
} }
/**
* meta_backend_ungrab_device: (skip)
*/
gboolean gboolean
meta_backend_ungrab_device (MetaBackend *backend, meta_backend_ungrab_device (MetaBackend *backend,
int device_id, int device_id,
@@ -330,9 +201,6 @@ meta_backend_ungrab_device (MetaBackend *backend,
return META_BACKEND_GET_CLASS (backend)->ungrab_device (backend, device_id, timestamp); return META_BACKEND_GET_CLASS (backend)->ungrab_device (backend, device_id, timestamp);
} }
/**
* meta_backend_warp_pointer: (skip)
*/
void void
meta_backend_warp_pointer (MetaBackend *backend, meta_backend_warp_pointer (MetaBackend *backend,
int x, int x,
@@ -341,47 +209,6 @@ meta_backend_warp_pointer (MetaBackend *backend,
META_BACKEND_GET_CLASS (backend)->warp_pointer (backend, x, y); META_BACKEND_GET_CLASS (backend)->warp_pointer (backend, x, y);
} }
void
meta_backend_set_keymap (MetaBackend *backend,
const char *layouts,
const char *variants,
const char *options)
{
META_BACKEND_GET_CLASS (backend)->set_keymap (backend, layouts, variants, options);
}
/**
* meta_backend_get_keymap: (skip)
*/
struct xkb_keymap *
meta_backend_get_keymap (MetaBackend *backend)
{
return META_BACKEND_GET_CLASS (backend)->get_keymap (backend);
}
void
meta_backend_lock_layout_group (MetaBackend *backend,
guint idx)
{
META_BACKEND_GET_CLASS (backend)->lock_layout_group (backend, idx);
}
/**
* meta_backend_get_stage:
* @backend: A #MetaBackend
*
* Gets the global #ClutterStage that's managed by this backend.
*
* Returns: (transfer none): the #ClutterStage
*/
ClutterActor *
meta_backend_get_stage (MetaBackend *backend)
{
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
return priv->stage;
}
static GType static GType
get_backend_type (void) get_backend_type (void)
{ {
@@ -454,13 +281,9 @@ static GSourceFuncs event_funcs = {
event_dispatch event_dispatch
}; };
/**
* meta_clutter_init: (skip)
*/
void void
meta_clutter_init (void) meta_clutter_init (void)
{ {
ClutterSettings *clutter_settings;
GSource *source; GSource *source;
meta_create_backend (); meta_create_backend ();
@@ -468,13 +291,6 @@ meta_clutter_init (void)
if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS) if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
g_error ("Unable to initialize Clutter.\n"); g_error ("Unable to initialize Clutter.\n");
/*
* XXX: We cannot handle high dpi scaling yet, so fix the scale to 1
* for now.
*/
clutter_settings = clutter_settings_get_default ();
g_object_set (clutter_settings, "window-scaling-factor", 1, NULL);
source = g_source_new (&event_funcs, sizeof (GSource)); source = g_source_new (&event_funcs, sizeof (GSource));
g_source_attach (source, NULL); g_source_attach (source, NULL);
g_source_unref (source); g_source_unref (source);

View File

@@ -27,7 +27,9 @@
#include <glib-object.h> #include <glib-object.h>
#include <clutter/clutter.h> #include <meta/meta-idle-monitor.h>
#include "meta-monitor-manager.h"
#include "meta-cursor-renderer.h"
typedef struct _MetaBackend MetaBackend; typedef struct _MetaBackend MetaBackend;
typedef struct _MetaBackendClass MetaBackendClass; typedef struct _MetaBackendClass MetaBackendClass;
@@ -36,15 +38,21 @@ GType meta_backend_get_type (void);
MetaBackend * meta_get_backend (void); MetaBackend * meta_get_backend (void);
void meta_backend_set_keymap (MetaBackend *backend, MetaIdleMonitor * meta_backend_get_idle_monitor (MetaBackend *backend,
const char *layouts, int device_id);
const char *variants, MetaMonitorManager * meta_backend_get_monitor_manager (MetaBackend *backend);
const char *options); MetaCursorRenderer * meta_backend_get_cursor_renderer (MetaBackend *backend);
void meta_backend_lock_layout_group (MetaBackend *backend, gboolean meta_backend_grab_device (MetaBackend *backend,
guint idx); int device_id,
uint32_t timestamp);
gboolean meta_backend_ungrab_device (MetaBackend *backend,
int device_id,
uint32_t timestamp);
ClutterActor *meta_backend_get_stage (MetaBackend *backend); void meta_backend_warp_pointer (MetaBackend *backend,
int x,
int y);
void meta_clutter_init (void); void meta_clutter_init (void);

View File

@@ -29,11 +29,8 @@
typedef struct { typedef struct {
CoglTexture2D *texture; CoglTexture2D *texture;
int hot_x, hot_y;
#ifdef HAVE_NATIVE_BACKEND
struct gbm_bo *bo; struct gbm_bo *bo;
#endif int hot_x, hot_y;
} MetaCursorImage; } MetaCursorImage;
struct _MetaCursorReference { struct _MetaCursorReference {
@@ -47,10 +44,8 @@ CoglTexture *meta_cursor_reference_get_cogl_texture (MetaCursorReference *cursor
int *hot_x, int *hot_x,
int *hot_y); int *hot_y);
#ifdef HAVE_NATIVE_BACKEND
struct gbm_bo *meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor, struct gbm_bo *meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
int *hot_x, int *hot_x,
int *hot_y); int *hot_y);
#endif
#endif /* META_CURSOR_PRIVATE_H */ #endif /* META_CURSOR_PRIVATE_H */

View File

@@ -27,14 +27,14 @@
#include "meta-cursor-renderer.h" #include "meta-cursor-renderer.h"
#include "meta-cursor-private.h" #include "meta-cursor-private.h"
#include <meta/meta-backend.h>
#include <meta/util.h>
#include <cogl/cogl.h> #include <cogl/cogl.h>
#include <cogl/cogl-wayland-server.h>
#include <clutter/clutter.h> #include <clutter/clutter.h>
#include "meta-stage.h" #include "meta-stage.h"
#include "wayland/meta-wayland-private.h"
struct _MetaCursorRendererPrivate struct _MetaCursorRendererPrivate
{ {
int current_x, current_y; int current_x, current_y;
@@ -51,20 +51,17 @@ static void
queue_redraw (MetaCursorRenderer *renderer) queue_redraw (MetaCursorRenderer *renderer)
{ {
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
MetaBackend *backend = meta_get_backend (); MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
ClutterActor *stage = meta_backend_get_stage (backend); ClutterActor *stage = compositor->stage;
CoglTexture *texture;
/* During early initialization, we can have no stage */ /* During early initialization, we can have no stage */
if (!stage) if (!stage)
return; return;
if (priv->displayed_cursor && !priv->handled_by_backend) if (priv->handled_by_backend)
texture = meta_cursor_reference_get_cogl_texture (priv->displayed_cursor, NULL, NULL); meta_stage_set_cursor (META_STAGE (stage), NULL, &priv->current_rect);
else else
texture = NULL; meta_stage_set_cursor (META_STAGE (stage), priv->displayed_cursor, &priv->current_rect);
meta_stage_set_cursor (META_STAGE (stage), texture, &priv->current_rect);
} }
static gboolean static gboolean

View File

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

View File

@@ -27,29 +27,32 @@
* pointer abstraction" * pointer abstraction"
*/ */
#include "config.h" #include <config.h>
#include "meta-cursor-tracker-private.h"
#include <string.h> #include <string.h>
#include <meta/main.h> #include <meta/main.h>
#include <meta/util.h> #include <meta/util.h>
#include <meta/errors.h> #include <meta/errors.h>
#include <cogl/cogl.h> #include <cogl/cogl.h>
#include <cogl/cogl-wayland-server.h>
#include <clutter/clutter.h> #include <clutter/clutter.h>
#include <gdk/gdk.h> #include <gdk/gdk.h>
#include <gdk/gdkx.h> #include <gdk/gdkx.h>
#include <X11/extensions/Xfixes.h>
#include "meta-backend-private.h" #include "meta-backend.h"
#include "meta-cursor-private.h" #include "meta-cursor-private.h"
#include "meta-cursor-tracker-private.h"
#include "screen-private.h"
#include "wayland/meta-wayland-private.h"
G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT); G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT);
enum { enum {
CURSOR_CHANGED, CURSOR_CHANGED,
LAST_SIGNAL LAST_SIGNAL
}; };
static guint signals[LAST_SIGNAL]; static guint signals[LAST_SIGNAL];
@@ -57,12 +60,10 @@ static guint signals[LAST_SIGNAL];
static MetaCursorReference * static MetaCursorReference *
get_displayed_cursor (MetaCursorTracker *tracker) get_displayed_cursor (MetaCursorTracker *tracker)
{ {
MetaDisplay *display = meta_get_display ();
if (!tracker->is_showing) if (!tracker->is_showing)
return NULL; return NULL;
if (meta_display_windows_are_interactable (display)) if (tracker->screen->display->grab_op == META_GRAB_OP_NONE)
{ {
if (tracker->has_window_cursor) if (tracker->has_window_cursor)
return tracker->window_cursor; return tracker->window_cursor;
@@ -96,9 +97,6 @@ sync_cursor (MetaCursorTracker *tracker)
static void static void
meta_cursor_tracker_init (MetaCursorTracker *self) meta_cursor_tracker_init (MetaCursorTracker *self)
{ {
MetaBackend *backend = meta_get_backend ();
self->renderer = meta_backend_get_cursor_renderer (backend);
self->is_showing = TRUE; self->is_showing = TRUE;
} }
@@ -131,9 +129,47 @@ meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass)
} }
static MetaCursorTracker * 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; static MetaCursorTracker *_cursor_tracker;
@@ -150,7 +186,7 @@ MetaCursorTracker *
meta_cursor_tracker_get_for_screen (MetaScreen *screen) meta_cursor_tracker_get_for_screen (MetaScreen *screen)
{ {
if (!_cursor_tracker) if (!_cursor_tracker)
_cursor_tracker = meta_cursor_tracker_new (); _cursor_tracker = meta_cursor_tracker_new (screen);
return _cursor_tracker; return _cursor_tracker;
} }
@@ -171,13 +207,12 @@ gboolean
meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker, meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
XEvent *xevent) XEvent *xevent)
{ {
MetaDisplay *display = meta_get_display ();
XFixesCursorNotifyEvent *notify_event; XFixesCursorNotifyEvent *notify_event;
if (meta_is_wayland_compositor ()) if (meta_is_wayland_compositor ())
return FALSE; return FALSE;
if (xevent->xany.type != display->xfixes_event_base + XFixesCursorNotify) if (xevent->xany.type != tracker->screen->display->xfixes_event_base + XFixesCursorNotify)
return FALSE; return FALSE;
notify_event = (XFixesCursorNotifyEvent *)xevent; notify_event = (XFixesCursorNotifyEvent *)xevent;
@@ -208,7 +243,6 @@ meta_cursor_reference_take_texture (CoglTexture2D *texture,
static void static void
ensure_xfixes_cursor (MetaCursorTracker *tracker) ensure_xfixes_cursor (MetaCursorTracker *tracker)
{ {
MetaDisplay *display = meta_get_display ();
XFixesCursorImage *cursor_image; XFixesCursorImage *cursor_image;
CoglTexture2D *sprite; CoglTexture2D *sprite;
guint8 *cursor_data; guint8 *cursor_data;
@@ -218,7 +252,7 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
if (tracker->xfixes_cursor) if (tracker->xfixes_cursor)
return; return;
cursor_image = XFixesGetCursorImage (display->xdisplay); cursor_image = XFixesGetCursorImage (tracker->screen->display->xdisplay);
if (!cursor_image) if (!cursor_image)
return; return;

View File

@@ -27,7 +27,7 @@
#include "display-private.h" #include "display-private.h"
#include "screen-private.h" #include "screen-private.h"
#include "meta-backend-private.h" #include "meta-backend.h"
#ifdef HAVE_NATIVE_BACKEND #ifdef HAVE_NATIVE_BACKEND
#include "backends/native/meta-cursor-renderer-native.h" #include "backends/native/meta-cursor-renderer-native.h"
@@ -39,9 +39,7 @@
#include <X11/extensions/Xfixes.h> #include <X11/extensions/Xfixes.h>
#include <X11/Xcursor/Xcursor.h> #include <X11/Xcursor/Xcursor.h>
#ifdef HAVE_WAYLAND
#include <cogl/cogl-wayland-server.h> #include <cogl/cogl-wayland-server.h>
#endif
MetaCursorReference * MetaCursorReference *
meta_cursor_reference_ref (MetaCursorReference *self) meta_cursor_reference_ref (MetaCursorReference *self)
@@ -56,11 +54,8 @@ static void
meta_cursor_image_free (MetaCursorImage *image) meta_cursor_image_free (MetaCursorImage *image)
{ {
cogl_object_unref (image->texture); cogl_object_unref (image->texture);
#ifdef HAVE_NATIVE_BACKEND
if (image->bo) if (image->bo)
gbm_bo_destroy (image->bo); gbm_bo_destroy (image->bo);
#endif
} }
static void static void
@@ -142,90 +137,70 @@ load_cursor_on_client (MetaCursor cursor)
meta_prefs_get_cursor_size ()); meta_prefs_get_cursor_size ());
} }
#ifdef HAVE_NATIVE_BACKEND
static void
get_hardware_cursor_size (uint64_t *cursor_width, uint64_t *cursor_height)
{
MetaBackend *meta_backend = meta_get_backend ();
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend);
if (META_IS_CURSOR_RENDERER_NATIVE (renderer))
{
meta_cursor_renderer_native_get_cursor_size (META_CURSOR_RENDERER_NATIVE (renderer), cursor_width, cursor_height);
return;
}
g_assert_not_reached ();
}
#endif
#ifdef HAVE_NATIVE_BACKEND
static void static void
meta_cursor_image_load_gbm_buffer (struct gbm_device *gbm, meta_cursor_image_load_gbm_buffer (struct gbm_device *gbm,
MetaCursorImage *image, MetaCursorImage *image,
uint8_t *pixels, uint8_t *pixels,
uint width, int width,
uint height, int height,
int rowstride, int rowstride,
uint32_t gbm_format) uint32_t gbm_format)
{ {
uint64_t cursor_width, cursor_height; if (width > 64 || height > 64)
get_hardware_cursor_size (&cursor_width, &cursor_height);
if (width > cursor_width || height > cursor_height)
{ {
meta_warning ("Invalid theme cursor size (must be at most %ux%u)\n", meta_warning ("Invalid theme cursor size (must be at most 64x64)\n");
(unsigned int)cursor_width, (unsigned int)cursor_height);
return; return;
} }
if (gbm_device_is_format_supported (gbm, gbm_format, if (gbm_device_is_format_supported (gbm, gbm_format,
GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE)) GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE))
{ {
uint8_t buf[4 * cursor_width * cursor_height]; uint8_t buf[4 * 64 * 64];
uint i; int i;
image->bo = gbm_bo_create (gbm, cursor_width, cursor_height, image->bo = gbm_bo_create (gbm, 64, 64,
gbm_format, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE); gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
memset (buf, 0, sizeof(buf)); memset (buf, 0, sizeof(buf));
for (i = 0; i < height; i++) for (i = 0; i < height; i++)
memcpy (buf + i * 4 * cursor_width, pixels + i * rowstride, width * 4); memcpy (buf + i * 4 * 64, pixels + i * rowstride, width * 4);
gbm_bo_write (image->bo, buf, cursor_width * cursor_height * 4); gbm_bo_write (image->bo, buf, 64 * 64 * 4);
} }
else else
meta_warning ("HW cursor for format %d not supported\n", gbm_format); meta_warning ("HW cursor for format %d not supported\n", gbm_format);
} }
#endif
#ifdef HAVE_NATIVE_BACKEND
static struct gbm_device * static struct gbm_device *
get_gbm_device (void) get_gbm_device (void)
{ {
#ifdef HAVE_NATIVE_BACKEND
MetaBackend *meta_backend = meta_get_backend (); MetaBackend *meta_backend = meta_get_backend ();
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend); MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend);
if (META_IS_CURSOR_RENDERER_NATIVE (renderer)) if (META_IS_CURSOR_RENDERER_NATIVE (renderer))
return meta_cursor_renderer_native_get_gbm_device (META_CURSOR_RENDERER_NATIVE (renderer)); return meta_cursor_renderer_native_get_gbm_device (META_CURSOR_RENDERER_NATIVE (renderer));
else
return NULL;
}
#endif #endif
return NULL;
}
static void static void
meta_cursor_image_load_from_xcursor_image (MetaCursorImage *image, meta_cursor_image_load_from_xcursor_image (MetaCursorImage *image,
XcursorImage *xc_image) XcursorImage *xc_image)
{ {
uint width, height, rowstride; int width, height, rowstride;
CoglPixelFormat cogl_format; CoglPixelFormat cogl_format;
uint32_t gbm_format;
ClutterBackend *clutter_backend; ClutterBackend *clutter_backend;
CoglContext *cogl_context; CoglContext *cogl_context;
struct gbm_device *gbm;
width = xc_image->width; width = xc_image->width;
height = xc_image->height; height = xc_image->height;
rowstride = width * 4; rowstride = width * 4;
gbm_format = GBM_FORMAT_ARGB8888;
#if G_BYTE_ORDER == G_LITTLE_ENDIAN #if G_BYTE_ORDER == G_LITTLE_ENDIAN
cogl_format = COGL_PIXEL_FORMAT_BGRA_8888; cogl_format = COGL_PIXEL_FORMAT_BGRA_8888;
#else #else
@@ -244,15 +219,13 @@ meta_cursor_image_load_from_xcursor_image (MetaCursorImage *image,
(uint8_t *) xc_image->pixels, (uint8_t *) xc_image->pixels,
NULL); NULL);
#ifdef HAVE_NATIVE_BACKEND gbm = get_gbm_device ();
struct gbm_device *gbm = get_gbm_device ();
if (gbm) if (gbm)
meta_cursor_image_load_gbm_buffer (gbm, meta_cursor_image_load_gbm_buffer (gbm,
image, image,
(uint8_t *) xc_image->pixels, (uint8_t *) xc_image->pixels,
width, height, rowstride, width, height, rowstride,
GBM_FORMAT_ARGB8888); gbm_format);
#endif
} }
MetaCursorReference * MetaCursorReference *
@@ -274,15 +247,19 @@ meta_cursor_reference_from_theme (MetaCursor cursor)
return self; return self;
} }
#ifdef HAVE_WAYLAND
static void static void
meta_cursor_image_load_from_buffer (MetaCursorImage *image, meta_cursor_image_load_from_buffer (MetaCursorImage *image,
struct wl_resource *buffer, struct wl_resource *buffer,
int hot_x, int hot_x,
int hot_y) int hot_y)
{ {
struct gbm_device *gbm = get_gbm_device ();
ClutterBackend *backend; ClutterBackend *backend;
CoglContext *cogl_context; CoglContext *cogl_context;
struct wl_shm_buffer *shm_buffer;
uint32_t gbm_format;
int width, height;
image->hot_x = hot_x; image->hot_x = hot_x;
image->hot_y = hot_y; image->hot_y = hot_y;
@@ -292,19 +269,13 @@ meta_cursor_image_load_from_buffer (MetaCursorImage *image,
image->texture = cogl_wayland_texture_2d_new_from_buffer (cogl_context, buffer, NULL); image->texture = cogl_wayland_texture_2d_new_from_buffer (cogl_context, buffer, NULL);
#ifdef HAVE_NATIVE_BACKEND width = cogl_texture_get_width (COGL_TEXTURE (image->texture));
struct gbm_device *gbm = get_gbm_device (); height = cogl_texture_get_height (COGL_TEXTURE (image->texture));
if (gbm)
shm_buffer = wl_shm_buffer_get (buffer);
if (shm_buffer)
{ {
uint32_t gbm_format; if (gbm)
uint64_t cursor_width, cursor_height;
uint width, height;
width = cogl_texture_get_width (COGL_TEXTURE (image->texture));
height = cogl_texture_get_height (COGL_TEXTURE (image->texture));
struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (buffer);
if (shm_buffer)
{ {
int rowstride = wl_shm_buffer_get_stride (shm_buffer); int rowstride = wl_shm_buffer_get_stride (shm_buffer);
@@ -336,28 +307,29 @@ meta_cursor_image_load_from_buffer (MetaCursorImage *image,
width, height, rowstride, width, height, rowstride,
gbm_format); gbm_format);
} }
else }
else
{
/* HW cursors must be 64x64, but 64x64 is huge, and no cursor theme actually uses
that, so themed cursors must be padded with transparent pixels to fill the
overlay. This is trivial if we have CPU access to the data, but it's not
possible if the buffer is in GPU memory (and possibly tiled too), so if we
don't get the right size, we fallback to GL.
*/
if (width != 64 || height != 64)
{ {
/* HW cursors have a predefined size (at least 64x64), which usually is bigger than cursor theme meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n");
size, so themed cursors must be padded with transparent pixels to fill the return;
overlay. This is trivial if we have CPU access to the data, but it's not }
possible if the buffer is in GPU memory (and possibly tiled too), so if we
don't get the right size, we fallback to GL.
*/
get_hardware_cursor_size (&cursor_width, &cursor_height);
if (width != cursor_width || height != cursor_height) if (gbm)
{ {
meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n"); image->bo = gbm_bo_import (gbm, GBM_BO_IMPORT_WL_BUFFER,
return; buffer, GBM_BO_USE_CURSOR_64X64);
}
image->bo = gbm_bo_import (gbm, GBM_BO_IMPORT_WL_BUFFER, buffer, GBM_BO_USE_CURSOR);
if (!image->bo) if (!image->bo)
meta_warning ("Importing HW cursor from wl_buffer failed\n"); meta_warning ("Importing HW cursor from wl_buffer failed\n");
} }
} }
#endif
} }
MetaCursorReference * MetaCursorReference *
@@ -373,7 +345,6 @@ meta_cursor_reference_from_buffer (struct wl_resource *buffer,
return self; return self;
} }
#endif
CoglTexture * CoglTexture *
meta_cursor_reference_get_cogl_texture (MetaCursorReference *cursor, meta_cursor_reference_get_cogl_texture (MetaCursorReference *cursor,
@@ -387,7 +358,6 @@ meta_cursor_reference_get_cogl_texture (MetaCursorReference *cursor,
return COGL_TEXTURE (cursor->image.texture); return COGL_TEXTURE (cursor->image.texture);
} }
#ifdef HAVE_NATIVE_BACKEND
struct gbm_bo * struct gbm_bo *
meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor, meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
int *hot_x, int *hot_x,
@@ -399,7 +369,6 @@ meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
*hot_y = cursor->image.hot_y; *hot_y = cursor->image.hot_y;
return cursor->image.bo; return cursor->image.bo;
} }
#endif
MetaCursor MetaCursor
meta_cursor_reference_get_meta_cursor (MetaCursorReference *cursor) meta_cursor_reference_get_meta_cursor (MetaCursorReference *cursor)

View File

@@ -28,15 +28,13 @@ MetaCursorReference * meta_cursor_reference_ref (MetaCursorReference *cursor);
void meta_cursor_reference_unref (MetaCursorReference *cursor); void meta_cursor_reference_unref (MetaCursorReference *cursor);
#include <meta/common.h> #include <meta/common.h>
#include <wayland-server.h>
MetaCursorReference * meta_cursor_reference_from_theme (MetaCursor cursor); MetaCursorReference * meta_cursor_reference_from_theme (MetaCursor cursor);
#ifdef HAVE_WAYLAND
#include <wayland-server.h>
MetaCursorReference * meta_cursor_reference_from_buffer (struct wl_resource *buffer, MetaCursorReference * meta_cursor_reference_from_buffer (struct wl_resource *buffer,
int hot_x, int hot_x,
int hot_y); int hot_y);
#endif
MetaCursor meta_cursor_reference_get_meta_cursor (MetaCursorReference *cursor); MetaCursor meta_cursor_reference_get_meta_cursor (MetaCursorReference *cursor);

View File

@@ -38,7 +38,7 @@
#include <meta/meta-idle-monitor.h> #include <meta/meta-idle-monitor.h>
#include "meta-idle-monitor-private.h" #include "meta-idle-monitor-private.h"
#include "meta-idle-monitor-dbus.h" #include "meta-idle-monitor-dbus.h"
#include "meta-backend-private.h" #include "meta-backend.h"
G_STATIC_ASSERT(sizeof(unsigned long) == sizeof(gpointer)); G_STATIC_ASSERT(sizeof(unsigned long) == sizeof(gpointer));

View File

@@ -34,7 +34,6 @@
#include "config.h" #include "config.h"
#include "boxes-private.h"
#include "meta-monitor-config.h" #include "meta-monitor-config.h"
#include <string.h> #include <string.h>
@@ -61,14 +60,13 @@ typedef struct {
gboolean enabled; gboolean enabled;
MetaRectangle rect; MetaRectangle rect;
float refresh_rate; float refresh_rate;
MetaMonitorTransform transform; enum wl_output_transform transform;
gboolean is_primary; gboolean is_primary;
gboolean is_presentation; gboolean is_presentation;
} MetaOutputConfig; } MetaOutputConfig;
typedef struct { typedef struct {
guint refcount;
MetaOutputKey *keys; MetaOutputKey *keys;
MetaOutputConfig *outputs; MetaOutputConfig *outputs;
unsigned int n_outputs; unsigned int n_outputs;
@@ -79,6 +77,7 @@ struct _MetaMonitorConfig {
GHashTable *configs; GHashTable *configs;
MetaConfiguration *current; MetaConfiguration *current;
gboolean current_is_stored;
gboolean current_is_for_laptop_lid; gboolean current_is_for_laptop_lid;
MetaConfiguration *previous; MetaConfiguration *previous;
@@ -125,29 +124,11 @@ config_clear (MetaConfiguration *config)
g_free (config->outputs); g_free (config->outputs);
} }
static MetaConfiguration *
config_ref (MetaConfiguration *config)
{
config->refcount++;
return config;
}
static void static void
config_unref (MetaConfiguration *config) config_free (gpointer config)
{ {
if (--config->refcount == 0) config_clear (config);
{ g_slice_free (MetaConfiguration, config);
config_clear (config);
g_slice_free (MetaConfiguration, config);
}
}
static MetaConfiguration *
config_new (void)
{
MetaConfiguration *config = g_slice_new0 (MetaConfiguration);
config->refcount = 1;
return config;
} }
static unsigned long static unsigned long
@@ -239,7 +220,7 @@ meta_monitor_config_init (MetaMonitorConfig *self)
const char *filename; const char *filename;
char *path; char *path;
self->configs = g_hash_table_new_full (config_hash, config_equal, NULL, (GDestroyNotify) config_unref); self->configs = g_hash_table_new_full (config_hash, config_equal, NULL, config_free);
filename = g_getenv ("MUTTER_MONITOR_FILENAME"); filename = g_getenv ("MUTTER_MONITOR_FILENAME");
if (filename == NULL) if (filename == NULL)
@@ -675,20 +656,20 @@ handle_text (GMarkupParseContext *context,
else if (strcmp (parser->output_field, "rotation") == 0) else if (strcmp (parser->output_field, "rotation") == 0)
{ {
if (strncmp (text, "normal", text_len) == 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) 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) 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) else if (strncmp (text, "right", text_len) == 0)
parser->output.transform = META_MONITOR_TRANSFORM_270; parser->output.transform = WL_OUTPUT_TRANSFORM_270;
else else
g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
"Invalid rotation type %.*s", (int)text_len, text); "Invalid rotation type %.*s", (int)text_len, text);
} }
else if (strcmp (parser->output_field, "reflect_x") == 0) else if (strcmp (parser->output_field, "reflect_x") == 0)
parser->output.transform += read_bool (text, text_len, error) ? 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) else if (strcmp (parser->output_field, "reflect_y") == 0)
{ {
/* FIXME (look at the rotation map in monitor.c) */ /* FIXME (look at the rotation map in monitor.c) */
@@ -815,6 +796,27 @@ make_config_key (MetaConfiguration *key,
key->n_outputs = o; key->n_outputs = o;
} }
gboolean
meta_monitor_config_match_current (MetaMonitorConfig *self,
MetaMonitorManager *manager)
{
MetaOutput *outputs;
unsigned n_outputs;
MetaConfiguration key;
gboolean ok;
if (self->current == NULL)
return FALSE;
outputs = meta_monitor_manager_get_outputs (manager, &n_outputs);
make_config_key (&key, outputs, n_outputs, -1);
ok = config_equal (&key, self->current);
config_clear (&key);
return ok;
}
gboolean gboolean
meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager) meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager)
{ {
@@ -849,45 +851,73 @@ meta_monitor_config_get_stored (MetaMonitorConfig *self,
return stored; return stored;
} }
static void
set_current (MetaMonitorConfig *self,
MetaConfiguration *config)
{
g_clear_pointer (&self->previous, (GDestroyNotify) config_unref);
self->previous = self->current;
self->current = config_ref (config);
}
static gboolean static gboolean
apply_configuration (MetaMonitorConfig *self, apply_configuration (MetaMonitorConfig *self,
MetaConfiguration *config, MetaConfiguration *config,
MetaMonitorManager *manager) MetaMonitorManager *manager,
gboolean stored)
{ {
GPtrArray *crtcs, *outputs; GPtrArray *crtcs, *outputs;
gboolean ret = FALSE;
crtcs = g_ptr_array_new_full (config->n_outputs, (GDestroyNotify)meta_crtc_info_free); crtcs = g_ptr_array_new_full (config->n_outputs, (GDestroyNotify)meta_crtc_info_free);
outputs = g_ptr_array_new_full (config->n_outputs, (GDestroyNotify)meta_output_info_free); outputs = g_ptr_array_new_full (config->n_outputs, (GDestroyNotify)meta_output_info_free);
if (!meta_monitor_config_assign_crtcs (config, manager, crtcs, outputs)) if (!meta_monitor_config_assign_crtcs (config, manager, crtcs, outputs))
goto out; {
g_ptr_array_unref (crtcs);
g_ptr_array_unref (outputs);
if (!stored)
config_free (config);
return FALSE;
}
meta_monitor_manager_apply_configuration (manager, meta_monitor_manager_apply_configuration (manager,
(MetaCRTCInfo**)crtcs->pdata, crtcs->len, (MetaCRTCInfo**)crtcs->pdata, crtcs->len,
(MetaOutputInfo**)outputs->pdata, outputs->len); (MetaOutputInfo**)outputs->pdata, outputs->len);
set_current (self, config); /* Stored (persistent) configurations override the previous one always.
Also, we clear the previous configuration if the current one (which is
about to become previous) is stored, or if the current one has
different outputs.
*/
if (stored ||
(self->current && self->current_is_stored))
{
if (self->previous)
config_free (self->previous);
self->previous = NULL;
}
else
{
/* Despite the name, config_equal() only checks the set of outputs,
not their modes
*/
if (self->current && config_equal (self->current, config))
{
self->previous = self->current;
}
else
{
if (self->current)
config_free (self->current);
self->previous = NULL;
}
}
self->current = config;
self->current_is_stored = stored;
/* If true, we'll be overridden at the end of this call /* If true, we'll be overridden at the end of this call
* inside turn_off_laptop_display / apply_configuration_with_lid */ inside turn_off_laptop_display()
*/
self->current_is_for_laptop_lid = FALSE; self->current_is_for_laptop_lid = FALSE;
ret = TRUE; if (self->current == self->previous)
self->previous = NULL;
out:
g_ptr_array_unref (crtcs); g_ptr_array_unref (crtcs);
g_ptr_array_unref (outputs); g_ptr_array_unref (outputs);
return ret; return TRUE;
} }
static gboolean static gboolean
@@ -915,19 +945,6 @@ laptop_display_is_on (MetaConfiguration *config)
return FALSE; return FALSE;
} }
static gboolean
multiple_outputs_are_enabled (MetaConfiguration *config)
{
unsigned int i, enabled;
enabled = 0;
for (i = 0; i < config->n_outputs; i++)
if (config->outputs[i].enabled)
enabled++;
return enabled > 1;
}
static MetaConfiguration * static MetaConfiguration *
make_laptop_lid_config (MetaConfiguration *reference) make_laptop_lid_config (MetaConfiguration *reference)
{ {
@@ -937,9 +954,9 @@ make_laptop_lid_config (MetaConfiguration *reference)
int x_after, y_after; int x_after, y_after;
int x_offset, y_offset; int x_offset, y_offset;
g_assert (multiple_outputs_are_enabled (reference)); g_assert (reference->n_outputs > 1);
new = config_new (); new = g_slice_new0 (MetaConfiguration);
new->n_outputs = reference->n_outputs; new->n_outputs = reference->n_outputs;
new->keys = g_new0 (MetaOutputKey, reference->n_outputs); new->keys = g_new0 (MetaOutputKey, reference->n_outputs);
new->outputs = g_new0 (MetaOutputConfig, reference->n_outputs); new->outputs = g_new0 (MetaOutputConfig, reference->n_outputs);
@@ -994,32 +1011,6 @@ make_laptop_lid_config (MetaConfiguration *reference)
return new; return new;
} }
static gboolean
apply_configuration_with_lid (MetaMonitorConfig *self,
MetaConfiguration *config,
MetaMonitorManager *manager)
{
if (self->lid_is_closed &&
multiple_outputs_are_enabled (config) &&
laptop_display_is_on (config))
{
MetaConfiguration *laptop_lid_config = make_laptop_lid_config (config);
if (apply_configuration (self, laptop_lid_config, manager))
{
self->current_is_for_laptop_lid = TRUE;
config_unref (laptop_lid_config);
return TRUE;
}
else
{
config_unref (laptop_lid_config);
return FALSE;
}
}
else
return apply_configuration (self, config, manager);
}
gboolean gboolean
meta_monitor_config_apply_stored (MetaMonitorConfig *self, meta_monitor_config_apply_stored (MetaMonitorConfig *self,
MetaMonitorManager *manager) MetaMonitorManager *manager)
@@ -1032,7 +1023,23 @@ meta_monitor_config_apply_stored (MetaMonitorConfig *self,
stored = meta_monitor_config_get_stored (self, outputs, n_outputs); stored = meta_monitor_config_get_stored (self, outputs, n_outputs);
if (stored) if (stored)
return apply_configuration_with_lid (self, stored, manager); {
if (self->lid_is_closed &&
stored->n_outputs > 1 &&
laptop_display_is_on (stored))
{
if (apply_configuration (self, make_laptop_lid_config (stored),
manager, FALSE))
{
self->current_is_for_laptop_lid = TRUE;
return TRUE;
}
else
return FALSE;
}
else
return apply_configuration (self, stored, manager, TRUE);
}
else else
return FALSE; return FALSE;
} }
@@ -1082,123 +1089,47 @@ find_primary_output (MetaOutput *outputs,
return best; return best;
} }
static void static MetaConfiguration *
init_config_from_preferred_mode (MetaOutputConfig *config, make_default_config (MetaMonitorConfig *self,
MetaOutput *output) MetaOutput *outputs,
unsigned n_outputs,
int max_width,
int max_height)
{ {
config->enabled = TRUE;
config->rect.x = 0;
config->rect.y = 0;
config->rect.width = output->preferred_mode->width;
config->rect.height = output->preferred_mode->height;
config->refresh_rate = output->preferred_mode->refresh_rate;
config->transform = META_MONITOR_TRANSFORM_NORMAL;
config->is_primary = FALSE;
config->is_presentation = FALSE;
}
/* This function handles configuring the outputs when the driver provides a
* suggested layout position for each output. This is done in recent versions
* of qxl and allows displays to be aligned on the guest in the same order as
* they are aligned on the client.
*/
static gboolean
make_suggested_config (MetaMonitorConfig *self,
MetaOutput *outputs,
unsigned n_outputs,
int max_width,
int max_height,
MetaConfiguration *config)
{
unsigned int i;
MetaOutput *primary;
GList *region = NULL;
g_return_val_if_fail (config != NULL, FALSE);
primary = find_primary_output (outputs, n_outputs);
for (i = 0; i < n_outputs; i++)
{
gboolean is_primary = (&outputs[i] == primary);
if (outputs[i].suggested_x < 0 || outputs[i].suggested_y < 0)
return FALSE;
init_config_from_preferred_mode (&config->outputs[i], &outputs[i]);
config->outputs[i].is_primary = is_primary;
config->outputs[i].rect.x = outputs[i].suggested_x;
config->outputs[i].rect.y = outputs[i].suggested_y;
/* Reject the configuration if the suggested positions result in
* overlapping displays */
if (meta_rectangle_overlaps_with_region (region, &config->outputs[i].rect))
{
g_warning ("Overlapping outputs, rejecting suggested configuration");
g_list_free (region);
return FALSE;
}
region = g_list_prepend (region, &config->outputs[i].rect);
}
g_list_free (region);
return TRUE;
}
static void
make_linear_config (MetaMonitorConfig *self,
MetaOutput *outputs,
unsigned n_outputs,
int max_width,
int max_height,
MetaConfiguration *config)
{
MetaOutput *primary;
unsigned i;
int x;
g_return_if_fail (config != NULL);
primary = find_primary_output (outputs, n_outputs);
x = primary->preferred_mode->width;
for (i = 0; i < n_outputs; i++)
{
gboolean is_primary = (&outputs[i] == primary);
init_config_from_preferred_mode (&config->outputs[i], &outputs[i]);
config->outputs[i].is_primary = is_primary;
if (is_primary)
{
config->outputs[i].rect.x = 0;
}
else
{
config->outputs[i].rect.x = x;
x += config->outputs[i].rect.width;
}
}
}
/* Search for a configuration that includes one less screen, then add the new
* one as a presentation screen in preferred mode.
*
* XXX: but presentation mode is not implemented in the control-center or in
* mutter core, so let's do extended for now.
*/
static gboolean
extend_stored_config (MetaMonitorConfig *self,
MetaOutput *outputs,
unsigned n_outputs,
int max_width,
int max_height,
MetaConfiguration *config)
{
int x, y;
unsigned i, j; unsigned i, j;
int x, y;
MetaConfiguration *ret;
MetaOutput *primary;
ret = g_slice_new (MetaConfiguration);
make_config_key (ret, outputs, n_outputs, -1);
ret->outputs = g_new0 (MetaOutputConfig, n_outputs);
/* Special case the simple case: one output, primary at preferred mode,
nothing else to do */
if (n_outputs == 1)
{
ret->outputs[0].enabled = TRUE;
ret->outputs[0].rect.x = 0;
ret->outputs[0].rect.y = 0;
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 = WL_OUTPUT_TRANSFORM_NORMAL;
ret->outputs[0].is_primary = TRUE;
return ret;
}
/* If we reach this point, this is either the first time mutter runs
on this system ever, or we just hotplugged a new screen.
In the latter case, search for a configuration that includes one
less screen, then add the new one as a presentation screen
in preferred mode.
XXX: but presentation mode is not implemented in the control-center
or in mutter core, so let's do extended for now.
*/
x = 0; x = 0;
y = 0; y = 0;
for (i = 0; i < n_outputs; i++) for (i = 0; i < n_outputs; i++)
@@ -1216,80 +1147,69 @@ extend_stored_config (MetaMonitorConfig *self,
{ {
if (j < i) if (j < i)
{ {
g_assert (output_key_equal (&config->keys[j], &ref->keys[j])); g_assert (output_key_equal (&ret->keys[j], &ref->keys[j]));
config->outputs[j] = ref->outputs[j]; ret->outputs[j] = ref->outputs[j];
x = MAX (x, ref->outputs[j].rect.x + ref->outputs[j].rect.width); x = MAX (x, ref->outputs[j].rect.x + ref->outputs[j].rect.width);
y = MAX (y, ref->outputs[j].rect.y + ref->outputs[j].rect.height); y = MAX (y, ref->outputs[j].rect.y + ref->outputs[j].rect.height);
} }
else if (j > i) else if (j > i)
{ {
g_assert (output_key_equal (&config->keys[j], &ref->keys[j - 1])); g_assert (output_key_equal (&ret->keys[j], &ref->keys[j - 1]));
config->outputs[j] = ref->outputs[j - 1]; ret->outputs[j] = ref->outputs[j - 1];
x = MAX (x, ref->outputs[j - 1].rect.x + ref->outputs[j - 1].rect.width); x = MAX (x, ref->outputs[j - 1].rect.x + ref->outputs[j - 1].rect.width);
y = MAX (y, ref->outputs[j - 1].rect.y + ref->outputs[j - 1].rect.height); y = MAX (y, ref->outputs[j - 1].rect.y + ref->outputs[j - 1].rect.height);
} }
else else
{ {
init_config_from_preferred_mode (&config->outputs[j], &outputs[0]); ret->outputs[j].enabled = TRUE;
ret->outputs[j].rect.x = 0;
ret->outputs[j].rect.y = 0;
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 = WL_OUTPUT_TRANSFORM_NORMAL;
ret->outputs[j].is_primary = FALSE;
ret->outputs[j].is_presentation = FALSE;
} }
} }
/* Place the new output at the right end of the screen, if it fits, /* Place the new output at the right end of the screen, if it fits,
otherwise below it, otherwise disable it (or apply_configuration will fail) */ otherwise below it, otherwise disable it (or apply_configuration will fail) */
if (x + config->outputs[i].rect.width <= max_width) if (x + ret->outputs[i].rect.width <= max_width)
config->outputs[i].rect.x = x; ret->outputs[i].rect.x = x;
else if (y + config->outputs[i].rect.height <= max_height) else if (y + ret->outputs[i].rect.height <= max_height)
config->outputs[i].rect.y = y; ret->outputs[i].rect.y = y;
else else
config->outputs[i].enabled = FALSE; ret->outputs[i].enabled = FALSE;
return TRUE; return ret;
} }
} }
return FALSE; /* No previous configuration found, try with a really default one, which
} is one primary that goes first and the rest to the right of it, extended.
*/
primary = find_primary_output (outputs, n_outputs);
static MetaConfiguration * x = primary->preferred_mode->width;
make_default_config (MetaMonitorConfig *self,
MetaOutput *outputs,
unsigned n_outputs,
int max_width,
int max_height,
gboolean use_stored_config)
{
MetaConfiguration *ret = NULL;
unsigned i;
ret = config_new ();
make_config_key (ret, outputs, n_outputs, -1);
ret->outputs = g_new0 (MetaOutputConfig, n_outputs);
/* Special case the simple case: one output, primary at preferred mode,
nothing else to do */
if (n_outputs == 1)
{
init_config_from_preferred_mode (&ret->outputs[0], &outputs[0]);
ret->outputs[0].is_primary = TRUE;
goto check_limits;
}
if (make_suggested_config (self, outputs, n_outputs, max_width, max_height, ret))
goto check_limits;
if (use_stored_config &&
extend_stored_config (self, outputs, n_outputs, max_width, max_height, ret))
goto check_limits;
make_linear_config (self, outputs, n_outputs, max_width, max_height, ret);
check_limits:
/* Disable outputs that would go beyond framebuffer limits */
for (i = 0; i < n_outputs; i++) for (i = 0; i < n_outputs; i++)
{ {
if ((ret->outputs[i].rect.x + ret->outputs[i].rect.width > max_width) MetaOutput *output = &outputs[i];
|| (ret->outputs[i].rect.y + ret->outputs[i].rect.height > max_height))
ret->outputs[i].enabled = FALSE; ret->outputs[i].enabled = TRUE;
ret->outputs[i].rect.x = (output == primary) ? 0 : x;
ret->outputs[i].rect.y = 0;
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 = WL_OUTPUT_TRANSFORM_NORMAL;
ret->outputs[i].is_primary = (output == primary);
/* Disable outputs that would go beyond framebuffer limits */
if (ret->outputs[i].rect.x + ret->outputs[i].rect.width > max_width)
ret->outputs[i].enabled = FALSE;
else if (output != primary)
x += output->preferred_mode->width;
} }
return ret; return ret;
@@ -1301,7 +1221,7 @@ ensure_at_least_one_output (MetaMonitorConfig *self,
MetaOutput *outputs, MetaOutput *outputs,
unsigned n_outputs) unsigned n_outputs)
{ {
MetaConfiguration *config; MetaConfiguration *ret;
MetaOutput *primary; MetaOutput *primary;
unsigned i; unsigned i;
@@ -1312,29 +1232,34 @@ ensure_at_least_one_output (MetaMonitorConfig *self,
/* Oh no, we don't! Activate the primary one and disable everything else */ /* Oh no, we don't! Activate the primary one and disable everything else */
config = config_new (); ret = g_slice_new (MetaConfiguration);
make_config_key (config, outputs, n_outputs, -1); make_config_key (ret, outputs, n_outputs, -1);
config->outputs = g_new0 (MetaOutputConfig, n_outputs); ret->outputs = g_new0 (MetaOutputConfig, n_outputs);
primary = find_primary_output (outputs, n_outputs); primary = find_primary_output (outputs, n_outputs);
for (i = 0; i < n_outputs; i++) for (i = 0; i < n_outputs; i++)
{ {
gboolean is_primary = (&outputs[i] == primary); MetaOutput *output = &outputs[i];
if (is_primary) if (output == primary)
{ {
init_config_from_preferred_mode (&config->outputs[i], &outputs[0]); ret->outputs[i].enabled = TRUE;
config->outputs[i].is_primary = TRUE; ret->outputs[i].rect.x = 0;
ret->outputs[i].rect.y = 0;
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 = WL_OUTPUT_TRANSFORM_NORMAL;
ret->outputs[i].is_primary = TRUE;
} }
else else
{ {
config->outputs[i].enabled = FALSE; ret->outputs[i].enabled = FALSE;
} }
} }
apply_configuration (self, config, manager); apply_configuration (self, ret, manager, FALSE);
config_unref (config);
return FALSE; return FALSE;
} }
@@ -1345,9 +1270,8 @@ meta_monitor_config_make_default (MetaMonitorConfig *self,
MetaOutput *outputs; MetaOutput *outputs;
MetaConfiguration *default_config; MetaConfiguration *default_config;
unsigned n_outputs; unsigned n_outputs;
gboolean ok = FALSE; gboolean ok;
int max_width, max_height; int max_width, max_height;
gboolean use_stored_config;
outputs = meta_monitor_manager_get_outputs (manager, &n_outputs); outputs = meta_monitor_manager_get_outputs (manager, &n_outputs);
meta_monitor_manager_get_screen_limits (manager, &max_width, &max_height); meta_monitor_manager_get_screen_limits (manager, &max_width, &max_height);
@@ -1358,21 +1282,23 @@ meta_monitor_config_make_default (MetaMonitorConfig *self,
return; return;
} }
/* if the device has hotplug_mode_update, it's possible that the default_config = make_default_config (self, outputs, n_outputs, max_width, max_height);
* current display configuration does not match a stored configuration.
* Since extend_existing_config() tries to build a configuration that is
* based on a previously-stored configuration, it's quite likely that the
* resulting config will fail. Even if it doesn't fail, it may result in
* an unexpected configuration, so don't attempt to use a stored config
* in this situation. */
use_stored_config = !meta_monitor_manager_has_hotplug_mode_update (manager);
default_config = make_default_config (self, outputs, n_outputs, max_width, max_height, use_stored_config);
if (default_config != NULL) if (default_config != NULL)
{ {
ok = apply_configuration_with_lid (self, default_config, manager); if (self->lid_is_closed &&
config_unref (default_config); default_config->n_outputs > 1 &&
laptop_display_is_on (default_config))
{
ok = apply_configuration (self, make_laptop_lid_config (default_config),
manager, FALSE);
config_free (default_config);
}
else
ok = apply_configuration (self, default_config, manager, FALSE);
} }
else
ok = FALSE;
if (!ok) if (!ok)
{ {
@@ -1409,7 +1335,7 @@ meta_monitor_config_update_current (MetaMonitorConfig *self,
outputs = meta_monitor_manager_get_outputs (manager, &n_outputs); outputs = meta_monitor_manager_get_outputs (manager, &n_outputs);
current = config_new (); current = g_slice_new (MetaConfiguration);
current->n_outputs = n_outputs; current->n_outputs = n_outputs;
current->outputs = g_new0 (MetaOutputConfig, n_outputs); current->outputs = g_new0 (MetaOutputConfig, n_outputs);
current->keys = g_new0 (MetaOutputKey, n_outputs); current->keys = g_new0 (MetaOutputKey, n_outputs);
@@ -1422,11 +1348,15 @@ meta_monitor_config_update_current (MetaMonitorConfig *self,
if (self->current && config_equal_full (current, self->current)) if (self->current && config_equal_full (current, self->current))
{ {
config_unref (current); config_free (current);
return; return;
} }
set_current (self, current); if (self->current && !self->current_is_stored)
config_free (self->current);
self->current = current;
self->current_is_stored = FALSE;
} }
void void
@@ -1434,17 +1364,7 @@ meta_monitor_config_restore_previous (MetaMonitorConfig *self,
MetaMonitorManager *manager) MetaMonitorManager *manager)
{ {
if (self->previous) if (self->previous)
{ apply_configuration (self, self->previous, manager, FALSE);
/* The user chose to restore the previous configuration. In this
* case, restore the previous configuration. */
MetaConfiguration *prev_config = config_ref (self->previous);
apply_configuration (self, prev_config, manager);
config_unref (prev_config);
/* After this, self->previous contains the rejected configuration.
* Since it was rejected, nuke it. */
g_clear_pointer (&self->previous, (GDestroyNotify) config_unref);
}
else else
{ {
if (!meta_monitor_config_apply_stored (self, manager)) if (!meta_monitor_config_apply_stored (self, manager))
@@ -1458,12 +1378,11 @@ turn_off_laptop_display (MetaMonitorConfig *self,
{ {
MetaConfiguration *new; MetaConfiguration *new;
if (!multiple_outputs_are_enabled (self->current)) if (self->current->n_outputs == 1)
return; return;
new = make_laptop_lid_config (self->current); new = make_laptop_lid_config (self->current);
apply_configuration (self, new, manager); apply_configuration (self, new, manager, FALSE);
config_unref (new);
self->current_is_for_laptop_lid = TRUE; self->current_is_for_laptop_lid = TRUE;
} }
@@ -1593,7 +1512,7 @@ meta_monitor_config_save (MetaMonitorConfig *self)
output->rect.x, output->rect.x,
output->rect.y, output->rect.y,
rotation_map[output->transform & 0x3], 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_primary ? "yes" : "no",
output->is_presentation ? "yes" : "no"); output->is_presentation ? "yes" : "no");
} }
@@ -1622,7 +1541,16 @@ meta_monitor_config_save (MetaMonitorConfig *self)
void void
meta_monitor_config_make_persistent (MetaMonitorConfig *self) meta_monitor_config_make_persistent (MetaMonitorConfig *self)
{ {
g_hash_table_replace (self->configs, self->current, config_ref (self->current)); if (self->current_is_stored)
return;
self->current_is_stored = TRUE;
g_hash_table_replace (self->configs, self->current, self->current);
if (self->previous)
config_free (self->previous);
self->previous = NULL;
meta_monitor_config_save (self); meta_monitor_config_save (self);
} }
@@ -1693,13 +1621,13 @@ output_supports_mode (MetaOutput *output,
} }
static gboolean static gboolean
crtc_assignment_assign (CrtcAssignment *assign, crtc_assignment_assign (CrtcAssignment *assign,
MetaCRTC *crtc, MetaCRTC *crtc,
MetaMonitorMode *mode, MetaMonitorMode *mode,
int x, int x,
int y, int y,
MetaMonitorTransform transform, enum wl_output_transform transform,
MetaOutput *output) MetaOutput *output)
{ {
MetaCRTCInfo *info = g_hash_table_lookup (assign->info, crtc); MetaCRTCInfo *info = g_hash_table_lookup (assign->info, crtc);
@@ -1861,6 +1789,7 @@ real_assign_crtcs (CrtcAssignment *assignment,
output_config->transform, output_config->transform,
pass); pass);
if (crtc_assignment_assign (assignment, crtc, &modes[j], if (crtc_assignment_assign (assignment, crtc, &modes[j],
output_config->rect.x, output_config->rect.y, output_config->rect.x, output_config->rect.y,
output_config->transform, output_config->transform,

View File

@@ -36,6 +36,9 @@ GType meta_monitor_config_get_type (void) G_GNUC_CONST;
MetaMonitorConfig *meta_monitor_config_new (void); MetaMonitorConfig *meta_monitor_config_new (void);
gboolean meta_monitor_config_match_current (MetaMonitorConfig *config,
MetaMonitorManager *manager);
gboolean meta_monitor_config_apply_stored (MetaMonitorConfig *config, gboolean meta_monitor_config_apply_stored (MetaMonitorConfig *config,
MetaMonitorManager *manager); MetaMonitorManager *manager);

View File

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

View File

@@ -37,13 +37,19 @@
#include <meta/errors.h> #include <meta/errors.h>
#include "meta-monitor-config.h" #include "meta-monitor-config.h"
#include "backends/x11/meta-monitor-manager-xrandr.h" #include "backends/x11/meta-monitor-manager-xrandr.h"
#include "meta-backend-private.h" #include "meta-backend.h"
enum { enum {
CONFIRM_DISPLAY_CHANGE, CONFIRM_DISPLAY_CHANGE,
SIGNALS_LAST SIGNALS_LAST
}; };
enum {
PROP_0,
PROP_POWER_SAVE_MODE,
PROP_LAST
};
static int signals[SIGNALS_LAST]; static int signals[SIGNALS_LAST];
static void meta_monitor_manager_display_config_init (MetaDBusDisplayConfigIface *iface); static void meta_monitor_manager_display_config_init (MetaDBusDisplayConfigIface *iface);
@@ -58,6 +64,14 @@ meta_monitor_manager_init (MetaMonitorManager *manager)
{ {
} }
static void
read_current_config (MetaMonitorManager *manager)
{
manager->serial++;
META_MONITOR_MANAGER_GET_CLASS (manager)->read_current (manager);
}
/* /*
* make_logical_config: * make_logical_config:
* *
@@ -111,7 +125,7 @@ make_logical_config (MetaMonitorManager *manager)
*/ */
info.is_presentation = TRUE; info.is_presentation = TRUE;
info.in_fullscreen = -1; info.in_fullscreen = -1;
info.winsys_id = 0; info.output_id = 0;
g_array_append_val (monitor_infos, info); g_array_append_val (monitor_infos, info);
@@ -142,8 +156,8 @@ make_logical_config (MetaMonitorManager *manager)
info->is_primary = info->is_primary || output->is_primary; info->is_primary = info->is_primary || output->is_primary;
info->is_presentation = info->is_presentation && output->is_presentation; info->is_presentation = info->is_presentation && output->is_presentation;
if (output->is_primary || info->winsys_id == 0) if (output->is_primary || info->output_id == 0)
info->winsys_id = output->winsys_id; info->output_id = output->output_id;
if (info->is_primary) if (info->is_primary)
manager->primary_monitor_index = info->number; manager->primary_monitor_index = info->number;
@@ -153,44 +167,16 @@ make_logical_config (MetaMonitorManager *manager)
manager->monitor_infos = (void*)g_array_free (monitor_infos, FALSE); manager->monitor_infos = (void*)g_array_free (monitor_infos, FALSE);
} }
static void
power_save_mode_changed (MetaMonitorManager *manager,
GParamSpec *pspec,
gpointer user_data)
{
MetaMonitorManagerClass *klass;
int mode = meta_dbus_display_config_get_power_save_mode (META_DBUS_DISPLAY_CONFIG (manager));
if (mode == META_POWER_SAVE_UNSUPPORTED)
return;
/* If DPMS is unsupported, force the property back. */
if (manager->power_save_mode == META_POWER_SAVE_UNSUPPORTED)
{
meta_dbus_display_config_set_power_save_mode (META_DBUS_DISPLAY_CONFIG (manager), META_POWER_SAVE_UNSUPPORTED);
return;
}
klass = META_MONITOR_MANAGER_GET_CLASS (manager);
if (klass->set_power_save_mode)
klass->set_power_save_mode (manager, mode);
manager->power_save_mode = mode;
}
static void static void
meta_monitor_manager_constructed (GObject *object) meta_monitor_manager_constructed (GObject *object)
{ {
MetaMonitorManager *manager = META_MONITOR_MANAGER (object); MetaMonitorManager *manager = META_MONITOR_MANAGER (object);
g_signal_connect_object (manager, "notify::power-save-mode",
G_CALLBACK (power_save_mode_changed), manager, 0);
manager->in_init = TRUE; manager->in_init = TRUE;
manager->config = meta_monitor_config_new (); manager->config = meta_monitor_config_new ();
meta_monitor_manager_read_current_config (manager); read_current_config (manager);
if (!meta_monitor_config_apply_stored (manager->config, manager)) if (!meta_monitor_config_apply_stored (manager->config, manager))
meta_monitor_config_make_default (manager->config, manager); meta_monitor_config_make_default (manager->config, manager);
@@ -203,7 +189,24 @@ meta_monitor_manager_constructed (GObject *object)
so this is not needed. so this is not needed.
*/ */
if (META_IS_MONITOR_MANAGER_XRANDR (manager)) if (META_IS_MONITOR_MANAGER_XRANDR (manager))
meta_monitor_manager_read_current_config (manager); {
MetaOutput *old_outputs;
MetaCRTC *old_crtcs;
MetaMonitorMode *old_modes;
unsigned int n_old_outputs, n_old_modes;
old_outputs = manager->outputs;
n_old_outputs = manager->n_outputs;
old_modes = manager->modes;
n_old_modes = manager->n_modes;
old_crtcs = manager->crtcs;
read_current_config (manager);
meta_monitor_manager_free_output_array (old_outputs, n_old_outputs);
meta_monitor_manager_free_mode_array (old_modes, n_old_modes);
g_free (old_crtcs);
}
make_logical_config (manager); make_logical_config (manager);
initialize_dbus_interface (manager); initialize_dbus_interface (manager);
@@ -212,6 +215,23 @@ meta_monitor_manager_constructed (GObject *object)
} }
static void static void
meta_monitor_manager_set_power_save_mode (MetaMonitorManager *manager,
MetaPowerSave mode)
{
MetaMonitorManagerClass *klass;
if (manager->power_save_mode == META_POWER_SAVE_UNSUPPORTED ||
mode == META_POWER_SAVE_UNSUPPORTED)
return;
klass = META_MONITOR_MANAGER_GET_CLASS (manager);
if (klass->set_power_save_mode)
klass->set_power_save_mode (manager, mode);
manager->power_save_mode = mode;
}
void
meta_monitor_manager_free_output_array (MetaOutput *old_outputs, meta_monitor_manager_free_output_array (MetaOutput *old_outputs,
int n_old_outputs) int n_old_outputs)
{ {
@@ -234,7 +254,7 @@ meta_monitor_manager_free_output_array (MetaOutput *old_outputs,
g_free (old_outputs); g_free (old_outputs);
} }
static void void
meta_monitor_manager_free_mode_array (MetaMonitorMode *old_modes, meta_monitor_manager_free_mode_array (MetaMonitorMode *old_modes,
int n_old_modes) int n_old_modes)
{ {
@@ -278,6 +298,44 @@ meta_monitor_manager_dispose (GObject *object)
G_OBJECT_CLASS (meta_monitor_manager_parent_class)->dispose (object); G_OBJECT_CLASS (meta_monitor_manager_parent_class)->dispose (object);
} }
static void
meta_monitor_manager_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MetaMonitorManager *self = META_MONITOR_MANAGER (object);
switch (prop_id)
{
case PROP_POWER_SAVE_MODE:
meta_monitor_manager_set_power_save_mode (self, g_value_get_int (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_monitor_manager_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MetaMonitorManager *self = META_MONITOR_MANAGER (object);
switch (prop_id)
{
case PROP_POWER_SAVE_MODE:
g_value_set_int (value, self->power_save_mode);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static GBytes * static GBytes *
meta_monitor_manager_real_read_edid (MetaMonitorManager *manager, meta_monitor_manager_real_read_edid (MetaMonitorManager *manager,
MetaOutput *output) MetaOutput *output)
@@ -298,6 +356,8 @@ meta_monitor_manager_class_init (MetaMonitorManagerClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->constructed = meta_monitor_manager_constructed; object_class->constructed = meta_monitor_manager_constructed;
object_class->get_property = meta_monitor_manager_get_property;
object_class->set_property = meta_monitor_manager_set_property;
object_class->dispose = meta_monitor_manager_dispose; object_class->dispose = meta_monitor_manager_dispose;
object_class->finalize = meta_monitor_manager_finalize; object_class->finalize = meta_monitor_manager_finalize;
@@ -311,6 +371,8 @@ meta_monitor_manager_class_init (MetaMonitorManagerClass *klass)
0, 0,
NULL, NULL, NULL, NULL, NULL, NULL,
G_TYPE_NONE, 0); G_TYPE_NONE, 0);
g_object_class_override_property (object_class, PROP_POWER_SAVE_MODE, "power-save-mode");
} }
static const double known_diagonals[] = { static const double known_diagonals[] = {
@@ -415,7 +477,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
GVariantBuilder transforms; GVariantBuilder transforms;
g_variant_builder_init (&transforms, G_VARIANT_TYPE ("au")); 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)) if (crtc->all_transforms & (1 << j))
g_variant_builder_add (&transforms, "u", j); g_variant_builder_add (&transforms, "u", j);
@@ -498,7 +560,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
g_variant_builder_add (&output_builder, "(uxiausauaua{sv})", g_variant_builder_add (&output_builder, "(uxiausauaua{sv})",
i, /* ID */ i, /* ID */
(gint64)output->winsys_id, (gint64)output->output_id,
(int)(output->crtc ? output->crtc - manager->crtcs : -1), (int)(output->crtc ? output->crtc - manager->crtcs : -1),
&crtcs, &crtcs,
output->name, output->name,
@@ -605,7 +667,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
int new_mode, x, y; int new_mode, x, y;
int new_screen_width, new_screen_height; int new_screen_width, new_screen_height;
guint transform; guint transform;
guint output_index; guint output_id;
GPtrArray *crtc_infos, *output_infos; GPtrArray *crtc_infos, *output_infos;
if (serial != manager->serial) if (serial != manager->serial)
@@ -632,6 +694,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
MetaOutput *first_output; MetaOutput *first_output;
MetaCRTC *crtc; MetaCRTC *crtc;
MetaMonitorMode *mode; MetaMonitorMode *mode;
guint output_id;
crtc_info = g_slice_new (MetaCRTCInfo); crtc_info = g_slice_new (MetaCRTCInfo);
crtc_info->outputs = g_ptr_array_new (); crtc_info->outputs = g_ptr_array_new ();
@@ -693,8 +756,8 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
crtc_info->y = 0; crtc_info->y = 0;
} }
if (transform < META_MONITOR_TRANSFORM_NORMAL || if (transform < WL_OUTPUT_TRANSFORM_NORMAL ||
transform > META_MONITOR_TRANSFORM_FLIPPED_270 || transform > WL_OUTPUT_TRANSFORM_FLIPPED_270 ||
((crtc->all_transforms & (1 << transform)) == 0)) ((crtc->all_transforms & (1 << transform)) == 0))
{ {
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
@@ -705,18 +768,18 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
crtc_info->transform = transform; crtc_info->transform = transform;
first_output = NULL; 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; 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_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_INVALID_ARGS, G_DBUS_ERROR_INVALID_ARGS,
"Invalid output id"); "Invalid output id");
return TRUE; return TRUE;
} }
output = &manager->outputs[output_index]; output = &manager->outputs[output_id];
if (!output_can_config (output, crtc, mode)) if (!output_can_config (output, crtc, mode))
{ {
@@ -761,12 +824,12 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
} }
g_variant_iter_init (&output_iter, outputs); 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; MetaOutputInfo *output_info;
gboolean primary, presentation; 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_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_INVALID_ARGS, G_DBUS_ERROR_INVALID_ARGS,
@@ -775,7 +838,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
} }
output_info = g_slice_new0 (MetaOutputInfo); 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)) if (g_variant_lookup (properties, "primary", "b", &primary))
output_info->is_primary = primary; output_info->is_primary = primary;
@@ -846,7 +909,7 @@ static gboolean
meta_monitor_manager_handle_change_backlight (MetaDBusDisplayConfig *skeleton, meta_monitor_manager_handle_change_backlight (MetaDBusDisplayConfig *skeleton,
GDBusMethodInvocation *invocation, GDBusMethodInvocation *invocation,
guint serial, guint serial,
guint output_index, guint output_id,
gint value) gint value)
{ {
MetaMonitorManager *manager = META_MONITOR_MANAGER (skeleton); MetaMonitorManager *manager = META_MONITOR_MANAGER (skeleton);
@@ -860,14 +923,14 @@ meta_monitor_manager_handle_change_backlight (MetaDBusDisplayConfig *skeleton,
return TRUE; 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_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_INVALID_ARGS, G_DBUS_ERROR_INVALID_ARGS,
"Invalid output id"); "Invalid output id");
return TRUE; return TRUE;
} }
output = &manager->outputs[output_index]; output = &manager->outputs[output_id];
if (value < 0 || value > 100) if (value < 0 || value > 100)
{ {
@@ -1137,31 +1200,6 @@ meta_monitor_manager_get_screen_limits (MetaMonitorManager *manager,
*height = manager->max_screen_height; *height = manager->max_screen_height;
} }
void
meta_monitor_manager_read_current_config (MetaMonitorManager *manager)
{
MetaOutput *old_outputs;
MetaCRTC *old_crtcs;
MetaMonitorMode *old_modes;
unsigned int n_old_outputs, n_old_modes;
/* Some implementations of read_current use the existing information
* we have available, so don't free the old configuration until after
* read_current finishes. */
old_outputs = manager->outputs;
n_old_outputs = manager->n_outputs;
old_modes = manager->modes;
n_old_modes = manager->n_modes;
old_crtcs = manager->crtcs;
manager->serial++;
META_MONITOR_MANAGER_GET_CLASS (manager)->read_current (manager);
meta_monitor_manager_free_output_array (old_outputs, n_old_outputs);
meta_monitor_manager_free_mode_array (old_modes, n_old_modes);
g_free (old_crtcs);
}
void void
meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager) meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager)
{ {
@@ -1179,22 +1217,3 @@ meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager)
g_free (old_monitor_infos); g_free (old_monitor_infos);
} }
void
meta_monitor_manager_on_hotplug (MetaMonitorManager *manager)
{
gboolean applied_config = FALSE;
/* If the monitor has hotplug_mode_update (which is used by VMs), don't bother
* applying our stored configuration, because it's likely the user just resizing
* the window.
*/
if (!meta_monitor_manager_has_hotplug_mode_update (manager))
{
if (meta_monitor_config_apply_stored (manager->config, manager))
applied_config = TRUE;
}
/* If we haven't applied any configuration, apply the default configuration. */
if (!applied_config)
meta_monitor_config_make_default (manager->config, manager);
}

View File

@@ -41,6 +41,8 @@
#include "display-private.h" #include "display-private.h"
#include <meta/screen.h> #include <meta/screen.h>
#include "stack-tracker.h" #include "stack-tracker.h"
#include "ui.h"
#include <wayland-server.h>
#include "meta-display-config-shared.h" #include "meta-display-config-shared.h"
#include "meta-dbus-display-config.h" #include "meta-dbus-display-config.h"
@@ -58,23 +60,12 @@ typedef struct _MetaMonitorInfo MetaMonitorInfo;
typedef struct _MetaCRTCInfo MetaCRTCInfo; typedef struct _MetaCRTCInfo MetaCRTCInfo;
typedef struct _MetaOutputInfo MetaOutputInfo; 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 struct _MetaOutput
{ {
/* The CRTC driving this output, NULL if the output is not enabled */ /* The CRTC driving this output, NULL if the output is not enabled */
MetaCRTC *crtc; MetaCRTC *crtc;
/* The low-level ID of this output, used to apply back configuration */ /* The low-level ID of this output, used to apply back configuration */
glong winsys_id; glong output_id;
char *name; char *name;
char *vendor; char *vendor;
char *product; char *product;
@@ -116,8 +107,6 @@ struct _MetaOutput
/* get a new preferred mode on hotplug events, to handle dynamic guest resizing */ /* get a new preferred mode on hotplug events, to handle dynamic guest resizing */
gboolean hotplug_mode_update; gboolean hotplug_mode_update;
gint suggested_x;
gint suggested_y;
}; };
struct _MetaCRTC struct _MetaCRTC
@@ -125,7 +114,7 @@ struct _MetaCRTC
glong crtc_id; glong crtc_id;
MetaRectangle rect; MetaRectangle rect;
MetaMonitorMode *current_mode; MetaMonitorMode *current_mode;
MetaMonitorTransform transform; enum wl_output_transform transform;
unsigned int all_transforms; unsigned int all_transforms;
/* Only used to build the logical configuration /* Only used to build the logical configuration
@@ -173,14 +162,14 @@ struct _MetaMonitorInfo
gboolean in_fullscreen; gboolean in_fullscreen;
/* The primary or first output for this monitor, 0 if we can't figure out. /* 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 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 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 (it's an attempt to keep windows on the same monitor, and preferably on
the primary one). the primary one).
*/ */
glong winsys_id; glong output_id;
}; };
/* /*
@@ -196,7 +185,7 @@ struct _MetaCRTCInfo {
MetaMonitorMode *mode; MetaMonitorMode *mode;
int x; int x;
int y; int y;
MetaMonitorTransform transform; enum wl_output_transform transform;
GPtrArray *outputs; GPtrArray *outputs;
}; };
@@ -341,14 +330,16 @@ void meta_monitor_manager_confirm_configuration (MetaMonitorManag
void meta_crtc_info_free (MetaCRTCInfo *info); void meta_crtc_info_free (MetaCRTCInfo *info);
void meta_output_info_free (MetaOutputInfo *info); void meta_output_info_free (MetaOutputInfo *info);
void meta_monitor_manager_free_output_array (MetaOutput *old_outputs,
int n_old_outputs);
void meta_monitor_manager_free_mode_array (MetaMonitorMode *old_modes,
int n_old_modes);
gboolean meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager); gboolean meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager);
void meta_monitor_manager_read_current_config (MetaMonitorManager *manager);
void meta_monitor_manager_on_hotplug (MetaMonitorManager *manager);
/* Returns true if transform causes width and height to be inverted /* Returns true if transform causes width and height to be inverted
This is true for the odd transforms in the enum */ This is true for the odd transforms in the enum */
static inline gboolean static inline gboolean
meta_monitor_transform_is_rotated (MetaMonitorTransform transform) meta_monitor_transform_is_rotated (enum wl_output_transform transform)
{ {
return (transform % 2); return (transform % 2);
} }

View File

@@ -36,24 +36,11 @@
struct _MetaBackendNativePrivate struct _MetaBackendNativePrivate
{ {
MetaLauncher *launcher; MetaLauncher *launcher;
GSettings *keyboard_settings;
}; };
typedef struct _MetaBackendNativePrivate MetaBackendNativePrivate; typedef struct _MetaBackendNativePrivate MetaBackendNativePrivate;
G_DEFINE_TYPE_WITH_PRIVATE (MetaBackendNative, meta_backend_native, META_TYPE_BACKEND); G_DEFINE_TYPE_WITH_PRIVATE (MetaBackendNative, meta_backend_native, META_TYPE_BACKEND);
static void
meta_backend_native_finalize (GObject *object)
{
MetaBackendNative *native = META_BACKEND_NATIVE (object);
MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native);
g_clear_object (&priv->keyboard_settings);
G_OBJECT_CLASS (meta_backend_native_parent_class)->finalize (object);
}
/* /*
* The pointer constrain code is mostly a rip-off of the XRandR code from Xorg. * The pointer constrain code is mostly a rip-off of the XRandR code from Xorg.
* (from xserver/randr/rrcrtc.c, RRConstrainCursorHarder) * (from xserver/randr/rrcrtc.c, RRConstrainCursorHarder)
@@ -155,46 +142,15 @@ pointer_constrain_callback (ClutterInputDevice *device,
constrain_all_screen_monitors(device, monitors, n_monitors, new_x, new_y); constrain_all_screen_monitors(device, monitors, n_monitors, new_x, new_y);
} }
static void
set_keyboard_repeat (MetaBackendNative *native)
{
MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native);
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
gboolean repeat;
unsigned int delay, interval;
repeat = g_settings_get_boolean (priv->keyboard_settings, "repeat");
delay = g_settings_get_uint (priv->keyboard_settings, "delay");
interval = g_settings_get_uint (priv->keyboard_settings, "repeat-interval");
clutter_evdev_set_keyboard_repeat (manager, repeat, delay, interval);
}
static void
keyboard_settings_changed (GSettings *settings,
const char *key,
gpointer data)
{
MetaBackendNative *native = data;
set_keyboard_repeat (native);
}
static void static void
meta_backend_native_post_init (MetaBackend *backend) meta_backend_native_post_init (MetaBackend *backend)
{ {
MetaBackendNative *native = META_BACKEND_NATIVE (backend);
MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native);
ClutterDeviceManager *manager = clutter_device_manager_get_default (); ClutterDeviceManager *manager = clutter_device_manager_get_default ();
META_BACKEND_CLASS (meta_backend_native_parent_class)->post_init (backend); META_BACKEND_CLASS (meta_backend_native_parent_class)->post_init (backend);
clutter_evdev_set_pointer_constrain_callback (manager, pointer_constrain_callback, clutter_evdev_set_pointer_constrain_callback (manager, pointer_constrain_callback,
NULL, NULL); NULL, NULL);
priv->keyboard_settings = g_settings_new ("org.gnome.settings-daemon.peripherals.keyboard");
g_signal_connect (priv->keyboard_settings, "changed",
G_CALLBACK (keyboard_settings_changed), native);
set_keyboard_repeat (native);
} }
static MetaIdleMonitor * static MetaIdleMonitor *
@@ -218,81 +174,15 @@ meta_backend_native_create_cursor_renderer (MetaBackend *backend)
return g_object_new (META_TYPE_CURSOR_RENDERER_NATIVE, NULL); 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_set_keymap (MetaBackend *backend,
const char *layouts,
const char *variants,
const char *options)
{
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
struct xkb_rule_names names;
struct xkb_keymap *keymap;
struct xkb_context *context;
names.rules = DEFAULT_XKB_RULES_FILE;
names.model = DEFAULT_XKB_MODEL;
names.layout = layouts;
names.variant = variants;
names.options = options;
context = xkb_context_new (XKB_CONTEXT_NO_FLAGS);
keymap = xkb_keymap_new_from_names (context, &names, XKB_KEYMAP_COMPILE_NO_FLAGS);
xkb_context_unref (context);
clutter_evdev_set_keyboard_map (manager, keymap);
g_signal_emit_by_name (backend, "keymap-changed", 0);
xkb_keymap_unref (keymap);
}
static struct xkb_keymap *
meta_backend_native_get_keymap (MetaBackend *backend)
{
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
return clutter_evdev_get_keyboard_map (manager);
}
static void
meta_backend_native_lock_layout_group (MetaBackend *backend,
guint idx)
{
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
clutter_evdev_set_keyboard_layout_index (manager, idx);
g_signal_emit_by_name (backend, "keymap-layout-group-changed", idx, 0);
}
static void static void
meta_backend_native_class_init (MetaBackendNativeClass *klass) meta_backend_native_class_init (MetaBackendNativeClass *klass)
{ {
MetaBackendClass *backend_class = META_BACKEND_CLASS (klass); MetaBackendClass *backend_class = META_BACKEND_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_backend_native_finalize;
backend_class->post_init = meta_backend_native_post_init; backend_class->post_init = meta_backend_native_post_init;
backend_class->create_idle_monitor = meta_backend_native_create_idle_monitor; 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_monitor_manager = meta_backend_native_create_monitor_manager;
backend_class->create_cursor_renderer = meta_backend_native_create_cursor_renderer; backend_class->create_cursor_renderer = meta_backend_native_create_cursor_renderer;
backend_class->warp_pointer = meta_backend_native_warp_pointer;
backend_class->set_keymap = meta_backend_native_set_keymap;
backend_class->get_keymap = meta_backend_native_get_keymap;
backend_class->lock_layout_group = meta_backend_native_lock_layout_group;
} }
static void static void
@@ -318,7 +208,7 @@ meta_activate_vt (int vt, GError **error)
* meta_activate_session: * meta_activate_session:
* *
* Tells mutter to activate the session. When mutter is a * Tells mutter to activate the session. When mutter is a
* display server, this tells logind to switch over to * Wayland compositor, this tells logind to switch over to
* the new session. * the new session.
*/ */
gboolean gboolean

View File

@@ -27,27 +27,16 @@
#include "meta-cursor-renderer-native.h" #include "meta-cursor-renderer-native.h"
#include <gbm.h> #include <gbm.h>
#include <xf86drm.h>
#include "meta-cursor-private.h" #include "meta-cursor-private.h"
#include "meta-monitor-manager.h" #include "meta-monitor-manager.h"
#ifndef DRM_CAP_CURSOR_WIDTH
#define DRM_CAP_CURSOR_WIDTH 0x8
#endif
#ifndef DRM_CAP_CURSOR_HEIGHT
#define DRM_CAP_CURSOR_HEIGHT 0x9
#endif
struct _MetaCursorRendererNativePrivate struct _MetaCursorRendererNativePrivate
{ {
gboolean has_hw_cursor; gboolean has_hw_cursor;
int drm_fd; int drm_fd;
struct gbm_device *gbm; struct gbm_device *gbm;
uint64_t cursor_width;
uint64_t cursor_height;
}; };
typedef struct _MetaCursorRendererNativePrivate MetaCursorRendererNativePrivate; typedef struct _MetaCursorRendererNativePrivate MetaCursorRendererNativePrivate;
@@ -82,13 +71,17 @@ set_crtc_cursor (MetaCursorRendererNative *native,
{ {
struct gbm_bo *bo; struct gbm_bo *bo;
union gbm_bo_handle handle; union gbm_bo_handle handle;
int width, height;
int hot_x, hot_y; int hot_x, hot_y;
bo = meta_cursor_reference_get_gbm_bo (cursor, &hot_x, &hot_y); bo = meta_cursor_reference_get_gbm_bo (cursor, &hot_x, &hot_y);
handle = gbm_bo_get_handle (bo); handle = gbm_bo_get_handle (bo);
width = gbm_bo_get_width (bo);
height = gbm_bo_get_height (bo);
drmModeSetCursor2 (priv->drm_fd, crtc->crtc_id, handle.u32, drmModeSetCursor2 (priv->drm_fd, crtc->crtc_id, handle.u32,
priv->cursor_width, priv->cursor_height, hot_x, hot_y); width, height, hot_x, hot_y);
} }
else else
{ {
@@ -193,19 +186,6 @@ meta_cursor_renderer_native_init (MetaCursorRendererNative *native)
CoglRenderer *cogl_renderer = cogl_display_get_renderer (cogl_context_get_display (ctx)); CoglRenderer *cogl_renderer = cogl_display_get_renderer (cogl_context_get_display (ctx));
priv->drm_fd = cogl_kms_renderer_get_kms_fd (cogl_renderer); priv->drm_fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
priv->gbm = gbm_create_device (priv->drm_fd); priv->gbm = gbm_create_device (priv->drm_fd);
uint64_t width, height;
if (drmGetCap (priv->drm_fd, DRM_CAP_CURSOR_WIDTH, &width) == 0 &&
drmGetCap (priv->drm_fd, DRM_CAP_CURSOR_HEIGHT, &height) == 0)
{
priv->cursor_width = width;
priv->cursor_height = height;
}
else
{
priv->cursor_width = 64;
priv->cursor_height = 64;
}
} }
#endif #endif
} }
@@ -218,16 +198,6 @@ meta_cursor_renderer_native_get_gbm_device (MetaCursorRendererNative *native)
return priv->gbm; return priv->gbm;
} }
void
meta_cursor_renderer_native_get_cursor_size (MetaCursorRendererNative *native,
uint64_t *width, uint64_t *height)
{
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
*width = priv->cursor_width;
*height = priv->cursor_height;
}
void void
meta_cursor_renderer_native_force_update (MetaCursorRendererNative *native) meta_cursor_renderer_native_force_update (MetaCursorRendererNative *native)
{ {

View File

@@ -50,7 +50,6 @@ struct _MetaCursorRendererNativeClass
GType meta_cursor_renderer_native_get_type (void) G_GNUC_CONST; GType meta_cursor_renderer_native_get_type (void) G_GNUC_CONST;
struct gbm_device * meta_cursor_renderer_native_get_gbm_device (MetaCursorRendererNative *renderer); struct gbm_device * meta_cursor_renderer_native_get_gbm_device (MetaCursorRendererNative *renderer);
void meta_cursor_renderer_native_get_cursor_size (MetaCursorRendererNative *native, uint64_t *width, uint64_t *height);
void meta_cursor_renderer_native_force_update (MetaCursorRendererNative *renderer); void meta_cursor_renderer_native_force_update (MetaCursorRendererNative *renderer);
#endif /* META_CURSOR_RENDERER_NATIVE_H */ #endif /* META_CURSOR_RENDERER_NATIVE_H */

View File

@@ -41,7 +41,8 @@
#include "dbus-utils.h" #include "dbus-utils.h"
#include "meta-dbus-login1.h" #include "meta-dbus-login1.h"
#include "backends/meta-backend-private.h" #include "wayland/meta-wayland-private.h"
#include "backends/meta-backend.h"
#include "meta-cursor-renderer-native.h" #include "meta-cursor-renderer-native.h"
struct _MetaLauncher struct _MetaLauncher
@@ -100,15 +101,15 @@ session_unpause (void)
clutter_egl_thaw_master_clock (); clutter_egl_thaw_master_clock ();
{ {
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
MetaBackend *backend = meta_get_backend (); MetaBackend *backend = meta_get_backend ();
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (backend); MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (backend);
ClutterActor *stage = meta_backend_get_stage (backend);
/* When we mode-switch back, we need to immediately queue a redraw /* When we mode-switch back, we need to immediately queue a redraw
* in case nothing else queued one for us, and force the cursor to * in case nothing else queued one for us, and force the cursor to
* update. */ * update. */
clutter_actor_queue_redraw (stage); clutter_actor_queue_redraw (compositor->stage);
meta_cursor_renderer_native_force_update (META_CURSOR_RENDERER_NATIVE (renderer)); meta_cursor_renderer_native_force_update (META_CURSOR_RENDERER_NATIVE (renderer));
} }
} }
@@ -130,8 +131,8 @@ take_device (Login1Session *session_proxy,
{ {
gboolean ret = FALSE; gboolean ret = FALSE;
GVariant *fd_variant = NULL; GVariant *fd_variant = NULL;
GUnixFDList *fd_list = NULL;
int fd = -1; int fd = -1;
GUnixFDList *fd_list;
if (!login1_session_call_take_device_sync (session_proxy, if (!login1_session_call_take_device_sync (session_proxy,
dev_major, dev_major,

View File

@@ -24,7 +24,6 @@
#include "config.h" #include "config.h"
#include "meta-monitor-manager-kms.h" #include "meta-monitor-manager-kms.h"
#include "meta-monitor-config.h"
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@@ -41,7 +40,7 @@
#include <meta/errors.h> #include <meta/errors.h>
#include "edid.h" #include "edid.h"
#include <gudev/gudev.h> #define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
typedef struct { typedef struct {
drmModeConnector *connector; drmModeConnector *connector;
@@ -71,8 +70,6 @@ struct _MetaMonitorManagerKms
unsigned int n_encoders; unsigned int n_encoders;
drmModeEncoder *current_encoder; drmModeEncoder *current_encoder;
GUdevClient *udev;
}; };
struct _MetaMonitorManagerKmsClass struct _MetaMonitorManagerKmsClass
@@ -262,7 +259,7 @@ find_output_by_id (MetaOutput *outputs,
unsigned i; unsigned i;
for (i = 0; i < n_outputs; i++) for (i = 0; i < n_outputs; i++)
if (outputs[i].winsys_id == id) if (outputs[i].output_id == id)
return &outputs[i]; return &outputs[i];
return NULL; return NULL;
@@ -366,9 +363,9 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
meta_crtc->rect.width = crtc->width; meta_crtc->rect.width = crtc->width;
meta_crtc->rect.height = crtc->height; meta_crtc->rect.height = crtc->height;
meta_crtc->is_dirty = FALSE; meta_crtc->is_dirty = FALSE;
meta_crtc->transform = META_MONITOR_TRANSFORM_NORMAL; meta_crtc->transform = WL_OUTPUT_TRANSFORM_NORMAL;
/* FIXME: implement! */ /* FIXME: implement! */
meta_crtc->all_transforms = 1 << META_MONITOR_TRANSFORM_NORMAL; meta_crtc->all_transforms = 1 << WL_OUTPUT_TRANSFORM_NORMAL;
if (crtc->mode_valid) if (crtc->mode_valid)
{ {
@@ -411,12 +408,10 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
meta_output->driver_private = output_kms = g_slice_new0 (MetaOutputKms); meta_output->driver_private = output_kms = g_slice_new0 (MetaOutputKms);
meta_output->driver_notify = (GDestroyNotify)meta_output_destroy_notify; 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->name = make_output_name (connector);
meta_output->width_mm = connector->mmWidth; meta_output->width_mm = connector->mmWidth;
meta_output->height_mm = connector->mmHeight; meta_output->height_mm = connector->mmHeight;
meta_output->suggested_x = -1;
meta_output->suggested_y = -1;
switch (connector->subpixel) switch (connector->subpixel)
{ {
@@ -496,7 +491,7 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
meta_output->crtc = NULL; meta_output->crtc = NULL;
old_output = find_output_by_id (old_outputs, n_old_outputs, old_output = find_output_by_id (old_outputs, n_old_outputs,
meta_output->winsys_id); meta_output->output_id);
if (old_output) if (old_output)
{ {
meta_output->is_primary = old_output->is_primary; meta_output->is_primary = old_output->is_primary;
@@ -672,7 +667,7 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
if (output_kms->dpms_prop_id != 0) 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); output_kms->dpms_prop_id, state);
if (ok < 0) if (ok < 0)
@@ -753,7 +748,7 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
{ {
MetaOutput *output = g_ptr_array_index (crtc_info->outputs, j); 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->is_dirty = TRUE;
output->crtc = crtc; output->crtc = crtc;
@@ -900,23 +895,6 @@ meta_monitor_manager_kms_set_crtc_gamma (MetaMonitorManager *manager,
drmModeCrtcSetGamma (manager_kms->fd, crtc->crtc_id, size, red, green, blue); drmModeCrtcSetGamma (manager_kms->fd, crtc->crtc_id, size, red, green, blue);
} }
static void
on_uevent (GUdevClient *client,
const char *action,
GUdevDevice *device,
gpointer user_data)
{
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (user_data);
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms);
if (!g_udev_device_get_property_as_boolean (device, "HOTPLUG"))
return;
meta_monitor_manager_read_current_config (manager);
meta_monitor_manager_on_hotplug (manager);
}
static void static void
meta_monitor_manager_kms_init (MetaMonitorManagerKms *manager_kms) meta_monitor_manager_kms_init (MetaMonitorManagerKms *manager_kms)
{ {
@@ -931,21 +909,6 @@ meta_monitor_manager_kms_init (MetaMonitorManagerKms *manager_kms)
cogl_renderer = cogl_display_get_renderer (cogl_display); cogl_renderer = cogl_display_get_renderer (cogl_display);
manager_kms->fd = cogl_kms_renderer_get_kms_fd (cogl_renderer); manager_kms->fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
const char *subsystems[2] = { "drm", NULL };
manager_kms->udev = g_udev_client_new (subsystems);
g_signal_connect (manager_kms->udev, "uevent",
G_CALLBACK (on_uevent), manager_kms);
}
static void
meta_monitor_manager_kms_dispose (GObject *object)
{
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (object);
g_clear_object (&manager_kms->udev);
G_OBJECT_CLASS (meta_monitor_manager_kms_parent_class)->dispose (object);
} }
static void static void
@@ -964,7 +927,6 @@ meta_monitor_manager_kms_class_init (MetaMonitorManagerKmsClass *klass)
MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass); MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = meta_monitor_manager_kms_dispose;
object_class->finalize = meta_monitor_manager_kms_finalize; object_class->finalize = meta_monitor_manager_kms_finalize;
manager_class->read_current = meta_monitor_manager_kms_read_current; manager_class->read_current = meta_monitor_manager_kms_read_current;

View File

@@ -24,18 +24,11 @@
#include "config.h" #include "config.h"
#include <string.h>
#include <stdlib.h>
#include "meta-backend-x11.h" #include "meta-backend-x11.h"
#include <clutter/x11/clutter-x11.h> #include <clutter/x11/clutter-x11.h>
#include <X11/extensions/sync.h> #include <X11/extensions/sync.h>
#include <X11/XKBlib.h>
#include <X11/extensions/XKBrules.h>
#include <X11/Xlib-xcb.h>
#include <xkbcommon/xkbcommon-x11.h>
#include "meta-idle-monitor-xsync.h" #include "meta-idle-monitor-xsync.h"
#include "meta-monitor-manager-xrandr.h" #include "meta-monitor-manager-xrandr.h"
@@ -50,7 +43,6 @@ struct _MetaBackendX11Private
{ {
/* The host X11 display */ /* The host X11 display */
Display *xdisplay; Display *xdisplay;
xcb_connection_t *xcb;
GSource *source; GSource *source;
int xsync_event_base; int xsync_event_base;
@@ -59,20 +51,9 @@ struct _MetaBackendX11Private
int xinput_opcode; int xinput_opcode;
int xinput_event_base; int xinput_event_base;
int xinput_error_base; int xinput_error_base;
Time latest_evtime;
uint8_t xkb_event_base;
uint8_t xkb_error_base;
struct xkb_keymap *keymap;
gchar *keymap_layouts;
gchar *keymap_variants;
gchar *keymap_options;
}; };
typedef struct _MetaBackendX11Private MetaBackendX11Private; typedef struct _MetaBackendX11Private MetaBackendX11Private;
static void apply_keymap (MetaBackendX11 *x11);
G_DEFINE_TYPE_WITH_PRIVATE (MetaBackendX11, meta_backend_x11, META_TYPE_BACKEND); G_DEFINE_TYPE_WITH_PRIVATE (MetaBackendX11, meta_backend_x11, META_TYPE_BACKEND);
static void static void
@@ -90,7 +71,6 @@ static void
translate_device_event (MetaBackendX11 *x11, translate_device_event (MetaBackendX11 *x11,
XIDeviceEvent *device_event) XIDeviceEvent *device_event)
{ {
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
Window stage_window = meta_backend_x11_get_xwindow (x11); Window stage_window = meta_backend_x11_get_xwindow (x11);
if (device_event->event != stage_window) if (device_event->event != stage_window)
@@ -108,21 +88,6 @@ translate_device_event (MetaBackendX11 *x11,
device_event->event_x = device_event->root_x; device_event->event_x = device_event->root_x;
device_event->event_y = device_event->root_y; 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 /* Clutter makes the assumption that there is only one X window
@@ -152,9 +117,6 @@ maybe_spoof_event_as_stage_event (MetaBackendX11 *x11,
case XI_ButtonRelease: case XI_ButtonRelease:
case XI_KeyPress: case XI_KeyPress:
case XI_KeyRelease: case XI_KeyRelease:
case XI_TouchBegin:
case XI_TouchUpdate:
case XI_TouchEnd:
translate_device_event (x11, (XIDeviceEvent *) input_event); translate_device_event (x11, (XIDeviceEvent *) input_event);
break; break;
default: default:
@@ -163,21 +125,6 @@ maybe_spoof_event_as_stage_event (MetaBackendX11 *x11,
} }
} }
static void
keymap_changed (MetaBackend *backend)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
if (priv->keymap)
{
xkb_keymap_unref (priv->keymap);
priv->keymap = NULL;
}
g_signal_emit_by_name (backend, "keymap-changed", 0);
}
static void static void
handle_host_xevent (MetaBackend *backend, handle_host_xevent (MetaBackend *backend,
XEvent *event) XEvent *event)
@@ -188,49 +135,24 @@ handle_host_xevent (MetaBackend *backend,
XGetEventData (priv->xdisplay, &event->xcookie); XGetEventData (priv->xdisplay, &event->xcookie);
{
MetaDisplay *display = meta_get_display ();
if (display)
{
MetaCompositor *compositor = display->compositor;
if (meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event))
bypass_clutter = TRUE;
}
}
if (event->type == (priv->xsync_event_base + XSyncAlarmNotify)) if (event->type == (priv->xsync_event_base + XSyncAlarmNotify))
handle_alarm_notify (backend, event); handle_alarm_notify (backend, event);
if (event->type == priv->xkb_event_base)
{
XkbAnyEvent *xkb_ev = (XkbAnyEvent *) event;
if (xkb_ev->device == META_VIRTUAL_CORE_KEYBOARD_ID)
{
switch (xkb_ev->xkb_type)
{
case XkbNewKeyboardNotify:
case XkbMapNotify:
keymap_changed (backend);
default:
break;
}
}
}
{ {
MetaMonitorManager *manager = meta_backend_get_monitor_manager (backend); MetaMonitorManager *manager = meta_backend_get_monitor_manager (backend);
if (META_IS_MONITOR_MANAGER_XRANDR (manager) && if (META_IS_MONITOR_MANAGER_XRANDR (manager) &&
meta_monitor_manager_xrandr_handle_xevent (META_MONITOR_MANAGER_XRANDR (manager), event)) 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) if (!bypass_clutter)
{ clutter_x11_handle_event (event);
maybe_spoof_event_as_stage_event (x11, event);
clutter_x11_handle_event (event);
}
XFreeEventData (priv->xdisplay, &event->xcookie); XFreeEventData (priv->xdisplay, &event->xcookie);
} }
@@ -313,35 +235,6 @@ x_event_source_new (MetaBackend *backend)
return source; 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
on_device_added (ClutterDeviceManager *device_manager,
ClutterInputDevice *device,
gpointer user_data)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (user_data);
if (clutter_input_device_get_device_type (device) == CLUTTER_KEYBOARD_DEVICE)
apply_keymap (x11);
}
static void static void
meta_backend_x11_post_init (MetaBackend *backend) meta_backend_x11_post_init (MetaBackend *backend)
{ {
@@ -379,22 +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"); meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer\n");
} }
take_touch_grab (backend);
priv->xcb = XGetXCBConnection (priv->xdisplay);
if (!xkb_x11_setup_xkb_extension (priv->xcb,
XKB_X11_MIN_MAJOR_XKB_VERSION,
XKB_X11_MIN_MINOR_XKB_VERSION,
XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS,
NULL, NULL,
&priv->xkb_event_base,
&priv->xkb_error_base))
meta_fatal ("X server doesn't have the XKB extension, version %d.%d or newer\n",
XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION);
g_signal_connect_object (clutter_device_manager_get_default (), "device-added",
G_CALLBACK (on_device_added), backend, 0);
META_BACKEND_CLASS (meta_backend_x11_parent_class)->post_init (backend); META_BACKEND_CLASS (meta_backend_x11_parent_class)->post_init (backend);
} }
@@ -436,9 +313,6 @@ meta_backend_x11_grab_device (MetaBackend *backend,
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits }; XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
int ret; int ret;
if (timestamp != CurrentTime)
timestamp = MAX (timestamp, priv->latest_evtime);
XISetMask (mask.mask, XI_ButtonPress); XISetMask (mask.mask, XI_ButtonPress);
XISetMask (mask.mask, XI_ButtonRelease); XISetMask (mask.mask, XI_ButtonRelease);
XISetMask (mask.mask, XI_Enter); XISetMask (mask.mask, XI_Enter);
@@ -488,228 +362,6 @@ meta_backend_x11_warp_pointer (MetaBackend *backend,
x, y); x, y);
} }
static void
get_xkbrf_var_defs (Display *xdisplay,
const char *layouts,
const char *variants,
const char *options,
char **rules_p,
XkbRF_VarDefsRec *var_defs)
{
char *rules = NULL;
/* Get it from the X property or fallback on defaults */
if (!XkbRF_GetNamesProp (xdisplay, &rules, var_defs) || !rules)
{
rules = strdup (DEFAULT_XKB_RULES_FILE);
var_defs->model = strdup (DEFAULT_XKB_MODEL);
var_defs->layout = NULL;
var_defs->variant = NULL;
var_defs->options = NULL;
}
/* Swap in our new options... */
free (var_defs->layout);
var_defs->layout = strdup (layouts);
free (var_defs->variant);
var_defs->variant = strdup (variants);
free (var_defs->options);
var_defs->options = strdup (options);
/* Sometimes, the property is a file path, and sometimes it's
not. Normalize it so it's always a file path. */
if (rules[0] == '/')
*rules_p = g_strdup (rules);
else
*rules_p = g_build_filename (XKB_BASE, "rules", rules, NULL);
free (rules);
}
static void
free_xkbrf_var_defs (XkbRF_VarDefsRec *var_defs)
{
free (var_defs->model);
free (var_defs->layout);
free (var_defs->variant);
free (var_defs->options);
}
static void
free_xkb_component_names (XkbComponentNamesRec *p)
{
free (p->keymap);
free (p->keycodes);
free (p->types);
free (p->compat);
free (p->symbols);
free (p->geometry);
}
static void
upload_xkb_description (Display *xdisplay,
const gchar *rules_file_path,
XkbRF_VarDefsRec *var_defs,
XkbComponentNamesRec *comp_names)
{
XkbDescRec *xkb_desc;
gchar *rules_file;
/* Upload it to the X server using the same method as setxkbmap */
xkb_desc = XkbGetKeyboardByName (xdisplay,
XkbUseCoreKbd,
comp_names,
XkbGBN_AllComponentsMask,
XkbGBN_AllComponentsMask &
(~XkbGBN_GeometryMask), True);
if (!xkb_desc)
{
g_warning ("Couldn't upload new XKB keyboard description");
return;
}
XkbFreeKeyboard (xkb_desc, 0, True);
rules_file = g_path_get_basename (rules_file_path);
if (!XkbRF_SetNamesProp (xdisplay, rules_file, var_defs))
g_warning ("Couldn't update the XKB root window property");
g_free (rules_file);
}
static void
apply_keymap (MetaBackendX11 *x11)
{
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
XkbRF_RulesRec *xkb_rules;
XkbRF_VarDefsRec xkb_var_defs = { 0 };
gchar *rules_file_path;
if (!priv->keymap_layouts ||
!priv->keymap_variants ||
!priv->keymap_options)
return;
get_xkbrf_var_defs (priv->xdisplay,
priv->keymap_layouts,
priv->keymap_variants,
priv->keymap_options,
&rules_file_path,
&xkb_var_defs);
xkb_rules = XkbRF_Load (rules_file_path, NULL, True, True);
if (xkb_rules)
{
XkbComponentNamesRec xkb_comp_names = { 0 };
XkbRF_GetComponents (xkb_rules, &xkb_var_defs, &xkb_comp_names);
upload_xkb_description (priv->xdisplay, rules_file_path, &xkb_var_defs, &xkb_comp_names);
free_xkb_component_names (&xkb_comp_names);
XkbRF_Free (xkb_rules, True);
}
else
{
g_warning ("Couldn't load XKB rules");
}
free_xkbrf_var_defs (&xkb_var_defs);
g_free (rules_file_path);
}
static void
meta_backend_x11_set_keymap (MetaBackend *backend,
const char *layouts,
const char *variants,
const char *options)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
g_free (priv->keymap_layouts);
priv->keymap_layouts = g_strdup (layouts);
g_free (priv->keymap_variants);
priv->keymap_variants = g_strdup (variants);
g_free (priv->keymap_options);
priv->keymap_options = g_strdup (options);
apply_keymap (x11);
}
static struct xkb_keymap *
meta_backend_x11_get_keymap (MetaBackend *backend)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
if (priv->keymap == NULL)
{
struct xkb_context *context = xkb_context_new (XKB_CONTEXT_NO_FLAGS);
priv->keymap = xkb_x11_keymap_new_from_device (context,
priv->xcb,
xkb_x11_get_core_keyboard_device_id (priv->xcb),
XKB_KEYMAP_COMPILE_NO_FLAGS);
xkb_context_unref (context);
}
return priv->keymap;
}
static void
meta_backend_x11_lock_layout_group (MetaBackend *backend,
guint idx)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
XkbLockGroup (priv->xdisplay, XkbUseCoreKbd, idx);
}
static void
meta_backend_x11_update_screen_size (MetaBackend *backend,
int width, int height)
{
if (meta_is_wayland_compositor ())
{
/* For a nested wayland session, we want to go through Clutter to update the
* toplevel window size, rather than doing it directly.
*/
META_BACKEND_CLASS (meta_backend_x11_parent_class)->update_screen_size (backend, width, height);
}
else
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
Window xwin = meta_backend_x11_get_xwindow (x11);
XResizeWindow (priv->xdisplay, xwin, width, height);
}
}
static void
meta_backend_x11_select_stage_events (MetaBackend *backend)
{
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
Window xwin = meta_backend_x11_get_xwindow (x11);
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
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);
XIClearMask (mask.mask, XI_TouchBegin);
XIClearMask (mask.mask, XI_TouchEnd);
XIClearMask (mask.mask, XI_TouchUpdate);
XISelectEvents (priv->xdisplay, xwin, &mask, 1);
}
static void static void
meta_backend_x11_class_init (MetaBackendX11Class *klass) meta_backend_x11_class_init (MetaBackendX11Class *klass)
{ {
@@ -719,14 +371,10 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass)
backend_class->create_idle_monitor = meta_backend_x11_create_idle_monitor; backend_class->create_idle_monitor = meta_backend_x11_create_idle_monitor;
backend_class->create_monitor_manager = meta_backend_x11_create_monitor_manager; backend_class->create_monitor_manager = meta_backend_x11_create_monitor_manager;
backend_class->create_cursor_renderer = meta_backend_x11_create_cursor_renderer; backend_class->create_cursor_renderer = meta_backend_x11_create_cursor_renderer;
backend_class->grab_device = meta_backend_x11_grab_device; backend_class->grab_device = meta_backend_x11_grab_device;
backend_class->ungrab_device = meta_backend_x11_ungrab_device; backend_class->ungrab_device = meta_backend_x11_ungrab_device;
backend_class->warp_pointer = meta_backend_x11_warp_pointer; backend_class->warp_pointer = meta_backend_x11_warp_pointer;
backend_class->set_keymap = meta_backend_x11_set_keymap;
backend_class->get_keymap = meta_backend_x11_get_keymap;
backend_class->lock_layout_group = meta_backend_x11_lock_layout_group;
backend_class->update_screen_size = meta_backend_x11_update_screen_size;
backend_class->select_stage_events = meta_backend_x11_select_stage_events;
} }
static void static void
@@ -747,6 +395,12 @@ meta_backend_x11_get_xdisplay (MetaBackendX11 *x11)
Window Window
meta_backend_x11_get_xwindow (MetaBackendX11 *x11) meta_backend_x11_get_xwindow (MetaBackendX11 *x11)
{ {
ClutterActor *stage = meta_backend_get_stage (META_BACKEND (x11)); MetaDisplay *display = meta_get_display ();
return clutter_x11_get_stage_window (CLUTTER_STAGE (stage)); MetaCompositor *compositor = display->compositor;
if (compositor == NULL)
return None;
ClutterStage *stage = CLUTTER_STAGE (compositor->stage);
return clutter_x11_get_stage_window (stage);
} }

View File

@@ -26,8 +26,6 @@
#include "meta-cursor-renderer-x11.h" #include "meta-cursor-renderer-x11.h"
#include <X11/extensions/Xfixes.h>
#include "meta-backend-x11.h" #include "meta-backend-x11.h"
#include "meta-stage.h" #include "meta-stage.h"

View File

@@ -35,8 +35,6 @@
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <X11/extensions/Xrandr.h> #include <X11/extensions/Xrandr.h>
#include <X11/extensions/dpms.h> #include <X11/extensions/dpms.h>
#include <X11/Xlib-xcb.h>
#include <xcb/randr.h>
#include "meta-backend-x11.h" #include "meta-backend-x11.h"
#include <meta/main.h> #include <meta/main.h>
@@ -44,7 +42,7 @@
#include "edid.h" #include "edid.h"
#include "meta-monitor-config.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: /* Look for DPI_FALLBACK in:
* http://git.gnome.org/browse/gnome-settings-daemon/tree/plugins/xsettings/gsd-xsettings-manager.c * http://git.gnome.org/browse/gnome-settings-daemon/tree/plugins/xsettings/gsd-xsettings-manager.c
@@ -57,6 +55,7 @@ struct _MetaMonitorManagerXrandr
Display *xdisplay; Display *xdisplay;
XRRScreenResources *resources; XRRScreenResources *resources;
int time;
int rr_event_base; int rr_event_base;
int rr_error_base; int rr_error_base;
}; };
@@ -68,31 +67,31 @@ struct _MetaMonitorManagerXrandrClass
G_DEFINE_TYPE (MetaMonitorManagerXrandr, meta_monitor_manager_xrandr, META_TYPE_MONITOR_MANAGER); G_DEFINE_TYPE (MetaMonitorManagerXrandr, meta_monitor_manager_xrandr, META_TYPE_MONITOR_MANAGER);
static MetaMonitorTransform static enum wl_output_transform
meta_monitor_transform_from_xrandr (Rotation rotation) wl_transform_from_xrandr (Rotation rotation)
{ {
static const MetaMonitorTransform y_reflected_map[4] = { static const enum wl_output_transform y_reflected_map[4] = {
META_MONITOR_TRANSFORM_FLIPPED_180, WL_OUTPUT_TRANSFORM_FLIPPED_180,
META_MONITOR_TRANSFORM_FLIPPED_90, WL_OUTPUT_TRANSFORM_FLIPPED_90,
META_MONITOR_TRANSFORM_FLIPPED, WL_OUTPUT_TRANSFORM_FLIPPED,
META_MONITOR_TRANSFORM_FLIPPED_270 WL_OUTPUT_TRANSFORM_FLIPPED_270
}; };
MetaMonitorTransform ret; enum wl_output_transform ret;
switch (rotation & 0x7F) switch (rotation & 0x7F)
{ {
default: default:
case RR_Rotate_0: case RR_Rotate_0:
ret = META_MONITOR_TRANSFORM_NORMAL; ret = WL_OUTPUT_TRANSFORM_NORMAL;
break; break;
case RR_Rotate_90: case RR_Rotate_90:
ret = META_MONITOR_TRANSFORM_90; ret = WL_OUTPUT_TRANSFORM_90;
break; break;
case RR_Rotate_180: case RR_Rotate_180:
ret = META_MONITOR_TRANSFORM_180; ret = WL_OUTPUT_TRANSFORM_180;
break; break;
case RR_Rotate_270: case RR_Rotate_270:
ret = META_MONITOR_TRANSFORM_270; ret = WL_OUTPUT_TRANSFORM_270;
break; break;
} }
@@ -106,126 +105,67 @@ meta_monitor_transform_from_xrandr (Rotation rotation)
#define ALL_ROTATIONS (RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270) #define ALL_ROTATIONS (RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270)
static MetaMonitorTransform static unsigned int
meta_monitor_transform_from_xrandr_all (Rotation rotation) wl_transform_from_xrandr_all (Rotation rotation)
{ {
unsigned ret; unsigned ret;
/* Handle the common cases first (none or all) */ /* Handle the common cases first (none or all) */
if (rotation == 0 || rotation == RR_Rotate_0) 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 */ /* All rotations and one reflection -> all of them by composition */
if ((rotation & ALL_ROTATIONS) && if ((rotation & ALL_ROTATIONS) &&
((rotation & RR_Reflect_X) || (rotation & RR_Reflect_Y))) ((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) if (rotation & RR_Rotate_90)
ret |= 1 << META_MONITOR_TRANSFORM_90; ret |= 1 << WL_OUTPUT_TRANSFORM_90;
if (rotation & RR_Rotate_180) if (rotation & RR_Rotate_180)
ret |= 1 << META_MONITOR_TRANSFORM_180; ret |= 1 << WL_OUTPUT_TRANSFORM_180;
if (rotation & RR_Rotate_270) 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)) 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)) 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)) 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)) if (rotation & (RR_Rotate_270 | RR_Reflect_X))
ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED_270; ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_270;
return ret; return ret;
} }
static gboolean static gboolean
output_get_integer_property (MetaMonitorManagerXrandr *manager_xrandr, output_get_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output, const char *propname, MetaOutput *output)
gint *value)
{ {
gboolean exists = FALSE; gboolean value;
Atom atom, actual_type; Atom atom, actual_type;
int actual_format; int actual_format;
unsigned long nitems, bytes_after; unsigned long nitems, bytes_after;
unsigned char *buffer; unsigned char *buffer;
atom = XInternAtom (manager_xrandr->xdisplay, propname, False); atom = XInternAtom (manager_xrandr->xdisplay, "_MUTTER_PRESENTATION_OUTPUT", False);
XRRGetOutputProperty (manager_xrandr->xdisplay, XRRGetOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id, (XID)output->output_id,
atom,
0, G_MAXLONG, False, False, XA_INTEGER,
&actual_type, &actual_format,
&nitems, &bytes_after, &buffer);
exists = (actual_type == XA_INTEGER && actual_format == 32 && nitems == 1);
if (exists && value != NULL)
*value = ((int*)buffer)[0];
XFree (buffer);
return exists;
}
static gboolean
output_get_property_exists (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output, const char *propname)
{
gboolean exists = FALSE;
Atom atom, actual_type;
int actual_format;
unsigned long nitems, bytes_after;
unsigned char *buffer;
atom = XInternAtom (manager_xrandr->xdisplay, propname, False);
XRRGetOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id,
atom,
0, G_MAXLONG, False, False, AnyPropertyType,
&actual_type, &actual_format,
&nitems, &bytes_after, &buffer);
exists = (actual_type != None);
XFree (buffer);
return exists;
}
static gboolean
output_get_boolean_property (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output, const char *propname)
{
gboolean value = FALSE;
Atom atom, actual_type;
int actual_format;
unsigned long nitems, bytes_after;
unsigned char *buffer;
atom = XInternAtom (manager_xrandr->xdisplay, propname, False);
XRRGetOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id,
atom, atom,
0, G_MAXLONG, False, False, XA_CARDINAL, 0, G_MAXLONG, False, False, XA_CARDINAL,
&actual_type, &actual_format, &actual_type, &actual_format,
&nitems, &bytes_after, &buffer); &nitems, &bytes_after, &buffer);
if (actual_type != XA_CARDINAL || actual_format != 32 || nitems < 1) if (actual_type != XA_CARDINAL || actual_format != 32 ||
goto out; nitems < 1)
return FALSE;
value = ((int*)buffer)[0]; value = ((int*)buffer)[0];
out:
XFree (buffer); XFree (buffer);
return value; return value;
} }
static gboolean
output_get_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output)
{
return output_get_boolean_property (manager_xrandr, output, "_MUTTER_PRESENTATION_OUTPUT");
}
static int static int
normalize_backlight (MetaOutput *output, normalize_backlight (MetaOutput *output,
int hw_value) int hw_value)
@@ -238,7 +178,7 @@ static int
output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr, output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output) MetaOutput *output)
{ {
int value = -1; gboolean value;
Atom atom, actual_type; Atom atom, actual_type;
int actual_format; int actual_format;
unsigned long nitems, bytes_after; unsigned long nitems, bytes_after;
@@ -246,23 +186,20 @@ output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False); atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
XRRGetOutputProperty (manager_xrandr->xdisplay, XRRGetOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id, (XID)output->output_id,
atom, atom,
0, G_MAXLONG, False, False, XA_INTEGER, 0, G_MAXLONG, False, False, XA_INTEGER,
&actual_type, &actual_format, &actual_type, &actual_format,
&nitems, &bytes_after, &buffer); &nitems, &bytes_after, &buffer);
if (actual_type != XA_INTEGER || actual_format != 32 || nitems < 1) if (actual_type != XA_INTEGER || actual_format != 32 ||
goto out; nitems < 1)
return -1;
value = ((int*)buffer)[0]; value = ((int*)buffer)[0];
out:
XFree (buffer); XFree (buffer);
if (value > 0) return normalize_backlight (output, value);
return normalize_backlight (output, value);
else
return -1;
} }
static void static void
@@ -270,34 +207,30 @@ output_get_backlight_limits_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output) MetaOutput *output)
{ {
Atom atom; Atom atom;
xcb_connection_t *xcb_conn; XRRPropertyInfo *info;
xcb_randr_query_output_property_reply_t *reply;
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False); atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
info = XRRQueryOutputProperty (manager_xrandr->xdisplay,
(XID)output->output_id,
atom);
xcb_conn = XGetXCBConnection (manager_xrandr->xdisplay); if (info == NULL)
reply = xcb_randr_query_output_property_reply (xcb_conn, {
xcb_randr_query_output_property (xcb_conn, meta_verbose ("could not get output property for %s\n", output->name);
(xcb_randr_output_t) output->winsys_id, return;
(xcb_atom_t) atom), }
NULL);
/* This can happen on systems without backlights. */ if (!info->range || info->num_values != 2)
if (reply == NULL)
return;
if (!reply->range || reply->length != 2)
{ {
meta_verbose ("backlight %s was not range\n", output->name); meta_verbose ("backlight %s was not range\n", output->name);
goto out; goto out;
} }
int32_t *values = xcb_randr_query_output_property_valid_values (reply); output->backlight_min = info->values[0];
output->backlight_min = values[0]; output->backlight_max = info->values[1];
output->backlight_max = values[1];
out: out:
free (reply); XFree (info);
} }
static int static int
@@ -345,25 +278,25 @@ get_edid_property (Display *dpy,
static GBytes * static GBytes *
read_output_edid (MetaMonitorManagerXrandr *manager_xrandr, read_output_edid (MetaMonitorManagerXrandr *manager_xrandr,
XID winsys_id) XID output_id)
{ {
Atom edid_atom; Atom edid_atom;
guint8 *result; guint8 *result;
gsize len; gsize len;
edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID", FALSE); 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) if (!result)
{ {
edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID_DATA", FALSE); 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) if (!result)
{ {
edid_atom = XInternAtom (manager_xrandr->xdisplay, "XFree86_DDC_EDID1_RAWDATA", FALSE); 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) if (result)
@@ -379,48 +312,26 @@ read_output_edid (MetaMonitorManagerXrandr *manager_xrandr,
static gboolean static gboolean
output_get_hotplug_mode_update (MetaMonitorManagerXrandr *manager_xrandr, output_get_hotplug_mode_update (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output) XID output_id)
{ {
return output_get_property_exists (manager_xrandr, output, "hotplug_mode_update"); Atom atom;
} XRRPropertyInfo *info;
gboolean result = FALSE;
static gint atom = XInternAtom (manager_xrandr->xdisplay, "hotplug_mode_update", False);
output_get_suggested_x (MetaMonitorManagerXrandr *manager_xrandr, info = XRRQueryOutputProperty (manager_xrandr->xdisplay, output_id,
MetaOutput *output) atom);
{
gint val;
if (output_get_integer_property (manager_xrandr, output, "suggested X", &val))
return val;
return -1; if (info)
}
static gint
output_get_suggested_y (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output)
{
gint val;
if (output_get_integer_property (manager_xrandr, output, "suggested Y", &val))
return val;
return -1;
}
static char *
get_xmode_name (XRRModeInfo *xmode)
{
int width = xmode->width;
int height = xmode->height;
if (xmode->hSkew != 0)
{ {
width += 2 * (xmode->hSkew >> 8); result = TRUE;
height += 2 * (xmode->hSkew & 0xff); XFree (info);
} }
return g_strdup_printf ("%dx%d", width, height); return result;
} }
static void static void
meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager) meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
{ {
@@ -486,6 +397,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
return; return;
manager_xrandr->resources = resources; manager_xrandr->resources = resources;
manager_xrandr->time = resources->configTimestamp;
manager->n_outputs = resources->noutput; manager->n_outputs = resources->noutput;
manager->n_crtcs = resources->ncrtc; manager->n_crtcs = resources->ncrtc;
manager->n_modes = resources->nmode; manager->n_modes = resources->nmode;
@@ -505,7 +417,6 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
mode->height = xmode->height; mode->height = xmode->height;
mode->refresh_rate = (xmode->dotClock / mode->refresh_rate = (xmode->dotClock /
((float)xmode->hTotal * xmode->vTotal)); ((float)xmode->hTotal * xmode->vTotal));
mode->name = get_xmode_name (xmode);
} }
for (i = 0; i < (unsigned)resources->ncrtc; i++) for (i = 0; i < (unsigned)resources->ncrtc; i++)
@@ -523,8 +434,8 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
meta_crtc->rect.width = crtc->width; meta_crtc->rect.width = crtc->width;
meta_crtc->rect.height = crtc->height; meta_crtc->rect.height = crtc->height;
meta_crtc->is_dirty = FALSE; meta_crtc->is_dirty = FALSE;
meta_crtc->transform = meta_monitor_transform_from_xrandr (crtc->rotation); meta_crtc->transform = wl_transform_from_xrandr (crtc->rotation);
meta_crtc->all_transforms = meta_monitor_transform_from_xrandr_all (crtc->rotations); meta_crtc->all_transforms = wl_transform_from_xrandr_all (crtc->rotations);
for (j = 0; j < (unsigned)resources->nmode; j++) for (j = 0; j < (unsigned)resources->nmode; j++)
{ {
@@ -556,10 +467,10 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
GBytes *edid; GBytes *edid;
MonitorInfo *parsed_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); 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) if (edid)
{ {
gsize len; gsize len;
@@ -592,9 +503,8 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
meta_output->width_mm = output->mm_width; meta_output->width_mm = output->mm_width;
meta_output->height_mm = output->mm_height; meta_output->height_mm = output->mm_height;
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN; meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
meta_output->hotplug_mode_update = output_get_hotplug_mode_update (manager_xrandr, meta_output); meta_output->hotplug_mode_update =
meta_output->suggested_x = output_get_suggested_x (manager_xrandr, meta_output); output_get_hotplug_mode_update (manager_xrandr, meta_output->output_id);
meta_output->suggested_y = output_get_suggested_y (manager_xrandr, meta_output);
meta_output->n_modes = output->nmode; meta_output->n_modes = output->nmode;
meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes); meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
@@ -646,7 +556,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
meta_output->possible_clones[j] = GINT_TO_POINTER (output->clones[j]); 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); meta_output->is_presentation = output_get_presentation_xrandr (manager_xrandr, meta_output);
output_get_backlight_limits_xrandr (manager_xrandr, meta_output); output_get_backlight_limits_xrandr (manager_xrandr, meta_output);
@@ -679,7 +589,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
for (k = 0; k < manager->n_outputs; k++) 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]; meta_output->possible_clones[j] = &manager->outputs[k];
break; break;
@@ -695,7 +605,7 @@ meta_monitor_manager_xrandr_read_edid (MetaMonitorManager *manager,
{ {
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (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 static void
@@ -727,25 +637,25 @@ meta_monitor_manager_xrandr_set_power_save_mode (MetaMonitorManager *manager,
} }
static Rotation static Rotation
meta_monitor_transform_to_xrandr (MetaMonitorTransform transform) wl_transform_to_xrandr (enum wl_output_transform transform)
{ {
switch (transform) switch (transform)
{ {
case META_MONITOR_TRANSFORM_NORMAL: case WL_OUTPUT_TRANSFORM_NORMAL:
return RR_Rotate_0; return RR_Rotate_0;
case META_MONITOR_TRANSFORM_90: case WL_OUTPUT_TRANSFORM_90:
return RR_Rotate_90; return RR_Rotate_90;
case META_MONITOR_TRANSFORM_180: case WL_OUTPUT_TRANSFORM_180:
return RR_Rotate_180; return RR_Rotate_180;
case META_MONITOR_TRANSFORM_270: case WL_OUTPUT_TRANSFORM_270:
return RR_Rotate_270; return RR_Rotate_270;
case META_MONITOR_TRANSFORM_FLIPPED: case WL_OUTPUT_TRANSFORM_FLIPPED:
return RR_Reflect_X | RR_Rotate_0; 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; 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; 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; return RR_Reflect_X | RR_Rotate_270;
} }
@@ -762,7 +672,7 @@ output_set_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
atom = XInternAtom (manager_xrandr->xdisplay, "_MUTTER_PRESENTATION_OUTPUT", False); atom = XInternAtom (manager_xrandr->xdisplay, "_MUTTER_PRESENTATION_OUTPUT", False);
XRRChangeOutputProperty (manager_xrandr->xdisplay, XRRChangeOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id, (XID)output->output_id,
atom, atom,
XA_CARDINAL, 32, PropModeReplace, XA_CARDINAL, 32, PropModeReplace,
(unsigned char*) &value, 1); (unsigned char*) &value, 1);
@@ -821,7 +731,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
XRRSetCrtcConfig (manager_xrandr->xdisplay, XRRSetCrtcConfig (manager_xrandr->xdisplay,
manager_xrandr->resources, manager_xrandr->resources,
(XID)crtc->crtc_id, (XID)crtc->crtc_id,
CurrentTime, manager_xrandr->time,
0, 0, 0, 0,
None, None,
RR_Rotate_0, RR_Rotate_0,
@@ -851,7 +761,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
XRRSetCrtcConfig (manager_xrandr->xdisplay, XRRSetCrtcConfig (manager_xrandr->xdisplay,
manager_xrandr->resources, manager_xrandr->resources,
(XID)crtc->crtc_id, (XID)crtc->crtc_id,
CurrentTime, manager_xrandr->time,
0, 0, 0, 0,
None, None,
RR_Rotate_0, RR_Rotate_0,
@@ -918,7 +828,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
output->crtc = crtc; output->crtc = crtc;
new_controlled_mask |= 1UL << j; new_controlled_mask |= 1UL << j;
outputs[j] = output->winsys_id; outputs[j] = output->output_id;
} }
if (crtc->current_mode == mode && if (crtc->current_mode == mode &&
@@ -934,10 +844,10 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
ok = XRRSetCrtcConfig (manager_xrandr->xdisplay, ok = XRRSetCrtcConfig (manager_xrandr->xdisplay,
manager_xrandr->resources, manager_xrandr->resources,
(XID)crtc->crtc_id, (XID)crtc->crtc_id,
CurrentTime, manager_xrandr->time,
crtc_info->x, crtc_info->y, crtc_info->x, crtc_info->y,
(XID)mode->mode_id, (XID)mode->mode_id,
meta_monitor_transform_to_xrandr (crtc_info->transform), wl_transform_to_xrandr (crtc_info->transform),
outputs, n_outputs); outputs, n_outputs);
if (ok != Success) if (ok != Success)
@@ -981,7 +891,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
{ {
XRRSetOutputPrimary (manager_xrandr->xdisplay, XRRSetOutputPrimary (manager_xrandr->xdisplay,
DefaultRootWindow (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, output_set_presentation_xrandr (manager_xrandr,
@@ -1024,7 +934,7 @@ meta_monitor_manager_xrandr_change_backlight (MetaMonitorManager *manager,
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False); atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
XRRChangeOutputProperty (manager_xrandr->xdisplay, XRRChangeOutputProperty (manager_xrandr->xdisplay,
(XID)output->winsys_id, (XID)output->output_id,
atom, atom,
XA_INTEGER, 32, PropModeReplace, XA_INTEGER, 32, PropModeReplace,
(unsigned char *) &hw_value, 1); (unsigned char *) &hw_value, 1);
@@ -1075,6 +985,16 @@ meta_monitor_manager_xrandr_set_crtc_gamma (MetaMonitorManager *manager,
XRRFreeGamma (gamma); XRRFreeGamma (gamma);
} }
static void
meta_monitor_manager_xrandr_rebuild_derived (MetaMonitorManager *manager)
{
/* This will be a no-op if the change was from our side, as
we already called it in the DBus method handler */
meta_monitor_config_update_current (manager->config, manager);
meta_monitor_manager_rebuild_derived (manager);
}
static void static void
meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr) meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr)
{ {
@@ -1134,30 +1054,63 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra
XEvent *event) XEvent *event)
{ {
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr); MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr);
gboolean hotplug; MetaOutput *old_outputs;
Time old_timestamp; MetaCRTC *old_crtcs;
MetaMonitorMode *old_modes;
unsigned int n_old_outputs, n_old_modes;
gboolean new_config;
if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify) if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify)
return FALSE; return FALSE;
XRRUpdateConfiguration (event); XRRUpdateConfiguration (event);
old_timestamp = manager_xrandr->resources->timestamp; /* Save the old structures, so they stay valid during the update */
old_outputs = manager->outputs;
n_old_outputs = manager->n_outputs;
old_modes = manager->modes;
n_old_modes = manager->n_modes;
old_crtcs = manager->crtcs;
meta_monitor_manager_read_current_config (manager); manager->serial++;
meta_monitor_manager_xrandr_read_current (manager);
new_config = manager_xrandr->resources->timestamp >=
manager_xrandr->resources->configTimestamp;
if (meta_monitor_manager_has_hotplug_mode_update (manager))
hotplug = manager_xrandr->resources->timestamp < manager_xrandr->resources->configTimestamp;
if (hotplug)
{ {
/* This is a hotplug event, so go ahead and build a new configuration. */ /* Check if the current intended configuration is a result of an
meta_monitor_manager_on_hotplug (manager); XRandR call. Otherwise, hotplug_mode_update tells us to get
a new preferred mode on hotplug events to handle dynamic
guest resizing. */
if (new_config)
meta_monitor_manager_xrandr_rebuild_derived (manager);
else
meta_monitor_config_make_default (manager->config, manager);
} }
else else
{ {
/* If something else changed -- tell the world about it. */ /* Check if the current intended configuration has the same outputs
if (old_timestamp < manager_xrandr->resources->timestamp) as the new real one, or if the event is a result of an XRandR call.
meta_monitor_manager_rebuild_derived (manager); If so, we can go straight to rebuild the logical config and tell
the outside world.
Otherwise, this event was caused by hotplug, so give a chance to
MetaMonitorConfig.
Note that we need to check both the timestamps and the list of
outputs, because the X server might emit spurious events with new
configTimestamps (bug 702804), and the driver may have changed
the EDID for some other reason (old qxl and vbox drivers). */
if (new_config || meta_monitor_config_match_current (manager->config, manager))
meta_monitor_manager_xrandr_rebuild_derived (manager);
else if (!meta_monitor_config_apply_stored (manager->config, manager))
meta_monitor_config_make_default (manager->config, manager);
} }
meta_monitor_manager_free_output_array (old_outputs, n_old_outputs);
meta_monitor_manager_free_mode_array (old_modes, n_old_modes);
g_free (old_crtcs);
return TRUE; return TRUE;
} }

View File

@@ -51,12 +51,6 @@ round_to_fixed (float x)
return roundf (x * 256); return roundf (x * 256);
} }
/* Help macros to scale from OpenGL <-1,1> coordinates system to
* window coordinates ranging [0,window-size]. Borrowed from clutter-utils.c
*/
#define MTX_GL_SCALE_X(x,w,v1,v2) ((((((x) / (w)) + 1.0f) / 2.0f) * (v1)) + (v2))
#define MTX_GL_SCALE_Y(y,w,v1,v2) ((v1) - (((((y) / (w)) + 1.0f) / 2.0f) * (v1)) + (v2))
/* This helper function checks if (according to our fixed point precision) /* This helper function checks if (according to our fixed point precision)
* the vertices @verts form a box of width @widthf and height @heightf * the vertices @verts form a box of width @widthf and height @heightf
* located at integral coordinates. These coordinates are returned * located at integral coordinates. These coordinates are returned
@@ -124,67 +118,3 @@ meta_actor_is_untransformed (ClutterActor *actor,
return meta_actor_vertices_are_untransformed (verts, widthf, heightf, x_origin, y_origin); return meta_actor_vertices_are_untransformed (verts, widthf, heightf, x_origin, y_origin);
} }
/**
* meta_actor_painting_untransformed:
* @paint_width: the width of the painted area
* @paint_height: the height of the painted area
* @x_origin: if the transform is only an integer translation
* then the X coordinate of the location of the origin under the transformation
* from drawing space to screen pixel space is returned here.
* @y_origin: if the transform is only an integer translation
* then the X coordinate of the location of the origin under the transformation
* from drawing space to screen pixel space is returned here.
*
* Determines if the current painting transform is an integer translation.
* This can differ from the result of meta_actor_is_untransformed() when
* painting an actor if we're inside a inside a clone paint. @paint_width
* and @paint_height are used to determine the vertices of the rectangle
* we check to see if the painted area is "close enough" to the integer
* transform.
*/
gboolean
meta_actor_painting_untransformed (int paint_width,
int paint_height,
int *x_origin,
int *y_origin)
{
CoglMatrix modelview, projection, modelview_projection;
ClutterVertex vertices[4];
float viewport[4];
int i;
cogl_get_modelview_matrix (&modelview);
cogl_get_projection_matrix (&projection);
cogl_matrix_multiply (&modelview_projection,
&projection,
&modelview);
vertices[0].x = 0;
vertices[0].y = 0;
vertices[0].z = 0;
vertices[1].x = paint_width;
vertices[1].y = 0;
vertices[1].z = 0;
vertices[2].x = 0;
vertices[2].y = paint_height;
vertices[2].z = 0;
vertices[3].x = paint_width;
vertices[3].y = paint_height;
vertices[3].z = 0;
cogl_get_viewport (viewport);
for (i = 0; i < 4; i++)
{
float w = 1;
cogl_matrix_transform_point (&modelview_projection, &vertices[i].x, &vertices[i].y, &vertices[i].z, &w);
vertices[i].x = MTX_GL_SCALE_X (vertices[i].x, w,
viewport[2], viewport[0]);
vertices[i].y = MTX_GL_SCALE_Y (vertices[i].y, w,
viewport[3], viewport[1]);
}
return meta_actor_vertices_are_untransformed (vertices, paint_width, paint_height, x_origin, y_origin);
}

View File

@@ -31,9 +31,4 @@ gboolean meta_actor_is_untransformed (ClutterActor *actor,
int *x_origin, int *x_origin,
int *y_origin); int *y_origin);
gboolean meta_actor_painting_untransformed (int paint_width,
int paint_height,
int *x_origin,
int *y_origin);
#endif /* __META_CLUTTER_UTILS_H__ */ #endif /* __META_CLUTTER_UTILS_H__ */

View File

@@ -22,6 +22,48 @@
#include <clutter/clutter.h> #include <clutter/clutter.h>
#include "cogl-utils.h" #include "cogl-utils.h"
/**
* meta_create_color_texture_4ub:
* @red: red component
* @green: green component
* @blue: blue component
* @alpha: alpha component
* @flags: Optional flags for the texture, or %COGL_TEXTURE_NONE;
* %COGL_TEXTURE_NO_SLICING is useful if the texture will be
* repeated to create a constant color fill, since hardware
* repeat can't be used for a sliced texture.
*
* Creates a texture that is a single pixel with the specified
* unpremultiplied color components.
*
* Return value: (transfer full): a newly created Cogl texture
*/
CoglTexture *
meta_create_color_texture_4ub (guint8 red,
guint8 green,
guint8 blue,
guint8 alpha,
CoglTextureFlags flags)
{
CoglColor color;
guint8 pixel[4];
cogl_color_init_from_4ub (&color, red, green, blue, alpha);
cogl_color_premultiply (&color);
pixel[0] = cogl_color_get_red_byte (&color);
pixel[1] = cogl_color_get_green_byte (&color);
pixel[2] = cogl_color_get_blue_byte (&color);
pixel[3] = cogl_color_get_alpha_byte (&color);
return cogl_texture_new_from_data (1, 1,
flags,
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
COGL_PIXEL_FORMAT_ANY,
4, pixel);
}
/* Based on gnome-shell/src/st/st-private.c:_st_create_texture_material.c */ /* Based on gnome-shell/src/st/st-private.c:_st_create_texture_material.c */
/** /**
@@ -64,78 +106,3 @@ meta_create_texture_pipeline (CoglTexture *src_texture)
return pipeline; return pipeline;
} }
static gboolean is_pot(int x)
{
return x > 0 && (x & (x - 1)) == 0;
}
/**
* meta_create_texture:
* @width: width of the texture to create
* @height: height of the texture to create
* @components; components to store in the texture (color or alpha)
* @flags: flags that affect the allocation behavior
*
* Creates a texture of the given size with the specified components
* for use as a frame buffer object.
*
* If non-power-of-two textures are not supported on the system, then
* the texture will be created as a texture rectangle; in this case,
* hardware repeating isn't possible, and texture coordinates are also
* different, but Cogl hides these issues from the application, except from
* GLSL shaders. Since GLSL is never (or at least almost never)
* present on such a system, this is not typically an issue.
*
* If %META_TEXTURE_ALLOW_SLICING is present in @flags, and the texture
* is larger than the texture size limits of the system, then the texture
* will be created as a sliced texture. This also will cause problems
* with using the texture with GLSL, and is more likely to be an issue
* since all GL implementations have texture size limits, and they can
* be as small as 2048x2048 on reasonably current systems.
*/
CoglTexture *
meta_create_texture (int width,
int height,
CoglTextureComponents components,
MetaTextureFlags flags)
{
ClutterBackend *backend = clutter_get_default_backend ();
CoglContext *ctx = clutter_backend_get_cogl_context (backend);
CoglTexture *texture;
gboolean should_use_rectangle = FALSE;
if (!(is_pot (width) && is_pot (height)) &&
!cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT))
{
if (cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_RECTANGLE))
should_use_rectangle = TRUE;
else
g_error ("Cannot create texture. Support for GL_ARB_texture_non_power_of_two or "
"ARB_texture_rectangle is required");
}
if (should_use_rectangle)
texture = COGL_TEXTURE (cogl_texture_rectangle_new_with_size (ctx, width, height));
else
texture = COGL_TEXTURE (cogl_texture_2d_new_with_size (ctx, width, height));
cogl_texture_set_components (texture, components);
if ((flags & META_TEXTURE_ALLOW_SLICING) != 0)
{
/* To find out if we need to slice the texture, we have to go ahead and force storage
* to be allocated
*/
CoglError *catch_error = NULL;
if (!cogl_texture_allocate (texture, &catch_error))
{
cogl_error_free (catch_error);
cogl_object_unref (texture);
texture = COGL_TEXTURE (cogl_texture_2d_sliced_new_with_size (ctx, width, height, COGL_TEXTURE_MAX_WASTE));
cogl_texture_set_components (texture, components);
}
}
return texture;
}

View File

@@ -23,16 +23,11 @@
#include <cogl/cogl.h> #include <cogl/cogl.h>
CoglTexture * meta_create_color_texture_4ub (guint8 red,
guint8 green,
guint8 blue,
guint8 alpha,
CoglTextureFlags flags);
CoglPipeline * meta_create_texture_pipeline (CoglTexture *texture); CoglPipeline * meta_create_texture_pipeline (CoglTexture *texture);
typedef enum {
META_TEXTURE_FLAGS_NONE = 0,
META_TEXTURE_ALLOW_SLICING = 1 << 1
} MetaTextureFlags;
CoglTexture *meta_create_texture (int width,
int height,
CoglTextureComponents components,
MetaTextureFlags flags);
#endif /* __META_COGL_UTILS_H__ */ #endif /* __META_COGL_UTILS_H__ */

View File

@@ -15,7 +15,8 @@ struct _MetaCompositor
{ {
MetaDisplay *display; MetaDisplay *display;
guint repaint_func_id; guint pre_paint_func_id;
guint post_paint_func_id;
gint64 server_time_query_time; gint64 server_time_query_time;
gint64 server_time_offset; gint64 server_time_offset;
@@ -23,7 +24,7 @@ struct _MetaCompositor
guint server_time_is_monotonic_time : 1; guint server_time_is_monotonic_time : 1;
guint no_mipmaps : 1; guint no_mipmaps : 1;
ClutterActor *stage, *window_group, *top_window_group, *feedback_group; ClutterActor *stage, *window_group, *top_window_group;
ClutterActor *background_actor; ClutterActor *background_actor;
GList *windows; GList *windows;
Window output; Window output;
@@ -40,6 +41,7 @@ struct _MetaCompositor
MetaPluginManager *plugin_mgr; MetaPluginManager *plugin_mgr;
gboolean frame_has_updated_xsurfaces; gboolean frame_has_updated_xsurfaces;
gboolean have_x11_sync_object;
}; };
/* Wait 2ms after vblank before starting to draw next frame */ /* Wait 2ms after vblank before starting to draw next frame */

View File

@@ -67,29 +67,41 @@
#include <meta/compositor-mutter.h> #include <meta/compositor-mutter.h>
#include <meta/prefs.h> #include <meta/prefs.h>
#include <meta/main.h> #include <meta/main.h>
#include <meta/meta-backend.h>
#include <meta/meta-background-actor.h> #include <meta/meta-background-actor.h>
#include <meta/meta-background-group.h> #include <meta/meta-background-group.h>
#include <meta/meta-shadow-factory.h> #include <meta/meta-shadow-factory.h>
#include "meta-window-actor-private.h" #include "meta-window-actor-private.h"
#include "meta-window-group.h" #include "meta-window-group.h"
#include "meta-stage.h"
#include "window-private.h" /* to check window->hidden */ #include "window-private.h" /* to check window->hidden */
#include "display-private.h" /* for meta_display_lookup_x_window() and meta_display_cancel_touch() */ #include "display-private.h" /* for meta_display_lookup_x_window() */
#include "util-private.h" #include "util-private.h"
#include "frame.h" #include "frame.h"
#include <X11/extensions/shape.h> #include <X11/extensions/shape.h>
#include <X11/extensions/Xcomposite.h> #include <X11/extensions/Xcomposite.h>
#include "meta-sync-ring.h"
#include "backends/meta-backend.h"
#include "backends/x11/meta-backend-x11.h" #include "backends/x11/meta-backend-x11.h"
#ifdef HAVE_WAYLAND
#include "wayland/meta-wayland-private.h" #include "wayland/meta-wayland-private.h"
#endif
static gboolean static gboolean
is_modal (MetaDisplay *display) is_modal (MetaDisplay *display)
{ {
return display->event_route == META_EVENT_ROUTE_COMPOSITOR_GRAB; return display->grab_op == META_GRAB_OP_COMPOSITOR;
}
static inline gboolean
composite_at_least_version (MetaDisplay *display, int maj, int min)
{
static int major = -1;
static int minor = -1;
if (major == -1)
meta_display_get_compositor_version (display, &major, &minor);
return (major > maj || (major == maj && minor >= min));
} }
static void sync_actor_stacking (MetaCompositor *compositor); static void sync_actor_stacking (MetaCompositor *compositor);
@@ -125,7 +137,11 @@ meta_switch_workspace_completed (MetaCompositor *compositor)
void void
meta_compositor_destroy (MetaCompositor *compositor) 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 static void
@@ -139,6 +155,33 @@ process_damage (MetaCompositor *compositor,
compositor->frame_has_updated_xsurfaces = TRUE; 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 */ /* compat helper */
static MetaCompositor * static MetaCompositor *
get_compositor_for_screen (MetaScreen *screen) get_compositor_for_screen (MetaScreen *screen)
@@ -185,19 +228,6 @@ meta_get_top_window_group_for_screen (MetaScreen *screen)
return compositor->top_window_group; return compositor->top_window_group;
} }
/**
* meta_get_feedback_group_for_screen:
* @screen: a #MetaScreen
*
* Returns: (transfer none): The feedback group corresponding to @screen
*/
ClutterActor *
meta_get_feedback_group_for_screen (MetaScreen *screen)
{
MetaCompositor *compositor = get_compositor_for_screen (screen);
return compositor->feedback_group;
}
/** /**
* meta_get_window_actors: * meta_get_window_actors:
* @screen: a #MetaScreen * @screen: a #MetaScreen
@@ -358,20 +388,12 @@ meta_begin_modal_for_plugin (MetaCompositor *compositor,
return FALSE; return FALSE;
display->grab_op = META_GRAB_OP_COMPOSITOR; display->grab_op = META_GRAB_OP_COMPOSITOR;
display->event_route = META_EVENT_ROUTE_COMPOSITOR_GRAB;
display->grab_window = NULL; display->grab_window = NULL;
display->grab_have_pointer = TRUE; display->grab_have_pointer = TRUE;
display->grab_have_keyboard = 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 ()) if (meta_is_wayland_compositor ())
{ meta_display_sync_wayland_input_focus (display);
meta_display_sync_wayland_input_focus (display);
meta_display_cancel_touch (display);
}
return TRUE; return TRUE;
} }
@@ -386,12 +408,7 @@ meta_end_modal_for_plugin (MetaCompositor *compositor,
g_return_if_fail (is_modal (display)); 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_op = META_GRAB_OP_NONE;
display->event_route = META_EVENT_ROUTE_NORMAL;
display->grab_window = NULL; display->grab_window = NULL;
display->grab_have_pointer = FALSE; display->grab_have_pointer = FALSE;
display->grab_have_keyboard = FALSE; display->grab_have_keyboard = FALSE;
@@ -413,10 +430,8 @@ after_stage_paint (ClutterStage *stage,
for (l = compositor->windows; l; l = l->next) for (l = compositor->windows; l; l = l->next)
meta_window_actor_post_paint (l->data); meta_window_actor_post_paint (l->data);
#ifdef HAVE_WAYLAND
if (meta_is_wayland_compositor ()) if (meta_is_wayland_compositor ())
meta_wayland_compositor_paint_finished (meta_wayland_compositor_get_default ()); meta_wayland_compositor_paint_finished (meta_wayland_compositor_get_default ());
#endif
} }
static void static void
@@ -468,34 +483,70 @@ meta_compositor_manage (MetaCompositor *compositor)
MetaDisplay *display = compositor->display; MetaDisplay *display = compositor->display;
Display *xdisplay = display->xdisplay; Display *xdisplay = display->xdisplay;
MetaScreen *screen = display->screen; MetaScreen *screen = display->screen;
Window xwin = 0;
gint width, height;
meta_screen_set_cm_selection (display->screen); meta_screen_set_cm_selection (display->screen);
{ if (meta_is_wayland_compositor ())
MetaBackend *backend = meta_get_backend (); {
compositor->stage = meta_backend_get_stage (backend); MetaWaylandCompositor *wayland_compositor = meta_wayland_compositor_get_default ();
}
/* We use connect_after() here to accomodate code in GNOME Shell that, compositor->stage = meta_stage_new ();
* when benchmarking drawing performance, connects to ::after-paint clutter_actor_show (compositor->stage);
* and calls glFinish(). The timing information from that will be
* more accurate if we hold off until that completes before we signal wayland_compositor->stage = compositor->stage;
* apps to begin drawing the next frame. If there are no other
* connections to ::after-paint, connect() vs. connect_after() doesn't meta_screen_get_size (screen, &width, &height);
* matter. clutter_actor_set_size (compositor->stage, width, height);
*/ }
g_signal_connect_after (CLUTTER_STAGE (compositor->stage), "after-paint", else
G_CALLBACK (after_stage_paint), compositor); {
compositor->stage = clutter_stage_new ();
meta_screen_get_size (screen, &width, &height);
clutter_actor_realize (compositor->stage);
xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (compositor->stage));
XResizeWindow (xdisplay, xwin, width, height);
{
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 };
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);
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);
XIClearMask (mask.mask, XI_TouchBegin);
XIClearMask (mask.mask, XI_TouchEnd);
XIClearMask (mask.mask, XI_TouchUpdate);
XISelectEvents (backend_xdisplay, xwin, &mask, 1);
}
}
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); clutter_stage_set_sync_delay (CLUTTER_STAGE (compositor->stage), META_SYNC_DELAY);
compositor->window_group = meta_window_group_new (screen); compositor->window_group = meta_window_group_new (screen);
compositor->top_window_group = meta_window_group_new (screen); compositor->top_window_group = meta_window_group_new (screen);
compositor->feedback_group = meta_window_group_new (screen);
clutter_actor_add_child (compositor->stage, compositor->window_group); clutter_actor_add_child (compositor->stage, compositor->window_group);
clutter_actor_add_child (compositor->stage, compositor->top_window_group); clutter_actor_add_child (compositor->stage, compositor->top_window_group);
clutter_actor_add_child (compositor->stage, compositor->feedback_group);
if (meta_is_wayland_compositor ()) if (meta_is_wayland_compositor ())
{ {
@@ -506,12 +557,7 @@ meta_compositor_manage (MetaCompositor *compositor)
} }
else else
{ {
Window xwin; compositor->output = get_output_window (compositor);
compositor->output = screen->composite_overlay_window;
xwin = meta_backend_x11_get_xwindow (META_BACKEND_X11 (meta_get_backend ()));
XReparentWindow (xdisplay, xwin, compositor->output, 0, 0); XReparentWindow (xdisplay, xwin, compositor->output, 0, 0);
meta_empty_stage_input_region (screen); meta_empty_stage_input_region (screen);
@@ -530,6 +576,8 @@ meta_compositor_manage (MetaCompositor *compositor)
* contents until we show the stage. * contents until we show the stage.
*/ */
XMapWindow (xdisplay, compositor->output); XMapWindow (xdisplay, compositor->output);
compositor->have_x11_sync_object = meta_sync_ring_init (display);
} }
redirect_windows (display->screen); redirect_windows (display->screen);
@@ -652,11 +700,12 @@ meta_compositor_remove_window (MetaCompositor *compositor,
} }
void void
meta_compositor_sync_updates_frozen (MetaCompositor *compositor, meta_compositor_set_updates_frozen (MetaCompositor *compositor,
MetaWindow *window) MetaWindow *window,
gboolean updates_frozen)
{ {
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window)); 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 void
@@ -716,6 +765,9 @@ meta_compositor_process_event (MetaCompositor *compositor,
XEvent *event, XEvent *event,
MetaWindow *window) MetaWindow *window)
{ {
if (meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event))
return TRUE;
if (!meta_is_wayland_compositor () && if (!meta_is_wayland_compositor () &&
event->type == meta_display_get_damage_event_base (compositor->display) + XDamageNotify) event->type == meta_display_get_damage_event_base (compositor->display) + XDamageNotify)
{ {
@@ -737,6 +789,10 @@ meta_compositor_process_event (MetaCompositor *compositor,
if (!meta_is_wayland_compositor () && event->type == MapNotify) if (!meta_is_wayland_compositor () && event->type == MapNotify)
clutter_x11_handle_event (event); 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 /* 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 * 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. * GTK+ windows in the same process, GTK+ needs the ConfigureNotify event, for example.
@@ -935,7 +991,7 @@ meta_compositor_sync_stack (MetaCompositor *compositor,
old_actor = old_stack->data; old_actor = old_stack->data;
old_window = meta_window_actor_get_meta_window (old_actor); old_window = meta_window_actor_get_meta_window (old_actor);
if ((old_window->hidden || old_window->unmanaging) && if (old_window->hidden &&
!meta_window_actor_effect_in_progress (old_actor)) !meta_window_actor_effect_in_progress (old_actor))
{ {
old_stack = g_list_delete_link (old_stack, old_stack); old_stack = g_list_delete_link (old_stack, old_stack);
@@ -969,7 +1025,7 @@ meta_compositor_sync_stack (MetaCompositor *compositor,
* filtered out non-animating hidden windows above. * filtered out non-animating hidden windows above.
*/ */
if (old_actor && if (old_actor &&
(!stack_actor || old_window->hidden || old_window->unmanaging)) (!stack_actor || old_window->hidden))
{ {
actor = old_actor; actor = old_actor;
window = old_window; window = old_window;
@@ -1003,6 +1059,43 @@ meta_compositor_sync_window_geometry (MetaCompositor *compositor,
meta_window_actor_sync_actor_geometry (window_actor, did_placement); meta_window_actor_sync_actor_geometry (window_actor, did_placement);
} }
void
meta_compositor_sync_screen_size (MetaCompositor *compositor,
guint width,
guint height)
{
MetaDisplay *display = compositor->display;
if (meta_is_wayland_compositor ())
{
/* FIXME: when we support a sliced stage, this is the place to do it
But! This is not the place to apply KMS config, here we only
notify Clutter/Cogl/GL that the framebuffer sizes changed.
And because for now clutter does not do sliced, we use one
framebuffer the size of the whole screen, and when running on
bare metal MetaMonitorManager will do the necessary tricks to
show the right portions on the right screens.
*/
clutter_actor_set_size (compositor->stage, width, height);
}
else
{
Display *xdisplay;
Window xwin;
xdisplay = meta_display_get_xdisplay (display);
xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (compositor->stage));
XResizeWindow (xdisplay, xwin, width, height);
}
meta_verbose ("Changed size for stage on screen %d to %dx%d\n",
meta_screen_get_screen_number (display->screen),
width, height);
}
static void static void
frame_callback (CoglOnscreen *onscreen, frame_callback (CoglOnscreen *onscreen,
CoglFrameEvent event, CoglFrameEvent event,
@@ -1045,11 +1138,12 @@ frame_callback (CoglOnscreen *onscreen,
} }
} }
static void static gboolean
pre_paint_windows (MetaCompositor *compositor) meta_pre_paint_func (gpointer data)
{ {
GList *l; GList *l;
MetaWindowActor *top_window; MetaWindowActor *top_window;
MetaCompositor *compositor = data;
if (compositor->onscreen == NULL) if (compositor->onscreen == NULL)
{ {
@@ -1061,7 +1155,7 @@ pre_paint_windows (MetaCompositor *compositor)
} }
if (compositor->windows == NULL) if (compositor->windows == NULL)
return; return TRUE;
top_window = g_list_last (compositor->windows)->data; top_window = g_list_last (compositor->windows)->data;
@@ -1078,10 +1172,12 @@ pre_paint_windows (MetaCompositor *compositor)
{ {
/* We need to make sure that any X drawing that happens before /* We need to make sure that any X drawing that happens before
* the XDamageSubtract() for each window above is visible to * the XDamageSubtract() for each window above is visible to
* subsequent GL rendering; the only standardized way to do this * subsequent GL rendering; the standardized way to do this is
* is EXT_x11_sync_object, which isn't yet widely available. For * GL_EXT_X11_sync_object. Since this isn't implemented yet in
* now, we count on details of Xorg and the open source drivers, * mesa, we also have a path that relies on the implementation
* and hope for the best otherwise. * of the open source drivers.
*
* Anything else, we just hope for the best.
* *
* Xorg and open source driver specifics: * Xorg and open source driver specifics:
* *
@@ -1096,17 +1192,28 @@ pre_paint_windows (MetaCompositor *compositor)
* round trip request at this point is sufficient to flush the * round trip request at this point is sufficient to flush the
* GLX buffers. * GLX buffers.
*/ */
XSync (compositor->display->xdisplay, False); if (compositor->have_x11_sync_object)
compositor->have_x11_sync_object = meta_sync_ring_insert_wait ();
compositor->frame_has_updated_xsurfaces = FALSE; else
XSync (compositor->display->xdisplay, False);
} }
return TRUE;
} }
static gboolean static gboolean
meta_repaint_func (gpointer data) meta_post_paint_func (gpointer data)
{ {
MetaCompositor *compositor = 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; return TRUE;
} }
@@ -1130,7 +1237,11 @@ meta_compositor_new (MetaDisplay *display)
{ {
MetaCompositor *compositor; MetaCompositor *compositor;
if (!composite_at_least_version (display, 0, 3))
return NULL;
compositor = g_new0 (MetaCompositor, 1); compositor = g_new0 (MetaCompositor, 1);
compositor->display = display; compositor->display = display;
if (g_getenv("META_DISABLE_MIPMAPS")) if (g_getenv("META_DISABLE_MIPMAPS"))
@@ -1141,10 +1252,16 @@ meta_compositor_new (MetaDisplay *display)
G_CALLBACK (on_shadow_factory_changed), G_CALLBACK (on_shadow_factory_changed),
compositor); compositor);
compositor->repaint_func_id = clutter_threads_add_repaint_func (meta_repaint_func, compositor->pre_paint_func_id =
compositor, clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_PRE_PAINT,
NULL); 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; return compositor;
} }
@@ -1309,12 +1426,3 @@ meta_compositor_show_window_menu (MetaCompositor *compositor,
{ {
meta_plugin_manager_show_window_menu (compositor->plugin_mgr, window, menu, x, y); 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

@@ -1,7 +1,7 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* /*
* Copyright 2009 Sander Dijkhuis * Copyright 2009 Sander Dijkhuis
* Copyright 2014 Red Hat, Inc. * Copyright 2010 Red Hat, Inc.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as * modify it under the terms of the GNU General Public License as
@@ -26,122 +26,23 @@
* *
*/ */
/*
* The overall model drawing model of this widget is that we have one
* texture, or two interpolated textures, possibly with alpha or
* margins that let the underlying background show through, blended
* over a solid color or a gradient. The result of that combination
* can then be affected by a "vignette" that darkens the background
* away from a central point (or as a no-GLSL fallback, simply darkens
* the background) and by overall opacity.
*
* As of GNOME 3.14, GNOME is only using a fraction of this when the
* user sets the background through the control center - what can be
* set is:
*
* A single image without a border
* An animation of images without a border that blend together,
* with the blend changing every 4-5 minutes
* A solid color with a repeated noise texture blended over it
*
* This all is pretty easy to do in a fragment shader, except when:
*
* A) We don't have GLSL - in this case, the operation of
* interpolating the two textures and blending the result over the
* background can't be expressed with Cogl's fixed-function layer
* combining (which is confined to what GL's texture environment
* combining can do) So we can only handle the above directly if
* there are no margins or alpha.
*
* B) The image textures are sliced. Texture size limits on older
* hardware (pre-965 intel hardware, r300, etc.) is often 2048,
* and it would be common to use a texture larger than this for a
* background and expect it to be scaled down. Cogl can compensate
* for this by breaking the texture up into multiple textures, but
* can't multitexture with sliced textures. So we can only handle
* the above if there's a single texture.
*
* However, even when we *can* represent everything in a single pass,
* it's not necessarily efficient. If we want to draw a 1024x768
* background, it's pretty inefficient to bilinearly texture from
* two 2560x1440 images and mix that. So the drawing model we take
* here is that MetaBackground generates a single texture (which
* might be a 1x1 texture for a solid color, or a 1x2 texture for a
* gradient, or a repeated texture for wallpaper, or a pre-rendered
* texture the size of the screen), and we draw with that, possibly
* adding the vignette and opacity.
*/
#include <config.h> #include <config.h>
#include <cogl/cogl-texture-pixmap-x11.h>
#include <clutter/clutter.h> #include <clutter/clutter.h>
#include <X11/Xatom.h>
#include "cogl-utils.h" #include "cogl-utils.h"
#include "clutter-utils.h" #include "compositor-private.h"
#include <meta/errors.h> #include <meta/errors.h>
#include <meta/meta-background.h>
#include "meta-background-actor-private.h" #include "meta-background-actor-private.h"
#include "meta-background-private.h"
#include "meta-cullable.h" #include "meta-cullable.h"
enum
{
PROP_META_SCREEN = 1,
PROP_MONITOR,
PROP_BACKGROUND,
PROP_VIGNETTE,
PROP_VIGNETTE_SHARPNESS,
PROP_BRIGHTNESS
};
typedef enum {
CHANGED_BACKGROUND = 1 << 0,
CHANGED_EFFECTS = 1 << 2,
CHANGED_VIGNETTE_PARAMETERS = 1 << 3,
CHANGED_ALL = 0xFFFF
} ChangedFlags;
#define VERTEX_SHADER_DECLARATIONS \
"uniform vec2 scale;\n" \
"uniform vec2 offset;\n" \
"varying vec2 position;\n" \
#define VERTEX_SHADER_CODE \
"position = cogl_tex_coord0_in.xy * scale + offset;\n" \
#define FRAGMENT_SHADER_DECLARATIONS \
"uniform float vignette_sharpness;\n" \
"varying vec2 position;\n" \
#define FRAGMENT_SHADER_CODE \
"float t = 2.0 * length(position);\n" \
"t = min(t, 1.0);\n" \
"float pixel_brightness = 1 - t * vignette_sharpness;\n" \
"cogl_color_out.rgb = cogl_color_out.rgb * pixel_brightness;\n" \
typedef struct _MetaBackgroundLayer MetaBackgroundLayer;
typedef enum {
PIPELINE_VIGNETTE = (1 << 0),
PIPELINE_BLEND = (1 << 1),
} PipelineFlags;
struct _MetaBackgroundActorPrivate struct _MetaBackgroundActorPrivate
{ {
MetaScreen *screen;
int monitor;
MetaBackground *background;
gboolean vignette;
double brightness;
double vignette_sharpness;
ChangedFlags changed;
CoglPipeline *pipeline;
PipelineFlags pipeline_flags;
cairo_rectangle_int_t texture_area;
gboolean force_bilinear;
cairo_region_t *clip_region; cairo_region_t *clip_region;
}; };
@@ -165,45 +66,27 @@ static void
meta_background_actor_dispose (GObject *object) meta_background_actor_dispose (GObject *object)
{ {
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (object); MetaBackgroundActor *self = META_BACKGROUND_ACTOR (object);
MetaBackgroundActorPrivate *priv = self->priv;
set_clip_region (self, NULL); set_clip_region (self, NULL);
meta_background_actor_set_background (self, NULL);
if (priv->pipeline)
{
cogl_object_unref (priv->pipeline);
priv->pipeline = NULL;
}
G_OBJECT_CLASS (meta_background_actor_parent_class)->dispose (object); G_OBJECT_CLASS (meta_background_actor_parent_class)->dispose (object);
} }
static void
get_preferred_size (MetaBackgroundActor *self,
gfloat *width,
gfloat *height)
{
MetaBackgroundActorPrivate *priv = META_BACKGROUND_ACTOR (self)->priv;
MetaRectangle monitor_geometry;
meta_screen_get_monitor_geometry (priv->screen, priv->monitor, &monitor_geometry);
if (width != NULL)
*width = monitor_geometry.width;
if (height != NULL)
*height = monitor_geometry.height;
}
static void static void
meta_background_actor_get_preferred_width (ClutterActor *actor, meta_background_actor_get_preferred_width (ClutterActor *actor,
gfloat for_height, gfloat for_height,
gfloat *min_width_p, gfloat *min_width_p,
gfloat *natural_width_p) gfloat *natural_width_p)
{ {
ClutterContent *content;
gfloat width; gfloat width;
get_preferred_size (META_BACKGROUND_ACTOR (actor), &width, NULL); content = clutter_actor_get_content (actor);
if (content)
clutter_content_get_preferred_size (content, &width, NULL);
else
width = 0;
if (min_width_p) if (min_width_p)
*min_width_p = width; *min_width_p = width;
@@ -218,9 +101,15 @@ meta_background_actor_get_preferred_height (ClutterActor *actor,
gfloat *natural_height_p) gfloat *natural_height_p)
{ {
ClutterContent *content;
gfloat height; gfloat height;
get_preferred_size (META_BACKGROUND_ACTOR (actor), NULL, &height); content = clutter_actor_get_content (actor);
if (content)
clutter_content_get_preferred_size (content, NULL, &height);
else
height = 0;
if (min_height_p) if (min_height_p)
*min_height_p = height; *min_height_p = height;
@@ -228,430 +117,43 @@ meta_background_actor_get_preferred_height (ClutterActor *actor,
*natural_height_p = height; *natural_height_p = height;
} }
static CoglPipeline *
make_pipeline (PipelineFlags pipeline_flags)
{
static CoglPipeline *templates[4];
CoglPipeline **templatep;
templatep = &templates[pipeline_flags];
if (*templatep == NULL)
{
/* Cogl automatically caches pipelines with no eviction policy,
* so we need to prevent identical pipelines from getting cached
* separately, by reusing the same shader snippets.
*/
*templatep = COGL_PIPELINE (meta_create_texture_pipeline (NULL));
if ((pipeline_flags & PIPELINE_VIGNETTE) != 0)
{
static CoglSnippet *vertex_snippet;
static CoglSnippet *fragment_snippet;
if (!vertex_snippet)
vertex_snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX,
VERTEX_SHADER_DECLARATIONS, VERTEX_SHADER_CODE);
cogl_pipeline_add_snippet (*templatep, vertex_snippet);
if (!fragment_snippet)
fragment_snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT,
FRAGMENT_SHADER_DECLARATIONS, FRAGMENT_SHADER_CODE);
cogl_pipeline_add_snippet (*templatep, fragment_snippet);
}
if ((pipeline_flags & PIPELINE_BLEND) == 0)
cogl_pipeline_set_blend (*templatep, "RGBA = ADD (SRC_COLOR, 0)", NULL);
}
return cogl_pipeline_copy (*templatep);
}
static void
setup_pipeline (MetaBackgroundActor *self,
cairo_rectangle_int_t *actor_pixel_rect)
{
MetaBackgroundActorPrivate *priv = self->priv;
PipelineFlags pipeline_flags = 0;
guint8 opacity;
float color_component;
CoglPipelineFilter filter;
opacity = clutter_actor_get_paint_opacity (CLUTTER_ACTOR (self));
if (opacity < 255)
pipeline_flags |= PIPELINE_BLEND;
if (priv->vignette && clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
pipeline_flags |= PIPELINE_VIGNETTE;
if (priv->pipeline &&
pipeline_flags != priv->pipeline_flags)
{
cogl_object_unref (priv->pipeline);
priv->pipeline = NULL;
}
if (priv->pipeline == NULL)
{
priv->pipeline_flags = pipeline_flags;
priv->pipeline = make_pipeline (pipeline_flags);
priv->changed = CHANGED_ALL;
}
if ((priv->changed & CHANGED_BACKGROUND) != 0)
{
CoglPipelineWrapMode wrap_mode;
CoglTexture *texture = meta_background_get_texture (priv->background,
priv->monitor,
&priv->texture_area,
&wrap_mode);
priv->force_bilinear = texture &&
(priv->texture_area.width != (int)cogl_texture_get_width (texture) ||
priv->texture_area.height != (int)cogl_texture_get_height (texture));
cogl_pipeline_set_layer_texture (priv->pipeline, 0, texture);
cogl_pipeline_set_layer_wrap_mode (priv->pipeline, 0, wrap_mode);
}
if ((priv->changed & CHANGED_VIGNETTE_PARAMETERS) != 0)
{
cogl_pipeline_set_uniform_1f (priv->pipeline,
cogl_pipeline_get_uniform_location (priv->pipeline,
"vignette_sharpness"),
priv->vignette_sharpness);
}
if (priv->vignette)
{
color_component = priv->brightness * opacity / 255.;
if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
{
/* Darken everything to match the average brightness that would
* be there if we were drawing the vignette, which is
* (1 - (pi/12.) * vignette_sharpness) [exercise for the reader :]
*/
color_component *= (1 - 0.74 * priv->vignette_sharpness);
}
}
else
color_component = opacity / 255.;
cogl_pipeline_set_color4f (priv->pipeline,
color_component,
color_component,
color_component,
opacity / 255.);
if (!priv->force_bilinear &&
meta_actor_painting_untransformed (actor_pixel_rect->width, actor_pixel_rect->height, NULL, NULL))
filter = COGL_PIPELINE_FILTER_NEAREST;
else
filter = COGL_PIPELINE_FILTER_LINEAR;
cogl_pipeline_set_layer_filters (priv->pipeline, 0, filter, filter);
}
static void
set_glsl_parameters (MetaBackgroundActor *self,
cairo_rectangle_int_t *actor_pixel_rect)
{
MetaBackgroundActorPrivate *priv = self->priv;
float scale[2];
float offset[2];
/* Compute a scale and offset for transforming texture coordinates to the
* coordinate system from [-0.5 to 0.5] across the area of the actor
*/
scale[0] = priv->texture_area.width / (float)actor_pixel_rect->width;
scale[1] = priv->texture_area.height / (float)actor_pixel_rect->height;
offset[0] = priv->texture_area.x / (float)actor_pixel_rect->width - 0.5;
offset[1] = priv->texture_area.y / (float)actor_pixel_rect->height - 0.5;
cogl_pipeline_set_uniform_float (priv->pipeline,
cogl_pipeline_get_uniform_location (priv->pipeline,
"scale"),
2, 1, scale);
cogl_pipeline_set_uniform_float (priv->pipeline,
cogl_pipeline_get_uniform_location (priv->pipeline,
"offset"),
2, 1, offset);
}
static void
paint_clipped_rectangle (CoglFramebuffer *fb,
CoglPipeline *pipeline,
cairo_rectangle_int_t *rect,
cairo_rectangle_int_t *texture_area)
{
float x1, y1, x2, y2;
float tx1, ty1, tx2, ty2;
x1 = rect->x;
y1 = rect->y;
x2 = rect->x + rect->width;
y2 = rect->y + rect->height;
tx1 = (x1 - texture_area->x) / texture_area->width;
ty1 = (y1 - texture_area->y) / texture_area->height;
tx2 = (x2 - texture_area->x) / texture_area->width;
ty2 = (y2 - texture_area->y) / texture_area->height;
cogl_framebuffer_draw_textured_rectangle (fb, pipeline,
x1, y1, x2, y2,
tx1, ty1, tx2, ty2);
}
static gboolean
meta_background_actor_get_paint_volume (ClutterActor *actor,
ClutterPaintVolume *volume)
{
return clutter_paint_volume_set_from_allocation (volume, actor);
}
static void
meta_background_actor_paint (ClutterActor *actor)
{
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (actor);
MetaBackgroundActorPrivate *priv = self->priv;
ClutterActorBox actor_box;
cairo_rectangle_int_t actor_pixel_rect;
CoglFramebuffer *fb;
int i;
if ((priv->clip_region && cairo_region_is_empty (priv->clip_region)))
return;
clutter_actor_get_content_box (actor, &actor_box);
actor_pixel_rect.x = actor_box.x1;
actor_pixel_rect.y = actor_box.y1;
actor_pixel_rect.width = actor_box.x2 - actor_box.x1;
actor_pixel_rect.height = actor_box.y2 - actor_box.y1;
setup_pipeline (self, &actor_pixel_rect);
set_glsl_parameters (self, &actor_pixel_rect);
/* Limit to how many separate rectangles we'll draw; beyond this just
* fall back and draw the whole thing */
#define MAX_RECTS 64
fb = cogl_get_draw_framebuffer ();
/* Now figure out what to actually paint.
*/
if (priv->clip_region != NULL)
{
int n_rects = cairo_region_num_rectangles (priv->clip_region);
if (n_rects <= MAX_RECTS)
{
for (i = 0; i < n_rects; i++)
{
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (priv->clip_region, i, &rect);
if (!gdk_rectangle_intersect (&actor_pixel_rect, &rect, &rect))
continue;
paint_clipped_rectangle (fb, priv->pipeline, &rect, &priv->texture_area);
}
return;
}
}
paint_clipped_rectangle (fb, priv->pipeline, &actor_pixel_rect, &priv->texture_area);
}
static void
meta_background_actor_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (object);
MetaBackgroundActorPrivate *priv = self->priv;
switch (prop_id)
{
case PROP_META_SCREEN:
priv->screen = g_value_get_object (value);
break;
case PROP_MONITOR:
priv->monitor = g_value_get_int (value);
break;
case PROP_BACKGROUND:
meta_background_actor_set_background (self, g_value_get_object (value));
break;
case PROP_VIGNETTE:
meta_background_actor_set_vignette (self,
g_value_get_boolean (value),
priv->brightness,
priv->vignette_sharpness);
break;
case PROP_VIGNETTE_SHARPNESS:
meta_background_actor_set_vignette (self,
priv->vignette,
priv->brightness,
g_value_get_double (value));
break;
case PROP_BRIGHTNESS:
meta_background_actor_set_vignette (self,
priv->vignette,
g_value_get_double (value),
priv->vignette_sharpness);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_background_actor_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MetaBackgroundActorPrivate *priv = META_BACKGROUND_ACTOR (object)->priv;
switch (prop_id)
{
case PROP_META_SCREEN:
g_value_set_object (value, priv->screen);
break;
case PROP_MONITOR:
g_value_set_int (value, priv->monitor);
break;
case PROP_BACKGROUND:
g_value_set_object (value, priv->background);
break;
case PROP_VIGNETTE:
g_value_set_boolean (value, priv->vignette);
break;
case PROP_BRIGHTNESS:
g_value_set_double (value, priv->brightness);
break;
case PROP_VIGNETTE_SHARPNESS:
g_value_set_double (value, priv->vignette_sharpness);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void static void
meta_background_actor_class_init (MetaBackgroundActorClass *klass) meta_background_actor_class_init (MetaBackgroundActorClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
GParamSpec *param_spec;
g_type_class_add_private (klass, sizeof (MetaBackgroundActorPrivate)); g_type_class_add_private (klass, sizeof (MetaBackgroundActorPrivate));
object_class->dispose = meta_background_actor_dispose; object_class->dispose = meta_background_actor_dispose;
object_class->set_property = meta_background_actor_set_property;
object_class->get_property = meta_background_actor_get_property;
actor_class->get_preferred_width = meta_background_actor_get_preferred_width; actor_class->get_preferred_width = meta_background_actor_get_preferred_width;
actor_class->get_preferred_height = meta_background_actor_get_preferred_height; actor_class->get_preferred_height = meta_background_actor_get_preferred_height;
actor_class->get_paint_volume = meta_background_actor_get_paint_volume;
actor_class->paint = meta_background_actor_paint;
param_spec = g_param_spec_object ("meta-screen",
"MetaScreen",
"MetaScreen",
META_TYPE_SCREEN,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_property (object_class,
PROP_META_SCREEN,
param_spec);
param_spec = g_param_spec_int ("monitor",
"monitor",
"monitor",
0, G_MAXINT, 0,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_property (object_class,
PROP_MONITOR,
param_spec);
param_spec = g_param_spec_object ("background",
"Background",
"MetaBackground object holding background parameters",
META_TYPE_BACKGROUND,
G_PARAM_READWRITE);
g_object_class_install_property (object_class,
PROP_BACKGROUND,
param_spec);
param_spec = g_param_spec_boolean ("vignette",
"Vignette",
"Whether vignette effect is enabled",
FALSE,
G_PARAM_READWRITE);
g_object_class_install_property (object_class,
PROP_VIGNETTE,
param_spec);
param_spec = g_param_spec_double ("brightness",
"Brightness",
"Brightness of vignette effect",
0.0, 1.0, 1.0,
G_PARAM_READWRITE);
g_object_class_install_property (object_class,
PROP_BRIGHTNESS,
param_spec);
param_spec = g_param_spec_double ("vignette-sharpness",
"Vignette Sharpness",
"Sharpness of vignette effect",
0.0, G_MAXDOUBLE, 0.0,
G_PARAM_READWRITE);
g_object_class_install_property (object_class,
PROP_VIGNETTE_SHARPNESS,
param_spec);
} }
static void static void
meta_background_actor_init (MetaBackgroundActor *self) meta_background_actor_init (MetaBackgroundActor *self)
{ {
MetaBackgroundActorPrivate *priv; self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
META_TYPE_BACKGROUND_ACTOR,
priv = self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, MetaBackgroundActorPrivate);
META_TYPE_BACKGROUND_ACTOR,
MetaBackgroundActorPrivate);
priv->vignette = FALSE;
priv->brightness = 1.0;
priv->vignette_sharpness = 0.0;
} }
/** /**
* meta_background_actor_new: * meta_background_actor_new:
* @monitor: Index of the monitor for which to draw the background
* *
* Creates a new actor to draw the background for the given monitor. * Creates a new actor to draw the background for the given monitor.
* This actor should be associated with a #MetaBackground using
* clutter_actor_set_content()
* *
* Return value: the newly created background actor * Return value: the newly created background actor
*/ */
ClutterActor * ClutterActor *
meta_background_actor_new (MetaScreen *screen, meta_background_actor_new (void)
int monitor)
{ {
MetaBackgroundActor *self; MetaBackgroundActor *self;
self = g_object_new (META_TYPE_BACKGROUND_ACTOR, self = g_object_new (META_TYPE_BACKGROUND_ACTOR, NULL);
"meta-screen", screen,
"monitor", monitor,
NULL);
return CLUTTER_ACTOR (self); return CLUTTER_ACTOR (self);
} }
@@ -683,7 +185,7 @@ cullable_iface_init (MetaCullableInterface *iface)
* meta_background_actor_get_clip_region: * meta_background_actor_get_clip_region:
* @self: a #MetaBackgroundActor * @self: a #MetaBackgroundActor
* *
* Return value (transfer none): a #cairo_region_t that represents the part of * Return value (transfer full): a #cairo_region_t that represents the part of
* the background not obscured by other #MetaBackgroundActor or * the background not obscured by other #MetaBackgroundActor or
* #MetaWindowActor objects. * #MetaWindowActor objects.
*/ */
@@ -691,92 +193,24 @@ cairo_region_t *
meta_background_actor_get_clip_region (MetaBackgroundActor *self) meta_background_actor_get_clip_region (MetaBackgroundActor *self)
{ {
MetaBackgroundActorPrivate *priv = self->priv; MetaBackgroundActorPrivate *priv = self->priv;
return priv->clip_region; ClutterActorBox content_box;
} cairo_rectangle_int_t content_area = { 0 };
cairo_region_t *clip_region;
static void
invalidate_pipeline (MetaBackgroundActor *self, g_return_val_if_fail (META_IS_BACKGROUND_ACTOR (self), NULL);
ChangedFlags changed)
{ if (!priv->clip_region)
MetaBackgroundActorPrivate *priv = self->priv; return NULL;
priv->changed |= changed; clutter_actor_get_content_box (CLUTTER_ACTOR (self), &content_box);
}
content_area.x = content_box.x1;
static void content_area.y = content_box.y1;
on_background_changed (MetaBackground *background, content_area.width = content_box.x2 - content_box.x1;
MetaBackgroundActor *self) content_area.height = content_box.y2 - content_box.y1;
{
invalidate_pipeline (self, CHANGED_BACKGROUND); clip_region = cairo_region_create_rectangle (&content_area);
clutter_actor_queue_redraw (CLUTTER_ACTOR (self)); cairo_region_intersect (clip_region, priv->clip_region);
}
return clip_region;
void
meta_background_actor_set_background (MetaBackgroundActor *self,
MetaBackground *background)
{
MetaBackgroundActorPrivate *priv;
g_return_if_fail (META_IS_BACKGROUND_ACTOR (self));
g_return_if_fail (background == NULL || META_IS_BACKGROUND (background));
priv = self->priv;
if (background == priv->background)
return;
if (priv->background)
{
g_signal_handlers_disconnect_by_func (priv->background,
(gpointer)on_background_changed,
self);
g_object_unref (priv->background);
priv->background = NULL;
}
if (background)
{
priv->background = g_object_ref (background);
g_signal_connect (priv->background, "changed",
G_CALLBACK (on_background_changed), self);
}
invalidate_pipeline (self, CHANGED_BACKGROUND);
clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
}
void
meta_background_actor_set_vignette (MetaBackgroundActor *self,
gboolean enabled,
double brightness,
double sharpness)
{
MetaBackgroundActorPrivate *priv;
gboolean changed = FALSE;
g_return_if_fail (META_IS_BACKGROUND_ACTOR (self));
g_return_if_fail (brightness >= 0. && brightness <= 1.);
g_return_if_fail (sharpness >= 0.);
priv = self->priv;
enabled = enabled != FALSE;
if (enabled != priv->vignette)
{
priv->vignette = enabled;
invalidate_pipeline (self, CHANGED_EFFECTS);
changed = TRUE;
}
if (brightness != priv->brightness || sharpness != priv->vignette_sharpness)
{
priv->brightness = brightness;
priv->vignette_sharpness = sharpness;
invalidate_pipeline (self, CHANGED_VIGNETTE_PARAMETERS);
changed = TRUE;
}
if (changed)
clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
} }

View File

@@ -1,357 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 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:meta-background-image
* @title: MetaBackgroundImage
* @short_description: objects holding images loaded from files, used for backgrounds
*/
#include <config.h>
#include <gio/gio.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <clutter/clutter.h>
#include <meta/meta-background-image.h>
#include "cogl-utils.h"
enum
{
LOADED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
struct _MetaBackgroundImageCache
{
GObject parent_instance;
GHashTable *images;
};
struct _MetaBackgroundImageCacheClass
{
GObjectClass parent_class;
};
struct _MetaBackgroundImage
{
GObject parent_instance;
GFile *file;
MetaBackgroundImageCache *cache;
gboolean in_cache;
gboolean loaded;
CoglTexture *texture;
};
struct _MetaBackgroundImageClass
{
GObjectClass parent_class;
};
G_DEFINE_TYPE (MetaBackgroundImageCache, meta_background_image_cache, G_TYPE_OBJECT);
static void
meta_background_image_cache_init (MetaBackgroundImageCache *cache)
{
cache->images = g_hash_table_new (g_file_hash, (GEqualFunc) g_file_equal);
}
static void
meta_background_image_cache_finalize (GObject *object)
{
MetaBackgroundImageCache *cache = META_BACKGROUND_IMAGE_CACHE (object);
GHashTableIter iter;
gpointer key, value;
g_hash_table_iter_init (&iter, cache->images);
while (g_hash_table_iter_next (&iter, &key, &value))
{
MetaBackgroundImage *image = value;
image->in_cache = FALSE;
}
g_hash_table_destroy (cache->images);
G_OBJECT_CLASS (meta_background_image_cache_parent_class)->finalize (object);
}
static void
meta_background_image_cache_class_init (MetaBackgroundImageCacheClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_background_image_cache_finalize;
}
/**
* meta_background_image_cache_get_default:
*
* Return value: (transfer none): the global singleton background cache
*/
MetaBackgroundImageCache *
meta_background_image_cache_get_default (void)
{
static MetaBackgroundImageCache *cache;
if (cache == NULL)
cache = g_object_new (META_TYPE_BACKGROUND_IMAGE_CACHE, NULL);
return cache;
}
static void
load_file (GTask *task,
MetaBackgroundImage *image,
gpointer task_data,
GCancellable *cancellable)
{
GError *error = NULL;
GdkPixbuf *pixbuf;
GFileInputStream *stream;
stream = g_file_read (image->file, NULL, &error);
if (stream == NULL)
{
g_task_return_error (task, error);
return;
}
pixbuf = gdk_pixbuf_new_from_stream (G_INPUT_STREAM (stream), NULL, &error);
g_object_unref (stream);
if (pixbuf == NULL)
{
g_task_return_error (task, error);
return;
}
g_task_return_pointer (task, pixbuf, (GDestroyNotify) g_object_unref);
}
static void
file_loaded (GObject *source_object,
GAsyncResult *result,
gpointer user_data)
{
MetaBackgroundImage *image = META_BACKGROUND_IMAGE (source_object);
GError *error = NULL;
GTask *task;
CoglTexture *texture;
GdkPixbuf *pixbuf;
int width, height, row_stride;
guchar *pixels;
gboolean has_alpha;
task = G_TASK (result);
pixbuf = g_task_propagate_pointer (task, &error);
if (pixbuf == NULL)
{
char *uri = g_file_get_uri (image->file);
g_warning ("Failed to load background '%s': %s",
uri, error->message);
g_clear_error (&error);
g_free (uri);
goto out;
}
width = gdk_pixbuf_get_width (pixbuf);
height = gdk_pixbuf_get_height (pixbuf);
row_stride = gdk_pixbuf_get_rowstride (pixbuf);
pixels = gdk_pixbuf_get_pixels (pixbuf);
has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
texture = meta_create_texture (width, height,
has_alpha ? COGL_TEXTURE_COMPONENTS_RGBA : COGL_TEXTURE_COMPONENTS_RGB,
META_TEXTURE_ALLOW_SLICING);
if (!cogl_texture_set_data (texture,
has_alpha ? COGL_PIXEL_FORMAT_RGBA_8888 : COGL_PIXEL_FORMAT_RGB_888,
row_stride,
pixels, 0,
NULL))
{
g_warning ("Failed to create texture for background");
cogl_object_unref (texture);
}
image->texture = texture;
out:
if (pixbuf != NULL)
g_object_unref (pixbuf);
image->loaded = TRUE;
g_signal_emit (image, signals[LOADED], 0);
}
/**
* meta_background_image_cache_load:
* @cache: a #MetaBackgroundImageCache
* @file: #GFile to load
*
* Loads an image to use as a background, or returns a reference to an
* image that is already in the process of loading or loaded. In either
* case, what is returned is a #MetaBackgroundImage which can be derefenced
* to get a #CoglTexture. If meta_background_image_is_loaded() returns %TRUE,
* the background is loaded, otherwise the MetaBackgroundImage::loaded
* signal will be emitted exactly once. The 'loaded' state means that the
* loading process finished, whether it succeeded or failed.
*
* Return value: (transfer full): a #MetaBackgroundImage to dereference to get the loaded texture
*/
MetaBackgroundImage *
meta_background_image_cache_load (MetaBackgroundImageCache *cache,
GFile *file)
{
MetaBackgroundImage *image;
GTask *task;
g_return_val_if_fail (META_IS_BACKGROUND_IMAGE_CACHE (cache), NULL);
g_return_val_if_fail (file != NULL, NULL);
image = g_hash_table_lookup (cache->images, file);
if (image != NULL)
return g_object_ref (image);
image = g_object_new (META_TYPE_BACKGROUND_IMAGE, NULL);
image->cache = cache;
image->in_cache = TRUE;
image->file = g_object_ref (file);
g_hash_table_insert (cache->images, image->file, image);
task = g_task_new (image, NULL, file_loaded, NULL);
g_task_run_in_thread (task, (GTaskThreadFunc) load_file);
g_object_unref (task);
return image;
}
/**
* meta_background_image_cache_purge:
* @cache: a #MetaBackgroundImageCache
* @file: file to remove from the cache
*
* Remove an entry from the cache; this would be used if monitoring
* showed that the file changed.
*/
void
meta_background_image_cache_purge (MetaBackgroundImageCache *cache,
GFile *file)
{
MetaBackgroundImage *image;
g_return_if_fail (META_IS_BACKGROUND_IMAGE_CACHE (cache));
g_return_if_fail (file != NULL);
image = g_hash_table_lookup (cache->images, file);
if (image == NULL)
return;
g_hash_table_remove (cache->images, image->file);
image->in_cache = FALSE;
}
G_DEFINE_TYPE (MetaBackgroundImage, meta_background_image, G_TYPE_OBJECT);
static void
meta_background_image_init (MetaBackgroundImage *image)
{
}
static void
meta_background_image_finalize (GObject *object)
{
MetaBackgroundImage *image = META_BACKGROUND_IMAGE (object);
if (image->in_cache)
g_hash_table_remove (image->cache->images, image->file);
if (image->texture)
cogl_object_unref (image->texture);
if (image->file)
g_object_unref (image->file);
G_OBJECT_CLASS (meta_background_image_parent_class)->finalize (object);
}
static void
meta_background_image_class_init (MetaBackgroundImageClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_background_image_finalize;
signals[LOADED] =
g_signal_new ("loaded",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 0);
}
/**
* meta_background_image_is_loaded:
* @image: a #MetaBackgroundImage
*
* Return value: %TRUE if loading has already completed, %FALSE otherwise
*/
gboolean
meta_background_image_is_loaded (MetaBackgroundImage *image)
{
g_return_val_if_fail (META_IS_BACKGROUND_IMAGE (image), FALSE);
return image->loaded;
}
/**
* meta_background_image_get_success:
* @image: a #MetaBackgroundImage
*
* This function is a convenience function for checking for success,
* without having to call meta_background_image_get_texture() and
* handle the return of a Cogl type.
*
* Return value: %TRUE if loading completed successfully, otherwise %FALSE
*/
gboolean
meta_background_image_get_success (MetaBackgroundImage *image)
{
g_return_val_if_fail (META_IS_BACKGROUND_IMAGE (image), FALSE);
return image->texture != NULL;
}
/**
* meta_background_image_get_texture:
* @image: a #MetaBackgroundImage
*
* Return value: (transfer none): a #CoglTexture if loading succeeded; if
* loading failed or has not yet finished, %NULL.
*/
CoglTexture *
meta_background_image_get_texture (MetaBackgroundImage *image)
{
g_return_val_if_fail (META_IS_BACKGROUND_IMAGE (image), NULL);
return image->texture;
}

View File

@@ -1,15 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#ifndef META_BACKGROUND_PRIVATE_H
#define META_BACKGROUND_PRIVATE_H
#include <config.h>
#include "meta-background-private.h"
CoglTexture *meta_background_get_texture (MetaBackground *self,
int monitor_index,
cairo_rectangle_int_t *texture_area,
CoglPipelineWrapMode *wrap_mode);
#endif /* META_BACKGROUND_PRIVATE_H */

File diff suppressed because it is too large Load Diff

View File

@@ -1,64 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* meta-dnd-actor-private.h: Actor for painting the DnD surface
*
* Copyright 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/>.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#ifndef META_DND_ACTOR_PRIVATE_H
#define META_DND_ACTOR_PRIVATE_H
#include "meta-feedback-actor-private.h"
/**
* MetaDnDActor:
*
* This class handles the rendering of the DnD surface
*/
#define META_TYPE_DND_ACTOR (meta_dnd_actor_get_type ())
#define META_DND_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DND_ACTOR, MetaDnDActor))
#define META_DND_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DND_ACTOR, MetaDnDActorClass))
#define META_IS_DND_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_DND_ACTOR))
#define META_IS_DND_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DND_ACTOR))
#define META_DND_ACTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DND_ACTOR, MetaDnDActorClass))
typedef struct _MetaDnDActor MetaDnDActor;
typedef struct _MetaDnDActorClass MetaDnDActorClass;
struct _MetaDnDActorClass
{
/*< private >*/
MetaFeedbackActorClass parent_class;
};
struct _MetaDnDActor
{
MetaFeedbackActor parent;
};
GType meta_dnd_actor_get_type (void);
ClutterActor *meta_dnd_actor_new (ClutterActor *drag_origin,
int start_x,
int start_y);
void meta_dnd_actor_drag_finish (MetaDnDActor *self,
gboolean success);
#endif /* META_DND_ACTOR_PRIVATE_H */

View File

@@ -1,231 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 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/>.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
/**
* SECTION:meta-dnd-actor
* @title: MetaDnDActor
* @short_description: Actor for painting the drag and drop surface
*
*/
#include <config.h>
#include <clutter/clutter.h>
#include "meta-dnd-actor-private.h"
#define DRAG_FAILED_DURATION 500
enum {
PROP_DRAG_ORIGIN = 1,
PROP_DRAG_START_X,
PROP_DRAG_START_Y
};
typedef struct _MetaDnDActorPrivate MetaDnDActorPrivate;
struct _MetaDnDActorPrivate
{
ClutterActor *drag_origin;
int drag_start_x;
int drag_start_y;
};
G_DEFINE_TYPE_WITH_PRIVATE (MetaDnDActor, meta_dnd_actor, META_TYPE_FEEDBACK_ACTOR)
static void
meta_dnd_actor_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MetaDnDActor *self = META_DND_ACTOR (object);
MetaDnDActorPrivate *priv = meta_dnd_actor_get_instance_private (self);
switch (prop_id)
{
case PROP_DRAG_ORIGIN:
priv->drag_origin = g_value_get_object (value);
break;
case PROP_DRAG_START_X:
priv->drag_start_x = g_value_get_int (value);
break;
case PROP_DRAG_START_Y:
priv->drag_start_y = g_value_get_int (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_dnd_actor_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MetaDnDActor *self = META_DND_ACTOR (object);
MetaDnDActorPrivate *priv = meta_dnd_actor_get_instance_private (self);
switch (prop_id)
{
case PROP_DRAG_ORIGIN:
g_value_set_object (value, priv->drag_origin);
break;
case PROP_DRAG_START_X:
g_value_set_int (value, priv->drag_start_x);
break;
case PROP_DRAG_START_Y:
g_value_set_int (value, priv->drag_start_y);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_dnd_actor_class_init (MetaDnDActorClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
object_class->set_property = meta_dnd_actor_set_property;
object_class->get_property = meta_dnd_actor_get_property;
pspec = g_param_spec_object ("drag-origin",
"Drag origin",
"The origin of the DnD operation",
CLUTTER_TYPE_ACTOR,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_property (object_class,
PROP_DRAG_ORIGIN,
pspec);
pspec = g_param_spec_int ("drag-start-x",
"Drag start X",
"The X axis of the drag start point",
0, G_MAXINT, 0,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_property (object_class,
PROP_DRAG_START_X,
pspec);
pspec = g_param_spec_int ("drag-start-y",
"Drag start Y",
"The Y axis of the drag start point",
0, G_MAXINT, 0,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_property (object_class,
PROP_DRAG_START_Y,
pspec);
}
static void
meta_dnd_actor_init (MetaDnDActor *self)
{
}
/**
* meta_dnd_actor_new:
*
* Creates a new actor to draw the current drag and drop surface.
*
* Return value: the newly created background actor
*/
ClutterActor *
meta_dnd_actor_new (ClutterActor *drag_origin,
int drag_start_x,
int drag_start_y)
{
MetaDnDActor *self;
self = g_object_new (META_TYPE_DND_ACTOR,
"drag-origin", drag_origin,
"drag-start-x", drag_start_x,
"drag-start-y", drag_start_y,
NULL);
return CLUTTER_ACTOR (self);
}
static void
drag_failed_complete (ClutterTimeline *timeline,
gboolean is_finished,
gpointer user_data)
{
ClutterActor *self = user_data;
clutter_actor_remove_all_children (self);
clutter_actor_destroy (self);
}
void
meta_dnd_actor_drag_finish (MetaDnDActor *self,
gboolean success)
{
MetaDnDActorPrivate *priv;
ClutterActor *actor;
g_return_if_fail (META_IS_DND_ACTOR (self));
actor = CLUTTER_ACTOR (self);
priv = meta_dnd_actor_get_instance_private (self);
if (success)
{
clutter_actor_remove_all_children (CLUTTER_ACTOR (self));
clutter_actor_destroy (CLUTTER_ACTOR (self));
}
else
{
ClutterTransition *transition;
clutter_actor_save_easing_state (actor);
clutter_actor_set_easing_mode (actor, CLUTTER_EASE_OUT_CUBIC);
clutter_actor_set_easing_duration (actor, DRAG_FAILED_DURATION);
clutter_actor_set_opacity (actor, 0);
if (CLUTTER_ACTOR_IS_VISIBLE (priv->drag_origin))
{
int anchor_x, anchor_y;
ClutterPoint dest;
clutter_actor_get_transformed_position (priv->drag_origin,
&dest.x, &dest.y);
meta_feedback_actor_get_anchor (META_FEEDBACK_ACTOR (self),
&anchor_x, &anchor_y);
dest.x += priv->drag_start_x - anchor_x;
dest.y += priv->drag_start_y - anchor_y;
clutter_actor_set_position (actor, dest.x, dest.y);
}
transition = clutter_actor_get_transition (actor, "opacity");
g_signal_connect (transition, "stopped",
G_CALLBACK (drag_failed_complete), self);
clutter_actor_restore_easing_state (actor);
}
}

View File

@@ -1,74 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* meta-feedback-actor-private.h: Actor for painting user interaction feedback
*
* Copyright 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/>.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#ifndef META_FEEDBACK_ACTOR_PRIVATE_H
#define META_FEEDBACK_ACTOR_PRIVATE_H
#include <clutter/clutter.h>
/**
* MetaFeedbackActor:
*
* This class handles the rendering of user interaction feedback
*/
#define META_TYPE_FEEDBACK_ACTOR (meta_feedback_actor_get_type ())
#define META_FEEDBACK_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_FEEDBACK_ACTOR, MetaFeedbackActor))
#define META_FEEDBACK_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_FEEDBACK_ACTOR, MetaFeedbackActorClass))
#define META_IS_FEEDBACK_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_FEEDBACK_ACTOR))
#define META_IS_FEEDBACK_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_FEEDBACK_ACTOR))
#define META_FEEDBACK_ACTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_FEEDBACK_ACTOR, MetaFeedbackActorClass))
typedef struct _MetaFeedbackActor MetaFeedbackActor;
typedef struct _MetaFeedbackActorClass MetaFeedbackActorClass;
struct _MetaFeedbackActorClass
{
/*< private >*/
ClutterActorClass parent_class;
};
struct _MetaFeedbackActor
{
ClutterActor parent;
};
GType meta_feedback_actor_get_type (void);
ClutterActor *meta_feedback_actor_new (int anchor_x,
int anchor_y);
void meta_feedback_actor_set_anchor (MetaFeedbackActor *actor,
int anchor_x,
int anchor_y);
void meta_feedback_actor_get_anchor (MetaFeedbackActor *actor,
int *anchor_x,
int *anchor_y);
void meta_feedback_actor_set_position (MetaFeedbackActor *self,
int x,
int y);
void meta_feedback_actor_update (MetaFeedbackActor *self,
const ClutterEvent *event);
#endif /* META_FEEDBACK_ACTOR_PRIVATE_H */

View File

@@ -1,249 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 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/>.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
/**
* SECTION:meta-feedback-actor
* @title: MetaFeedbackActor
* @short_description: Actor for painting user interaction feedback
*/
#include <config.h>
#include "display-private.h"
#include "compositor-private.h"
#include "meta-feedback-actor-private.h"
enum {
PROP_ANCHOR_X = 1,
PROP_ANCHOR_Y
};
typedef struct _MetaFeedbackActorPrivate MetaFeedbackActorPrivate;
struct _MetaFeedbackActorPrivate
{
int anchor_x;
int anchor_y;
int pos_x;
int pos_y;
};
G_DEFINE_TYPE_WITH_PRIVATE (MetaFeedbackActor, meta_feedback_actor, CLUTTER_TYPE_ACTOR)
static void
meta_feedback_actor_constructed (GObject *object)
{
MetaDisplay *display;
display = meta_get_display ();
clutter_actor_add_child (display->compositor->feedback_group,
CLUTTER_ACTOR (object));
}
static void
meta_feedback_actor_update_position (MetaFeedbackActor *self)
{
MetaFeedbackActorPrivate *priv = meta_feedback_actor_get_instance_private (self);
clutter_actor_set_position (CLUTTER_ACTOR (self),
priv->pos_x - priv->anchor_x,
priv->pos_y - priv->anchor_y);
}
static void
meta_feedback_actor_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MetaFeedbackActor *self = META_FEEDBACK_ACTOR (object);
MetaFeedbackActorPrivate *priv = meta_feedback_actor_get_instance_private (self);
switch (prop_id)
{
case PROP_ANCHOR_X:
priv->anchor_x = g_value_get_int (value);
meta_feedback_actor_update_position (self);
break;
case PROP_ANCHOR_Y:
priv->anchor_y = g_value_get_int (value);
meta_feedback_actor_update_position (self);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_feedback_actor_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MetaFeedbackActor *self = META_FEEDBACK_ACTOR (object);
MetaFeedbackActorPrivate *priv = meta_feedback_actor_get_instance_private (self);
switch (prop_id)
{
case PROP_ANCHOR_X:
g_value_set_int (value, priv->anchor_x);
break;
case PROP_ANCHOR_Y:
g_value_set_int (value, priv->anchor_y);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_feedback_actor_class_init (MetaFeedbackActorClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
object_class->constructed = meta_feedback_actor_constructed;
object_class->set_property = meta_feedback_actor_set_property;
object_class->get_property = meta_feedback_actor_get_property;
pspec = g_param_spec_int ("anchor-x",
"Anchor X",
"The X axis of the anchor point",
0, G_MAXINT, 0,
G_PARAM_READWRITE);
g_object_class_install_property (object_class,
PROP_ANCHOR_X,
pspec);
pspec = g_param_spec_int ("anchor-y",
"Anchor Y",
"The Y axis of the anchor point",
0, G_MAXINT, 0,
G_PARAM_READWRITE);
g_object_class_install_property (object_class,
PROP_ANCHOR_Y,
pspec);
}
static void
meta_feedback_actor_init (MetaFeedbackActor *self)
{
clutter_actor_set_reactive (CLUTTER_ACTOR (self), FALSE);
}
/**
* meta_feedback_actor_new:
*
* Creates a new actor to draw the current drag and drop surface.
*
* Return value: the newly created background actor
*/
ClutterActor *
meta_feedback_actor_new (int anchor_x,
int anchor_y)
{
MetaFeedbackActor *self;
self = g_object_new (META_TYPE_FEEDBACK_ACTOR,
"anchor-x", anchor_x,
"anchor-y", anchor_y,
NULL);
return CLUTTER_ACTOR (self);
}
void
meta_feedback_actor_set_anchor (MetaFeedbackActor *self,
int anchor_x,
int anchor_y)
{
MetaFeedbackActorPrivate *priv;
g_return_if_fail (META_IS_FEEDBACK_ACTOR (self));
priv = meta_feedback_actor_get_instance_private (self);
if (priv->anchor_x == anchor_x && priv->anchor_y == anchor_y)
return;
if (priv->anchor_x != anchor_y)
{
priv->anchor_x = anchor_x;
g_object_notify (G_OBJECT (self), "anchor-x");
}
if (priv->anchor_y != anchor_y)
{
priv->anchor_y = anchor_y;
g_object_notify (G_OBJECT (self), "anchor-y");
}
meta_feedback_actor_update_position (self);
}
void
meta_feedback_actor_get_anchor (MetaFeedbackActor *self,
int *anchor_x,
int *anchor_y)
{
MetaFeedbackActorPrivate *priv;
g_return_if_fail (META_IS_FEEDBACK_ACTOR (self));
priv = meta_feedback_actor_get_instance_private (self);
if (anchor_x)
*anchor_x = priv->anchor_x;
if (anchor_y)
*anchor_y = priv->anchor_y;
}
void
meta_feedback_actor_set_position (MetaFeedbackActor *self,
int x,
int y)
{
MetaFeedbackActorPrivate *priv;
g_return_if_fail (META_IS_FEEDBACK_ACTOR (self));
priv = meta_feedback_actor_get_instance_private (self);
priv->pos_x = x;
priv->pos_y = y;
meta_feedback_actor_update_position (self);
}
void
meta_feedback_actor_update (MetaFeedbackActor *self,
const ClutterEvent *event)
{
ClutterPoint point;
g_return_if_fail (META_IS_FEEDBACK_ACTOR (self));
g_return_if_fail (event != NULL);
clutter_event_get_position (event, &point);
meta_feedback_actor_set_position (self, point.x, point.y);
}

View File

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

View File

@@ -170,15 +170,6 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
klass->minimize (plugin, actor); klass->minimize (plugin, actor);
} }
break; break;
case META_PLUGIN_UNMINIMIZE:
if (klass->unminimize)
{
retval = TRUE;
meta_plugin_manager_kill_window_effects (plugin_mgr,
actor);
klass->unminimize (plugin, actor);
}
break;
case META_PLUGIN_MAP: case META_PLUGIN_MAP:
if (klass->map) if (klass->map)
{ {
@@ -383,20 +374,3 @@ meta_plugin_manager_show_window_menu (MetaPluginManager *plugin_mgr,
if (klass->show_window_menu) if (klass->show_window_menu)
klass->show_window_menu (plugin, window, menu, x, y); 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

@@ -35,7 +35,6 @@
#define META_PLUGIN_MAP (1<<3) #define META_PLUGIN_MAP (1<<3)
#define META_PLUGIN_DESTROY (1<<4) #define META_PLUGIN_DESTROY (1<<4)
#define META_PLUGIN_SWITCH_WORKSPACE (1<<5) #define META_PLUGIN_SWITCH_WORKSPACE (1<<5)
#define META_PLUGIN_UNMINIMIZE (1<<6)
#define META_PLUGIN_ALL_EFFECTS (~0) #define META_PLUGIN_ALL_EFFECTS (~0)
@@ -88,10 +87,5 @@ void meta_plugin_manager_show_window_menu (MetaPluginManager *mgr,
int x, int x,
int y); int y);
void meta_plugin_manager_show_window_menu_for_rect (MetaPluginManager *mgr,
MetaWindow *window,
MetaWindowMenuType menu,
MetaRectangle *rect);
#endif #endif

View File

@@ -110,13 +110,6 @@ meta_plugin_minimize_completed (MetaPlugin *plugin,
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_MINIMIZE); meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_MINIMIZE);
} }
void
meta_plugin_unminimize_completed (MetaPlugin *plugin,
MetaWindowActor *actor)
{
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_UNMINIMIZE);
}
void void
meta_plugin_maximize_completed (MetaPlugin *plugin, meta_plugin_maximize_completed (MetaPlugin *plugin,
MetaWindowActor *actor) MetaWindowActor *actor)

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