Compare commits

..

12 Commits

Author SHA1 Message Date
5bc7ae4095 ff 2014-04-06 17:43:43 -04:00
1a78515606 ui: Use the default GdkDisplay / GdkScreen
These are the values we always use anyway, and it allows us to
seal off MetaUI further and have them on their own X connection.
2014-04-06 17:43:43 -04:00
4122257bce ui: Store the GdkDisplay / GdkScreen internally
We're going to get the defaults instead of passing them through soon.
2014-04-06 17:43:43 -04:00
29f6e3bda5 ui: Remove Display from the UI API
We already store it in the MetaUI struct, so add that where it's
missing and remove Display.
2014-04-06 17:43:43 -04:00
bbcbf5820f ui: Don't hang the MetaUI pointer off the GdkDisplay
Instead, use the user_data in the filter to pass a MetaUI through.
2014-04-06 17:22:55 -04:00
ee7c58984a ui: Kill off meta_ui_get_screen_number
GTK+ always opens the DefaultScreen now, so we can do the same.
2014-04-06 17:06:12 -04:00
03e5bbf59f xprop: Don't use GDK for reading text properties 2014-04-06 17:06:12 -04:00
cc6becb163 errors: Copy error trap code from GDK into mutter
In order to kill off using GDK for event handling in X11, we're going
to need to stop using GDK primitives.
2014-04-06 16:16:33 -04:00
e3b855a583 errors: Kill off meta_error_trap_push_with_return
It isn't special; it's just an alias for meta_error_trap_push.
2014-04-06 16:16:31 -04:00
5d8dd0653e display: Remove vestigals of old error trap implementation 2014-04-06 15:54:47 -04:00
abe94827f5 events: Don't pass any X input events on to Clutter / GTK+ 2014-04-06 15:32:30 -04:00
72b88c929e events: Early exit when we get a SN notification event
Nothing else needs to see this.
2014-04-06 15:23:20 -04:00
289 changed files with 72920 additions and 58211 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

43
.gitignore vendored
View File

@ -3,7 +3,6 @@ Makefile.in
Makefile.in.in
aclocal.m4
autom4te.cache
build-aux
compile
config.guess
config.h
@ -20,11 +19,11 @@ libtool
ltmain.sh
missing
.deps
50-mutter-navigation.xml
50-mutter-system.xml
50-mutter-windows.xml
mutter.desktop
mutter-wayland.desktop
src/50-mutter-navigation.xml
src/50-mutter-system.xml
src/50-mutter-windows.xml
src/mutter-wm.desktop
src/mutter-wayland.desktop
*.o
*.a
*.lo
@ -33,6 +32,10 @@ mutter-wayland.desktop
*.swp
*.gir
*.typelib
tidy-enum-types.[ch]
tidy-marshal.[ch]
stamp-tidy-enum-types.h
stamp-tidy-marshal.h
stamp-h1
*.gmo
*.make
@ -41,12 +44,11 @@ stamp-it
.intltool-merge-cache
POTFILES
po/*.pot
libmutter.pc
mutter
mutter-restart-helper
mutter-test-client
mutter-test-runner
mutter-all.test
50-metacity-desktop-key.xml
50-metacity-key.xml
libmutter-wayland.pc
mutter-wayland
mutter-launch
org.gnome.mutter.gschema.valid
org.gnome.mutter.gschema.xml
org.gnome.mutter.wayland.gschema.valid
@ -54,7 +56,19 @@ org.gnome.mutter.wayland.gschema.xml
testasyncgetprop
testboxes
testgradient
m4/*
mutter-grayscale
mutter-mag
mutter-message
mutter-window-demo
focus-window
test-attached
test-focus
test-gravity
test-resizing
test-size-hints
# We can't say just "wm-tester" here or it will ignore the directory
# rather than the binary
src/wm-tester/wm-tester
INSTALL
mkinstalldirs
src/mutter-enum-types.[ch]
@ -63,14 +77,13 @@ src/mutter-marshal.[ch]
src/stamp-mutter-marshal.h
src/meta-dbus-display-config.[ch]
src/meta-dbus-idle-monitor.[ch]
src/meta-dbus-login1.[ch]
src/mutter-plugins.pc
src/gtk-shell-protocol.c
src/gtk-shell-server-protocol.h
src/xdg-shell-protocol.c
src/xdg-shell-server-protocol.h
src/xserver-protocol.c
src/xserver-server-protocol.h
src/meta/meta-version.h
doc/reference/*.args
doc/reference/*.bak
doc/reference/*.hierarchy

View File

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

191
NEWS
View File

@ -1,194 +1,3 @@
3.14.1.5
========
* Fix wayland hiDPI regressions [Adel; #739161]
Contributors:
Adel Gadllah, Florian Müllner, Jasper St. Pierre
Translations:
Dušan Kazik [sk]
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
======
* Add basic HiDPI support on wayland [Adel; #728902]
* Fix crash when monitors change during suspend [Giovanni; #725637]
* Replace mutter-launch with logind integration [Jasper; #724604]
* Move window menu into the compositor [Jasper; #726352]
* Fix delayed focus-follows-mouse support [Florian; #730541]
* Support fallback app menu in window decorations [Florian; #730752]
* Misc. bug fixes and cleanups [Giovanni, Jonas, Jasper; #729732, #729602,
#726714]
Contributors:
Jonas Ådahl, Giovanni Campagna, Adel Gadllah, Florian Müllner,
Jasper St. Pierre, Rico Tzschichholz
Translations:
Pau Iranzo [ca], Daniel Mustieles [es]
3.13.1
======
* Fix opacity values from _NET_WM_WINDOW_OPACITY [Nirbheek; #727874]
* Merge wayland branch [Jasper, Giovanni, Robert B., Neil, Adel, Rui, Jonas,
Lionel, Tim, Owen, Florian, Colin W., Cosimo, Ray, Kalev, Pavel, Robert A.,
Magdalen, Marek, Matthias, Alban, Seán, Daniel, Stefano, Carlos, Colin G.,
Andreas, Alexander, Ryan, Marc-André, Asad, Alberto, Bastien, Hans,
Debarshi, Sindhu, Andika, Rico, Olav]
* Don't prevent workspace switches for present_with_time() [Florian; #728018]
* Add shortcuts for switching to the last workspace [Elad; #659288]
* Make move/resize menu items behave like the keybindings [Jasper; #728617]
* Misc. bug fixes and cleanups [Jasper, Bastien, Florian, Adel; #720631,
#727979, #728423, #728395, #729044]
Contributors:
Jonas Ådahl, Elad Alfassa, Robert Ancell, Magdalen Berns, Robert Bragg,
Giovanni Campagna, Cosimo Cecchi, Marek Chalupa, Nirbheek Chauhan,
Matthias Clasen, Alban Crequy, Seán de Búrca, Daniel Drake, Jason Ekstrand,
Stefano Facchini, Adel Gadllah, Carlos Garnacho, Colin Guthrie,
Andreas Heider, Lionel Landwerlin, Alexander Larsson, Kalev Lember,
Ryan Lortie, Tim Lunn, Marc-André Lureau, Rui Matos, Asad Mehmood,
Alberto Milone, Florian Müllner, Bastien Nocera, Hans Petter Jansson,
Debarshi Ray, Neil Roberts, Sindhu S, Jasper St. Pierre, Ray Strode,
Andika Triwidada, Rico Tzschichholz, Pavel Vasin, Olav Vitters,
Colin Walters, A. Walton, Owen W. Taylor
Translations:
Inaki Larranaga Murgoitio [eu], marablack3 [el], Daniel Mustieles [es],
Fran Diéguez [gl], Yosef Or Boczko [he], Dirgita [id]
3.12.0
======
* Fix grab issue with SSD xwayland windows [Rui; #726123]

View File

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

View File

@ -1,8 +1,9 @@
AC_PREREQ(2.62)
AC_PREREQ(2.50)
AC_CONFIG_MACRO_DIR([m4])
m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [14])
m4_define([mutter_micro_version], [1.5])
m4_define([mutter_minor_version], [12])
m4_define([mutter_micro_version], [0])
m4_define([mutter_version],
[mutter_major_version.mutter_minor_version.mutter_micro_version])
@ -12,8 +13,6 @@ m4_define([mutter_plugin_api_version], [3])
AC_INIT([mutter], [mutter_version],
[http://bugzilla.gnome.org/enter_bug.cgi?product=mutter])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_SRCDIR(src/core/display.c)
AC_CONFIG_HEADERS(config.h)
@ -21,6 +20,10 @@ AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz tar-ustar subdir-objects])
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],)
AM_MAINTAINER_MODE([enable])
# Change pkglibdir and pkgdatadir to mutter-wayland instead of mutter
PACKAGE="mutter-wayland"
AC_SUBST([PACKAGE], [$PACKAGE])
MUTTER_MAJOR_VERSION=mutter_major_version
MUTTER_MINOR_VERSION=mutter_minor_version
MUTTER_MICRO_VERSION=mutter_micro_version
@ -36,18 +39,16 @@ AC_SUBST(MUTTER_PLUGIN_DIR)
# Honor aclocal flags
AC_SUBST(ACLOCAL_AMFLAGS, "\${ACLOCAL_FLAGS}")
GETTEXT_PACKAGE=mutter
GETTEXT_PACKAGE=mutter-wayland
AC_SUBST(GETTEXT_PACKAGE)
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[Name of default gettext domain])
LT_PREREQ([2.2.6])
LT_INIT([disable-static])
IT_PROG_INTLTOOL([0.41])
IT_PROG_INTLTOOL([0.34.90])
AC_PROG_CC
AC_PROG_CC_C_O
AC_PROG_INSTALL
AC_ISC_POSIX
AC_HEADER_STDC
PKG_PROG_PKG_CONFIG([0.21])
AC_LIBTOOL_WIN32_DLL
AM_PROG_LIBTOOL
# Sets GLIB_GENMARSHAL and GLIB_MKENUMS
AM_PATH_GLIB_2_0()
@ -71,28 +72,16 @@ CANBERRA_GTK_VERSION=0.26
CLUTTER_PACKAGE=clutter-1.0
MUTTER_PC_MODULES="
gtk+-3.0 >= 3.9.11
gio-unix-2.0 >= 2.25.10
gtk+-3.0 >= 3.3.7
gio-2.0 >= 2.25.10
pango >= 1.2.0
cairo >= 1.10.0
gsettings-desktop-schemas >= 3.7.3
$CLUTTER_PACKAGE >= 1.19.5
xcomposite >= 0.2 xfixes xrender xdamage xi >= 1.6.0
$CLUTTER_PACKAGE >= 1.17.5
cogl-1.0 >= 1.17.1
gbm >= 10.3
upower-glib >= 0.99.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
@ -121,18 +110,37 @@ AC_ARG_WITH(libcanberra,
[disable the use of libcanberra for playing sounds]),,
with_libcanberra=auto)
AC_ARG_ENABLE(xsync,
AC_HELP_STRING([--disable-xsync],
[disable mutter's use of the XSync extension]),,
enable_xsync=auto)
AC_ARG_ENABLE(shape,
AC_HELP_STRING([--disable-shape],
[disable mutter's use of the shaped window extension]),,
enable_shape=auto)
## Wayland support requires the xserver.xml protocol extension found in the weston
## repository but since there aren't currently established conventions for
## installing and discovering these we simply require a location to be given
## explicitly...
AC_ARG_WITH([wayland-protocols],
[AS_HELP_STRING([--with-wayland-protocols], [Location for wayland extension protocol specs])],
[
],
[])
AC_ARG_WITH([xwayland-path],
[AS_HELP_STRING([--with-xwayland-path], [Absolute path for an X Wayland server])],
[XWAYLAND_PATH="$withval"],
[XWAYLAND_PATH="$bindir/Xwayland"])
AC_ARG_ENABLE(installed_tests,
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)
AM_GLIB_GNU_GETTEXT
## here we get the flags we'll actually use
# GRegex requires Glib-2.14.0
PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.14.0)
PKG_CHECK_MODULES(MUTTER_LAUNCH, libdrm libsystemd-login)
# Unconditionally use this dir to avoid a circular dep with gnomecc
GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings"
@ -197,27 +205,17 @@ if test x$found_introspection != xno; then
AC_SUBST(META_GIR)
fi
MUTTER_PC_MODULES="$MUTTER_PC_MODULES xcursor"
AC_PATH_PROG([WAYLAND_SCANNER],[wayland-scanner],[no])
AS_IF([test "x$WAYLAND_SCANNER" = "xno"],
AC_MSG_ERROR([Could not find wayland-scanner in your PATH, required for parsing wayland extension protocols]))
AC_SUBST([WAYLAND_SCANNER])
AC_SUBST(XWAYLAND_PATH)
MUTTER_PC_MODULES="$MUTTER_PC_MODULES clutter-wayland-1.0 clutter-wayland-compositor-1.0 clutter-egl-1.0 wayland-server libdrm"
PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES)
PKG_CHECK_MODULES(MUTTER_NATIVE_BACKEND, [clutter-egl-1.0 libdrm libsystemd libinput], [have_native_backend=yes], [have_native_backend=no])
if test $have_native_backend = yes; then
AC_DEFINE([HAVE_NATIVE_BACKEND],[1],[Define if you want to enable the native (KMS) backend based on systemd])
fi
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],
AC_DEFINE([HAVE_XI23],[1],[Define if you have support for XInput 2.3 or greater]))
@ -254,8 +252,38 @@ if test x$have_xinerama = xno; then
AC_MSG_ERROR([Xinerama extension was not found])
fi
AC_DEFINE_UNQUOTED([XKB_BASE], ["`$PKG_CONFIG --variable xkb_base xkeyboard-config`"],
[XKB base dir])
SHAPE_LIBS=
found_shape=no
AC_CHECK_LIB(Xext, XShapeQueryExtension,
[AC_CHECK_HEADER(X11/extensions/shape.h,
SHAPE_LIBS=-lXext found_shape=yes)],
, $ALL_X_LIBS)
if test x$enable_shape = xno; then
found_shape=no
fi
if test x$enable_shape = xyes; then
if test "$found_shape" = "no"; then
AC_MSG_ERROR([--enable-shape forced and Shape not found])
exit 1
fi
fi
if test "x$found_shape" = "xyes"; then
AC_DEFINE(HAVE_SHAPE, , [Have the shape extension library])
fi
found_xkb=no
AC_CHECK_LIB(X11, XkbQueryExtension,
[AC_CHECK_HEADER(X11/XKBlib.h,
found_xkb=yes)],
, $ALL_X_LIBS)
if test "x$found_xkb" = "xyes"; then
AC_DEFINE(HAVE_XKB, , [Have keyboard extension library])
fi
RANDR_LIBS=
found_randr=no
@ -263,13 +291,37 @@ AC_CHECK_LIB(Xrandr, XRRUpdateConfiguration,
[AC_CHECK_HEADER(X11/extensions/Xrandr.h,
RANDR_LIBS=-lXrandr found_randr=yes,,
[#include <X11/Xlib.h>])],
, -lXext $ALL_X_LIBS)
, -lXrender -lXext $ALL_X_LIBS)
if test "x$found_randr" = "xyes"; then
AC_DEFINE(HAVE_RANDR, , [Have the Xrandr extension library])
fi
MUTTER_LIBS="$MUTTER_LIBS $RANDR_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm"
XSYNC_LIBS=
found_xsync=no
AC_CHECK_LIB(Xext, XSyncQueryExtension,
[AC_CHECK_HEADER(X11/extensions/sync.h,
found_xsync=yes,,
[#include <X11/Xlib.h>])],
, $ALL_X_LIBS)
if test x$enable_xsync = xno; then
found_xsync=no
fi
if test x$enable_xsync = xyes; then
if test "$found_xsync" = "no"; then
AC_MSG_ERROR([--enable-xsync forced and XSync not found])
exit 1
fi
fi
if test "x$found_xsync" = "xyes"; then
XSYNC_LIBS=-lXext
AC_DEFINE(HAVE_XSYNC, , [Have the Xsync extension library])
fi
MUTTER_LIBS="$MUTTER_LIBS $XSYNC_LIBS $RANDR_LIBS $SHAPE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm"
found_sm=no
case "$MUTTER_LIBS" in
@ -301,6 +353,17 @@ fi
AM_CONDITIONAL(HAVE_SM, test "$found_sm" = "yes")
HOST_ALIAS=$host_alias
AC_SUBST(HOST_ALIAS)
AC_PATH_PROG(GDK_PIXBUF_CSOURCE, gdk-pixbuf-csource, no)
if test x"$GDK_PIXBUF_CSOURCE" = xno; then
AC_MSG_ERROR([gdk-pixbuf-csource executable not found in your path - should be installed with GTK])
fi
AC_SUBST(GDK_PIXBUF_CSOURCE)
AC_PATH_PROG(ZENITY, zenity, no)
if test x"$ZENITY" = xno; then
AC_MSG_ERROR([zenity not found in your path - needed for dialogs])
@ -383,15 +446,13 @@ changequote([,])dnl
AC_CONFIG_FILES([
Makefile
data/Makefile
doc/Makefile
doc/man/Makefile
doc/reference/Makefile
doc/reference/meta-docs.sgml
src/Makefile
src/libmutter.pc
src/libmutter-wayland.pc
src/compositor/plugins/Makefile
src/meta/meta-version.h
po/Makefile.in
])
@ -407,7 +468,7 @@ fi
dnl ==========================================================================
echo "
mutter-$VERSION
mutter-wayland-$VERSION
prefix: ${prefix}
source code location: ${srcdir}
@ -417,6 +478,8 @@ mutter-$VERSION
libcanberra: ${have_libcanberra}
Introspection: ${found_introspection}
Session management: ${found_sm}
Shape extension: ${found_shape}
Xsync: ${found_xsync}
"

View File

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

View File

@ -1,17 +0,0 @@
[Desktop Entry]
Type=Application
_Name=Mutter
Exec=mutter
NoDisplay=true
# name of loadable control center module
X-GNOME-WMSettingsModule=metacity
# name we put on the WM spec check window
X-GNOME-WMName=Mutter
# back compat only
X-GnomeWMSettingsLibrary=metacity
X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=mutter
X-GNOME-Bugzilla-Component=general
X-GNOME-Autostart-Phase=WindowManager
X-GNOME-Provides=windowmanager
X-GNOME-Autostart-Notify=true

View File

@ -79,6 +79,8 @@ IGNORE_HFILES= \
iconcache.h \
inlinepixbufs.h \
keybindings-private.h \
menu.h \
metaaccellabel.h \
meta-background-actor-private.h \
meta-background-group-private.h \
meta-module.h \
@ -111,13 +113,6 @@ IGNORE_HFILES= \
xprops.h \
$(NULL)
if !HAVE_WAYLAND
IGNORE_HFILES += \
meta-surface-actor-wayland.h \
wayland \
$(NULL)
endif
MKDB_OPTIONS+=--ignore-files="$(IGNORE_HFILES)"
# Images to copy into HTML directory.
@ -145,7 +140,7 @@ expand_content_files= \
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
GTKDOC_CFLAGS=$(MUTTER_CFLAGS)
GTKDOC_LIBS=$(MUTTER_LIBS) $(top_builddir)/src/libmutter.la
GTKDOC_LIBS=$(MUTTER_LIBS) $(top_builddir)/src/libmutter-wayland.la
# This includes the standard gtk-doc make rules, copied by gtkdocize.
include $(top_srcdir)/gtk-doc.make

View File

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

View File

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

View File

@ -1,12 +1,8 @@
# List of source files containing translatable strings.
# Please keep this file sorted alphabetically.
data/50-mutter-navigation.xml.in
data/50-mutter-system.xml.in
data/50-mutter-windows.xml.in
data/mutter.desktop.in
data/org.gnome.mutter.gschema.xml.in
data/org.gnome.mutter.wayland.gschema.xml.in
src/backends/meta-monitor-manager.c
src/50-mutter-navigation.xml.in
src/50-mutter-system.xml.in
src/50-mutter-windows.xml.in
src/compositor/compositor.c
src/compositor/meta-background.c
src/core/bell.c
@ -16,15 +12,21 @@ src/core/display.c
src/core/errors.c
src/core/keybindings.c
src/core/main.c
src/core/monitor.c
src/core/mutter.c
src/core/prefs.c
src/core/screen.c
src/x11/session.c
src/core/util.c
src/core/window.c
src/x11/window-props.c
src/x11/xprops.c
src/mutter-wayland.desktop.in
src/org.gnome.mutter.gschema.xml.in
src/org.gnome.mutter.wayland.gschema.xml.in
src/ui/frames.c
src/ui/menu.c
src/ui/metaaccellabel.c
src/ui/resizepopup.c
src/ui/theme.c
src/ui/theme-parser.c
src/x11/session.c
src/x11/window-props.c
src/x11/xprops.c

View File

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

733
po/ar.po

File diff suppressed because it is too large Load Diff

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

3703
po/ca.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1687
po/cs.po

File diff suppressed because it is too large Load Diff

1835
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

1931
po/el.po

File diff suppressed because it is too large Load Diff

2308
po/es.po

File diff suppressed because it is too large Load Diff

1808
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

1478
po/fr.po

File diff suppressed because it is too large Load Diff

3214
po/ga.po

File diff suppressed because it is too large Load Diff

1790
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

2017
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

1873
po/hu.po

File diff suppressed because it is too large Load Diff

1287
po/id.po

File diff suppressed because it is too large Load Diff

1741
po/it.po

File diff suppressed because it is too large Load Diff

3436
po/kn.po

File diff suppressed because it is too large Load Diff

1197
po/ko.po

File diff suppressed because it is too large Load Diff

1447
po/lt.po

File diff suppressed because it is too large Load Diff

1501
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

1421
po/nb.po

File diff suppressed because it is too large Load Diff

1194
po/nl.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

1499
po/pa.po

File diff suppressed because it is too large Load Diff

1447
po/pl.po

File diff suppressed because it is too large Load Diff

797
po/pt.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1625
po/ru.po

File diff suppressed because it is too large Load Diff

1720
po/sk.po

File diff suppressed because it is too large Load Diff

789
po/sl.po

File diff suppressed because it is too large Load Diff

1716
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

1132
po/uk.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -17,9 +17,6 @@
<KeyListEntry name="move-to-workspace-4"
_description="Move window to workspace 4" />
<KeyListEntry name="move-to-workspace-last"
_description="Move window to last workspace" />
<KeyListEntry name="move-to-workspace-left"
_description="Move window one workspace to the left" />
@ -45,68 +42,26 @@
_description="Move window one monitor down" />
<KeyListEntry name="switch-applications"
reverse-entry="switch-applications-backward"
_description="Switch applications"/>
<KeyListEntry name="switch-applications-backward"
reverse-entry="switch-applications"
hidden="true"
_description="Switch to previous application"/>
<KeyListEntry name="switch-windows"
reverse-entry="switch-windows-backward"
_description="Switch windows"/>
<KeyListEntry name="switch-windows-backward"
reverse-entry="switch-windows"
hidden="true"
_description="Switch to previous window"/>
<KeyListEntry name="switch-group"
reverse-entry="switch-group-backward"
_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"
reverse-entry="switch-panels-backward"
_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"
reverse-entry="cycle-windows-backward"
_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"
reverse-entry="cycle-group-backward"
_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"
reverse-entry="cycle-panels-backward"
_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"
_description="Hide all normal windows"/>
@ -122,9 +77,6 @@
<KeyListEntry name="switch-to-workspace-4"
_description="Switch to workspace 4" />
<KeyListEntry name="switch-to-workspace-last"
_description="Switch to last workspace" />
<KeyListEntry name="switch-to-workspace-left"
_description="Move to workspace left" />

View File

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

View File

@ -1,69 +1,60 @@
# Flag build for parallelism; see https://savannah.gnu.org/patch/?6905
.AUTOPARALLEL:
lib_LTLIBRARIES = libmutter.la
lib_LTLIBRARIES = libmutter-wayland.la
SUBDIRS=compositor/plugins
EXTRA_DIST =
AM_CPPFLAGS = \
INCLUDES= \
-DCLUTTER_ENABLE_COMPOSITOR_API \
-DCLUTTER_ENABLE_EXPERIMENTAL_API \
-DCOGL_ENABLE_EXPERIMENTAL_API \
-DCOGL_ENABLE_EXPERIMENTAL_2_0_API \
-DCLUTTER_DISABLE_DEPRECATION_WARNINGS \
-DCOGL_DISABLE_DEPRECATION_WARNINGS \
$(MUTTER_CFLAGS) \
$(MUTTER_NATIVE_BACKEND_CFLAGS) \
-I$(builddir) \
-I$(top_builddir) \
-I$(srcdir) \
-I$(srcdir)/backends \
-I$(srcdir)/core \
-I$(srcdir)/ui \
-I$(srcdir)/compositor \
-DMUTTER_LIBEXECDIR=\"$(libexecdir)\" \
-DMUTTER_LOCALEDIR=\"$(localedir)\" \
-DHOST_ALIAS=\"@HOST_ALIAS@\" \
-DMUTTER_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\" \
-DMUTTER_PKGDATADIR=\"$(pkgdatadir)\" \
-DMUTTER_DATADIR=\"$(datadir)\" \
-DG_LOG_DOMAIN=\"mutter\" \
-DSN_API_NOT_YET_FROZEN=1 \
-DMUTTER_MAJOR_VERSION=$(MUTTER_MAJOR_VERSION) \
-DMUTTER_MINOR_VERSION=$(MUTTER_MINOR_VERSION) \
-DMUTTER_MICRO_VERSION=$(MUTTER_MICRO_VERSION) \
-DMUTTER_PLUGIN_API_VERSION=$(MUTTER_PLUGIN_API_VERSION) \
-DMUTTER_PKGLIBDIR=\"$(pkglibdir)\" \
-DMUTTER_PLUGIN_DIR=\"$(MUTTER_PLUGIN_DIR)\" \
-DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\" \
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \
-DXWAYLAND_PATH=\"$(XWAYLAND_PATH)\"
-DXWAYLAND_PATH='"@XWAYLAND_PATH@"'
mutter_built_sources = \
$(dbus_idle_built_sources) \
$(dbus_display_config_built_sources) \
$(dbus_login1_built_sources) \
mutter-enum-types.h \
mutter-enum-types.c
if HAVE_WAYLAND
mutter_built_sources += \
mutter-enum-types.c \
gtk-shell-protocol.c \
gtk-shell-server-protocol.h \
xdg-shell-protocol.c \
xdg-shell-server-protocol.h
endif
wayland_protocols = \
wayland/protocol/gtk-shell.xml \
wayland/protocol/xdg-shell.xml
libmutter_la_SOURCES = \
libmutter_wayland_la_SOURCES = \
backends/meta-backend.c \
meta/meta-backend.h \
backends/meta-backend-private.h \
backends/meta-backend.h \
backends/meta-cursor.c \
backends/meta-cursor.h \
backends/meta-cursor-private.h \
backends/meta-cursor-tracker.c \
backends/meta-cursor-tracker-private.h \
backends/meta-cursor-renderer.c \
backends/meta-cursor-renderer.h \
backends/meta-display-config-shared.h \
backends/meta-idle-monitor.c \
backends/meta-idle-monitor-private.h \
backends/meta-idle-monitor-dbus.c \
@ -74,20 +65,20 @@ libmutter_la_SOURCES = \
backends/meta-monitor-manager.h \
backends/meta-monitor-manager-dummy.c \
backends/meta-monitor-manager-dummy.h \
backends/meta-stage.h \
backends/meta-stage.c \
backends/edid-parse.c \
backends/edid.h \
backends/x11/meta-backend-x11.c \
backends/x11/meta-backend-x11.h \
backends/x11/meta-cursor-renderer-x11.c \
backends/x11/meta-cursor-renderer-x11.h \
backends/native/meta-idle-monitor-native.c \
backends/native/meta-idle-monitor-native.h \
backends/native/meta-monitor-manager-kms.c \
backends/native/meta-monitor-manager-kms.h \
backends/native/meta-weston-launch.c \
backends/native/meta-weston-launch.h \
backends/x11/meta-idle-monitor-xsync.c \
backends/x11/meta-idle-monitor-xsync.h \
backends/x11/meta-monitor-manager-xrandr.c \
backends/x11/meta-monitor-manager-xrandr.h \
core/meta-accel-parse.c \
core/meta-accel-parse.h \
backends/x11/meta-xrandr-shared.h \
core/above-tab-keycode.c \
core/barrier.c \
meta/barrier.h \
core/bell.c \
@ -102,17 +93,11 @@ libmutter_la_SOURCES = \
compositor/compositor.c \
compositor/compositor-private.h \
compositor/meta-background.c \
compositor/meta-background-private.h \
compositor/meta-background-actor.c \
compositor/meta-background-actor-private.h \
compositor/meta-background-image.c \
compositor/meta-background-group.c \
compositor/meta-cullable.c \
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.h \
compositor/meta-plugin.c \
@ -126,6 +111,8 @@ libmutter_la_SOURCES = \
compositor/meta-surface-actor.h \
compositor/meta-surface-actor-x11.c \
compositor/meta-surface-actor-x11.h \
compositor/meta-surface-actor-wayland.c \
compositor/meta-surface-actor-wayland.h \
compositor/meta-texture-rectangle.c \
compositor/meta-texture-rectangle.h \
compositor/meta-texture-tower.c \
@ -141,7 +128,6 @@ libmutter_la_SOURCES = \
meta/compositor.h \
meta/meta-background.h \
meta/meta-background-actor.h \
meta/meta-background-image.h \
meta/meta-background-group.h \
meta/meta-plugin.h \
meta/meta-shadow-factory.h \
@ -164,8 +150,6 @@ libmutter_la_SOURCES = \
core/frame.h \
ui/gradient.c \
meta/gradient.h \
core/meta-gesture-tracker.c \
core/meta-gesture-tracker-private.h \
core/keybindings.c \
core/keybindings-private.h \
core/main.c \
@ -177,7 +161,6 @@ libmutter_la_SOURCES = \
core/screen-private.h \
meta/screen.h \
meta/types.h \
core/restart.c \
core/stack.c \
core/stack.h \
core/stack-tracker.c \
@ -195,6 +178,10 @@ libmutter_la_SOURCES = \
ui/ui.h \
ui/frames.c \
ui/frames.h \
ui/menu.c \
ui/menu.h \
ui/metaaccellabel.c \
ui/metaaccellabel.h \
ui/resizepopup.c \
ui/resizepopup.h \
ui/theme-parser.c \
@ -206,8 +193,6 @@ libmutter_la_SOURCES = \
x11/iconcache.h \
x11/async-getprop.c \
x11/async-getprop.h \
x11/events.c \
x11/events.h \
x11/group-private.h \
x11/group-props.c \
x11/group-props.h \
@ -222,22 +207,13 @@ libmutter_la_SOURCES = \
x11/window-x11-private.h \
x11/xprops.c \
x11/xprops.h \
x11/mutter-Xatomtype.h
if HAVE_WAYLAND
libmutter_la_SOURCES += \
compositor/meta-surface-actor-wayland.c \
compositor/meta-surface-actor-wayland.h \
x11/mutter-Xatomtype.h \
wayland/meta-wayland.c \
wayland/meta-wayland.h \
wayland/meta-wayland-private.h \
wayland/meta-xwayland.c \
wayland/meta-xwayland.h \
wayland/meta-xwayland-private.h \
wayland/meta-wayland-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.h \
wayland/meta-wayland-keyboard.c \
@ -246,43 +222,24 @@ libmutter_la_SOURCES += \
wayland/meta-wayland-pointer.h \
wayland/meta-wayland-seat.c \
wayland/meta-wayland-seat.h \
wayland/meta-wayland-touch.c \
wayland/meta-wayland-touch.h \
wayland/meta-wayland-stage.h \
wayland/meta-wayland-stage.c \
wayland/meta-wayland-surface.c \
wayland/meta-wayland-surface.h \
wayland/meta-wayland-types.h \
wayland/meta-wayland-versions.h \
wayland/meta-wayland-outputs.c \
wayland/meta-wayland-outputs.h \
wayland/window-wayland.c \
wayland/window-wayland.h
endif
if HAVE_NATIVE_BACKEND
libmutter_la_SOURCES += \
backends/native/meta-backend-native.c \
backends/native/meta-backend-native.h \
backends/native/meta-cursor-renderer-native.c \
backends/native/meta-cursor-renderer-native.h \
backends/native/meta-idle-monitor-native.c \
backends/native/meta-idle-monitor-native.h \
backends/native/meta-monitor-manager-kms.c \
backends/native/meta-monitor-manager-kms.h \
backends/native/meta-launcher.c \
backends/native/meta-launcher.h \
backends/native/dbus-utils.c \
backends/native/dbus-utils.h
endif
nodist_libmutter_la_SOURCES = \
nodist_libmutter_wayland_la_SOURCES = \
$(mutter_built_sources)
libmutter_la_LDFLAGS = -no-undefined
libmutter_la_LIBADD = $(MUTTER_LIBS) $(MUTTER_NATIVE_BACKEND_LIBS)
libmutter_wayland_la_LDFLAGS = -no-undefined
libmutter_wayland_la_LIBADD = $(MUTTER_LIBS)
# Headers installed for plugins; introspected information will
# be extracted into Mutter-<version>.gir
libmutterinclude_headers = \
libmutterinclude_base_headers = \
meta/barrier.h \
meta/boxes.h \
meta/common.h \
@ -294,11 +251,9 @@ libmutterinclude_headers = \
meta/group.h \
meta/keybindings.h \
meta/main.h \
meta/meta-backend.h \
meta/meta-background.h \
meta/meta-background-actor.h \
meta/meta-background-image.h \
meta/meta-background-group.h \
meta/meta-background.h \
meta/meta-cursor-tracker.h \
meta/meta-idle-monitor.h \
meta/meta-plugin.h \
@ -313,38 +268,34 @@ libmutterinclude_headers = \
meta/window.h \
meta/workspace.h
libmutterinclude_built_headers = \
meta/meta-version.h
libmutterinclude_base_headers = \
$(libmutterinclude_headers) \
$(libmutterinclude_built_headers)
# Excluded from scanning for introspection but installed
# atomnames.h: macros cause problems for scanning process
libmutterinclude_extra_headers = \
meta/atomnames.h
libmutterincludedir = $(includedir)/mutter/meta
libmutterincludedir = $(includedir)/mutter-wayland/meta
libmutterinclude_HEADERS = \
$(libmutterinclude_headers) \
$(libmutterinclude_base_headers) \
$(libmutterinclude_extra_headers)
nodist_libmutterinclude_HEADERS = \
$(libmutterinclude_built_headers)
bin_PROGRAMS=mutter-wayland
bin_PROGRAMS=mutter
noinst_PROGRAMS=
mutter_wayland_SOURCES = core/mutter.c
mutter_wayland_LDADD = $(MUTTER_LIBS) libmutter-wayland.la
mutter_SOURCES = core/mutter.c
mutter_LDADD = $(MUTTER_LIBS) libmutter.la
bin_PROGRAMS+=mutter-launch
libexec_PROGRAMS = mutter-restart-helper
mutter_restart_helper_SOURCES = core/restart-helper.c
mutter_restart_helper_LDADD = $(MUTTER_LIBS)
mutter_launch_SOURCES = \
backends/native/weston-launch.c \
backends/native/weston-launch.h
include Makefile-tests.am
mutter_launch_CFLAGS = $(MUTTER_LAUNCH_CFLAGS) -DLIBDIR=\"$(libdir)\"
mutter_launch_LDFLAGS = $(MUTTER_LAUNCH_LIBS) -lpam
install-exec-hook:
-chown root $(DESTDIR)$(bindir)/mutter-launch
-chmod u+s $(DESTDIR)$(bindir)/mutter-launch
if HAVE_INTROSPECTION
include $(INTROSPECTION_MAKEFILE)
@ -366,45 +317,83 @@ typelib_DATA = Meta-$(api_version).typelib
INTROSPECTION_GIRS = Meta-$(api_version).gir
Meta-$(api_version).gir: libmutter.la
Meta-$(api_version).gir: libmutter-wayland.la
@META_GIR@_INCLUDES = GObject-2.0 GDesktopEnums-3.0 Gdk-3.0 Gtk-3.0 Clutter-1.0 xlib-2.0 xfixes-4.0 Cogl-1.0
@META_GIR@_EXPORT_PACKAGES = libmutter
@META_GIR@_CFLAGS = $(AM_CPPFLAGS)
@META_GIR@_LIBS = libmutter.la
@META_GIR@_EXPORT_PACKAGES = libmutter-wayland
@META_GIR@_CFLAGS = $(INCLUDES)
@META_GIR@_LIBS = libmutter-wayland.la
@META_GIR@_FILES = \
mutter-enum-types.h \
$(libmutterinclude_base_headers) \
$(filter %.c,$(libmutter_la_SOURCES) $(nodist_libmutter_la_SOURCES))
$(filter %.c,$(libmutter_wayland_la_SOURCES) $(nodist_libmutter_wayland_la_SOURCES))
@META_GIR@_SCANNERFLAGS = --warn-all --warn-error
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-wayland.la
testgradient_LDADD = $(MUTTER_LIBS) libmutter-wayland.la
testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter-wayland.la
@INTLTOOL_DESKTOP_RULE@
desktopfilesdir=$(datadir)/applications
desktopfiles_in_files=mutter-wayland.desktop.in
desktopfiles_files=$(desktopfiles_in_files:.desktop.in=.desktop)
desktopfiles_DATA = $(desktopfiles_files)
xmldir = @GNOME_KEYBINDINGS_KEYSDIR@
xml_in_files = \
50-mutter-navigation.xml.in \
50-mutter-system.xml.in \
50-mutter-windows.xml.in
xml_DATA = $(xml_in_files:.xml.in=.xml)
dbus_idle_built_sources = meta-dbus-idle-monitor.c meta-dbus-idle-monitor.h
gsettings_SCHEMAS = org.gnome.mutter.gschema.xml org.gnome.mutter.wayland.gschema.xml
@INTLTOOL_XML_NOMERGE_RULE@
@GSETTINGS_RULES@
convertdir = $(datadir)/GConf/gsettings
convert_DATA = mutter-schemas.convert
CLEANFILES = \
mutter-wayland.desktop \
mutter-wm.desktop \
org.gnome.mutter.gschema.xml \
org.gnome.mutter.wayland.gschema.xml \
$(xml_DATA) \
$(mutter_built_sources) \
$(typelib_DATA) \
$(gir_DATA)
DISTCLEANFILES = \
$(libmutterinclude_built_headers)
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libmutter.pc
EXTRA_DIST += \
pkgconfig_DATA = libmutter-wayland.pc
EXTRA_DIST=$(desktopfiles_files) \
$(wmproperties_files) \
$(IMAGES) \
$(desktopfiles_in_files) \
$(wmproperties_in_files) \
$(xml_in_files) \
$(wayland_protocols) \
libmutter.pc.in \
org.gnome.mutter.gschema.xml.in \
org.gnome.mutter.wayland.gschema.xml.in \
mutter-schemas.convert \
libmutter-wayland.pc.in \
mutter-enum-types.h.in \
mutter-enum-types.c.in \
org.freedesktop.login1.xml \
org.gnome.Mutter.DisplayConfig.xml \
org.gnome.Mutter.IdleMonitor.xml
BUILT_SOURCES = \
$(mutter_built_sources) \
$(libmutterinclude_built_headers)
BUILT_SOURCES = $(mutter_built_sources)
MUTTER_STAMP_FILES = stamp-mutter-enum-types.h
CLEANFILES += $(MUTTER_STAMP_FILES)
@ -444,15 +433,6 @@ $(dbus_idle_built_sources) : Makefile.am org.gnome.Mutter.IdleMonitor.xml
--c-generate-object-manager \
$(srcdir)/org.gnome.Mutter.IdleMonitor.xml
dbus_login1_built_sources = meta-dbus-login1.c meta-dbus-login1.h
$(dbus_login1_built_sources) : Makefile.am org.freedesktop.login1.xml
$(AM_V_GEN)gdbus-codegen \
--interface-prefix org.freedesktop.login1 \
--c-namespace Login1 \
--generate-c-code meta-dbus-login1 \
$(srcdir)/org.freedesktop.login1.xml
%-protocol.c : $(srcdir)/wayland/protocol/%.xml
$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
%-server-protocol.h : $(srcdir)/wayland/protocol/%.xml

View File

@ -179,7 +179,7 @@ decode_display_parameters (const uchar *edid, MonitorInfo *info)
else if (edid[0x16] == 0)
{
info->width_mm = -1;
info->height_mm = -1;
info->height_mm = -1;
info->aspect_ratio = 100.0 / (edid[0x15] + 99);
}
else if (edid[0x15] == 0)
@ -267,7 +267,7 @@ decode_color_characteristics (const uchar *edid, MonitorInfo *info)
static int
decode_established_timings (const uchar *edid, MonitorInfo *info)
{
static const Timing established[][8] =
static const Timing established[][8] =
{
{
{ 800, 600, 60 },

View File

@ -1,9 +1,9 @@
/* edid.h
*
* Copyright 2007, 2008, Red Hat, Inc.
*
*
* This file is part of the Gnome Library.
*
*
* The Gnome Library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2 of the
@ -13,12 +13,12 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
*
* You should have received a copy of the GNU Library General Public
* License along with the Gnome Library; see the file COPYING.LIB. If not,
* write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
*
* Author: Soren Sandmann <sandmann@redhat.com>
*/
@ -177,7 +177,7 @@ struct MonitorInfo
DetailedTiming detailed_timings[4]; /* If monitor has a preferred
* mode, it is the first one
* (whether it has, is
* determined by the
* determined by the
* preferred_timing_includes
* bit.
*/
@ -189,5 +189,7 @@ struct MonitorInfo
};
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

View File

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

View File

@ -24,387 +24,15 @@
#include "config.h"
#include <meta/meta-backend.h>
#include "meta-backend-private.h"
#include "meta-backend.h"
#include <meta/main.h>
#include "backends/x11/meta-backend-x11.h"
#include "meta-stage.h"
#include <gdk/gdkx.h>
#include <clutter/clutter.h>
#include <clutter/x11/clutter-x11.h>
#ifdef HAVE_NATIVE_BACKEND
#include "backends/native/meta-backend-native.h"
#endif
static MetaBackend *_backend;
/**
* meta_get_backend:
*
* Accessor for the singleton MetaBackend.
*
* Returns: (transfer none): The only #MetaBackend there is.
*/
MetaBackend *
meta_get_backend (void)
{
return _backend;
}
struct _MetaBackendPrivate
{
MetaMonitorManager *monitor_manager;
MetaCursorRenderer *cursor_renderer;
ClutterActor *stage;
};
typedef struct _MetaBackendPrivate MetaBackendPrivate;
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaBackend, meta_backend, G_TYPE_OBJECT);
static void
meta_backend_finalize (GObject *object)
{
MetaBackend *backend = META_BACKEND (object);
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
int i;
g_clear_object (&priv->monitor_manager);
for (i = 0; i <= backend->device_id_max; i++)
{
if (backend->device_monitors[i])
g_object_unref (backend->device_monitors[i]);
}
G_OBJECT_CLASS (meta_backend_parent_class)->finalize (object);
}
static void
meta_backend_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
meta_backend_real_post_init (MetaBackend *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);
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);
{
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 *
meta_backend_real_create_cursor_renderer (MetaBackend *backend)
{
return meta_cursor_renderer_new ();
}
static gboolean
meta_backend_real_grab_device (MetaBackend *backend,
int device_id,
uint32_t timestamp)
{
/* Do nothing */
return TRUE;
}
static gboolean
meta_backend_real_ungrab_device (MetaBackend *backend,
int device_id,
uint32_t timestamp)
{
/* Do nothing */
return TRUE;
}
static void
meta_backend_real_update_screen_size (MetaBackend *backend,
int width, int height)
{
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 */
}
static void
meta_backend_class_init (MetaBackendClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_backend_finalize;
klass->post_init = meta_backend_real_post_init;
klass->create_cursor_renderer = meta_backend_real_create_cursor_renderer;
klass->grab_device = meta_backend_real_grab_device;
klass->ungrab_device = meta_backend_real_ungrab_device;
klass->update_screen_size = meta_backend_real_update_screen_size;
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
meta_backend_init (MetaBackend *backend)
{
_backend = backend;
}
static void
meta_backend_post_init (MetaBackend *backend)
{
META_BACKEND_GET_CLASS (backend)->post_init (backend);
}
/**
* meta_backend_get_idle_monitor: (skip)
*/
MetaIdleMonitor *
meta_backend_get_idle_monitor (MetaBackend *backend,
int device_id)
{
g_return_val_if_fail (device_id >= 0 && device_id < 256, NULL);
return backend->device_monitors[device_id];
}
/**
* meta_backend_get_monitor_manager: (skip)
*/
MetaMonitorManager *
meta_backend_get_monitor_manager (MetaBackend *backend)
{
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
return priv->monitor_manager;
}
/**
* meta_backend_get_cursor_renderer: (skip)
*/
MetaCursorRenderer *
meta_backend_get_cursor_renderer (MetaBackend *backend)
{
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
return priv->cursor_renderer;
}
/**
* meta_backend_grab_device: (skip)
*/
gboolean
meta_backend_grab_device (MetaBackend *backend,
int device_id,
uint32_t timestamp)
{
return META_BACKEND_GET_CLASS (backend)->grab_device (backend, device_id, timestamp);
}
/**
* meta_backend_ungrab_device: (skip)
*/
gboolean
meta_backend_ungrab_device (MetaBackend *backend,
int device_id,
uint32_t timestamp)
{
return META_BACKEND_GET_CLASS (backend)->ungrab_device (backend, device_id, timestamp);
}
/**
* meta_backend_warp_pointer: (skip)
*/
void
meta_backend_warp_pointer (MetaBackend *backend,
int x,
int 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
get_backend_type (void)
{
#if defined(CLUTTER_WINDOWING_X11)
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_X11))
return META_TYPE_BACKEND_X11;
#endif
#if defined(CLUTTER_WINDOWING_EGL) && defined(HAVE_NATIVE_BACKEND)
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
return META_TYPE_BACKEND_NATIVE;
#endif
g_assert_not_reached ();
}
static void
meta_create_backend (void)
{
/* meta_backend_init() above install the backend globally so
* so meta_get_backend() works even during initialization. */
g_object_new (get_backend_type (), NULL);
}
#include "backends/native/meta-weston-launch.h"
#include <meta/util.h>
/* Mutter is responsible for pulling events off the X queue, so Clutter
* doesn't need (and shouldn't) run its normal event source which polls
@ -454,30 +82,76 @@ static GSourceFuncs event_funcs = {
event_dispatch
};
/**
* meta_clutter_init: (skip)
*/
static MetaLauncher *launcher;
void
meta_clutter_init (void)
{
ClutterSettings *clutter_settings;
GSource *source;
meta_create_backend ();
/* When running as an X11 compositor, we install our own event filter and
* pass events to Clutter explicitly, so we need to prevent Clutter from
* handling our events.
*
* However, when running as a Wayland compostior under X11 nested, Clutter
* Clutter needs to see events related to its own window. We need to
* eventually replace this with a proper frontend / backend split: Clutter
* under nested is connecting to the "host X server" to get its events it
* needs to put up a window, and GTK+ is connecting to the "inner X server".
* The two would the same in the X11 compositor case, but not when running
* XWayland as a Wayland compositor.
*/
if (!meta_is_wayland_compositor ())
{
clutter_x11_set_display (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
clutter_x11_disable_event_retrieval ();
}
/* If we're running on bare metal, we're a display server,
* so start talking to weston-launch. */
#if defined(CLUTTER_WINDOWING_EGL)
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
launcher = meta_launcher_new ();
#endif
if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
g_error ("Unable to initialize Clutter.\n");
/*
* 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));
g_source_attach (source, NULL);
g_source_unref (source);
meta_backend_post_init (_backend);
}
gboolean
meta_activate_vt (int vt, GError **error)
{
if (launcher)
return meta_launcher_activate_vt (launcher, vt, error);
else
{
g_debug ("Ignoring VT switch keybinding, not running as display server");
return TRUE;
}
}
/**
* meta_activate_session:
*
* Tells mutter to activate the session. When mutter is a
* Wayland compositor, this tells logind to switch over to
* the new session.
*/
gboolean
meta_activate_session (void)
{
GError *error = NULL;
if (!meta_launcher_activate_vt (launcher, -1, &error))
{
g_warning ("Could not activate session: %s\n", error->message);
g_error_free (error);
return FALSE;
}
return TRUE;
}

View File

@ -22,11 +22,13 @@
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#ifndef DBUS_UTILS_H
#define DBUS_UTILS_H
#ifndef META_BACKEND_H
#define META_BACKEND_H
char *
get_escaped_dbus_path (const char *prefix,
const char *component);
#include <glib-object.h>
#endif /* DBUS_UTILS_H */
void meta_clutter_init (void);
gboolean meta_activate_vt (int vt, GError **error);
#endif /* META_BACKEND_H */

View File

@ -36,7 +36,6 @@ typedef struct {
struct _MetaCursorReference {
int ref_count;
MetaCursor cursor;
MetaCursorImage image;
};

View File

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

View File

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

View File

@ -23,20 +23,35 @@
#define META_CURSOR_TRACKER_PRIVATE_H
#include <meta/meta-cursor-tracker.h>
#include <wayland-server.h>
#include "meta-cursor.h"
#include "meta-cursor-renderer.h"
struct _MetaCursorTracker {
GObject parent_instance;
MetaCursorRenderer *renderer;
MetaScreen *screen;
gboolean is_showing;
gboolean has_hw_cursor;
/* The cursor tracker stores the cursor for the current grab
* operation, the cursor for the window with pointer focus, and
* the cursor for the root window, which contains either the
* default arrow cursor or the 'busy' hourglass if we're launching
* an app.
*
* We choose the first one available -- if there's a grab cursor,
* we choose that cursor, if there's window cursor, we choose that,
* otherwise we choose the root cursor.
*
* The displayed_cursor contains the chosen cursor.
*/
MetaCursorReference *displayed_cursor;
/* Wayland clients can set a NULL buffer as their cursor
MetaCursorReference *grab_cursor;
/* Wayland clients can set a NULL buffer as their cursor
* explicitly, which means that we shouldn't display anything.
* So, we can't simply store a NULL in window_cursor to
* determine an unset window cursor; we need an extra boolean.
@ -46,8 +61,16 @@ struct _MetaCursorTracker {
MetaCursorReference *root_cursor;
/* The cursor from the X11 server. */
MetaCursorReference *xfixes_cursor;
MetaCursorReference *theme_cursors[META_CURSOR_LAST];
int current_x, current_y;
MetaRectangle current_rect;
MetaRectangle previous_rect;
gboolean previous_is_valid;
CoglPipeline *pipeline;
int drm_fd;
struct gbm_device *gbm;
};
struct _MetaCursorTrackerClass {
@ -57,6 +80,8 @@ struct _MetaCursorTrackerClass {
gboolean meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
XEvent *xevent);
void meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker,
MetaCursorReference *cursor);
void meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
MetaCursorReference *cursor);
void meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker);
@ -66,7 +91,8 @@ void meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
void meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
int new_x,
int new_y);
void meta_cursor_tracker_paint (MetaCursorTracker *tracker);
MetaCursorReference * meta_cursor_tracker_get_displayed_cursor (MetaCursorTracker *tracker);
void meta_cursor_tracker_force_update (MetaCursorTracker *tracker);
#endif

View File

@ -1,8 +1,8 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
/*
* Copyright 2013 Red Hat, Inc.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
@ -12,7 +12,7 @@
* 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/>.
*
@ -34,70 +34,42 @@
#include <meta/errors.h>
#include <cogl/cogl.h>
#include <cogl/cogl-wayland-server.h>
#include <clutter/clutter.h>
#include <gbm.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include "meta-backend-private.h"
#include "meta-cursor-private.h"
#include "meta-cursor-tracker-private.h"
#include "screen-private.h"
#include "meta-monitor-manager.h"
#include "wayland/meta-wayland-private.h"
G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT);
enum {
CURSOR_CHANGED,
LAST_SIGNAL
CURSOR_CHANGED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
static MetaCursorReference *
get_displayed_cursor (MetaCursorTracker *tracker)
{
MetaDisplay *display = meta_get_display ();
if (!tracker->is_showing)
return NULL;
if (meta_display_windows_are_interactable (display))
{
if (tracker->has_window_cursor)
return tracker->window_cursor;
}
return tracker->root_cursor;
}
static void
update_displayed_cursor (MetaCursorTracker *tracker)
{
meta_cursor_renderer_set_cursor (tracker->renderer, tracker->displayed_cursor);
}
static void
sync_cursor (MetaCursorTracker *tracker)
{
MetaCursorReference *displayed_cursor = get_displayed_cursor (tracker);
if (tracker->displayed_cursor == displayed_cursor)
return;
g_clear_pointer (&tracker->displayed_cursor, meta_cursor_reference_unref);
if (displayed_cursor)
tracker->displayed_cursor = meta_cursor_reference_ref (displayed_cursor);
update_displayed_cursor (tracker);
g_signal_emit (tracker, signals[CURSOR_CHANGED], 0);
}
static void meta_cursor_tracker_set_crtc_has_hw_cursor (MetaCursorTracker *tracker,
MetaCRTC *crtc,
gboolean has_hw_cursor);
static void sync_cursor (MetaCursorTracker *tracker);
static void
meta_cursor_tracker_init (MetaCursorTracker *self)
{
MetaBackend *backend = meta_get_backend ();
/* (JS) Best (?) that can be assumed since XFixes doesn't provide a way of
detecting if the system mouse cursor is showing or not.
self->renderer = meta_backend_get_cursor_renderer (backend);
On wayland we start with the cursor showing
*/
self->is_showing = TRUE;
}
@ -105,12 +77,22 @@ static void
meta_cursor_tracker_finalize (GObject *object)
{
MetaCursorTracker *self = META_CURSOR_TRACKER (object);
int i;
if (self->displayed_cursor)
meta_cursor_reference_unref (self->displayed_cursor);
if (self->root_cursor)
meta_cursor_reference_unref (self->root_cursor);
for (i = 0; i < META_CURSOR_LAST; i++)
if (self->theme_cursors[i])
meta_cursor_reference_unref (self->theme_cursors[i]);
if (self->pipeline)
cogl_object_unref (self->pipeline);
if (self->gbm)
gbm_device_destroy (self->gbm);
G_OBJECT_CLASS (meta_cursor_tracker_parent_class)->finalize (object);
}
@ -129,13 +111,80 @@ meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass)
G_TYPE_NONE, 0);
}
static MetaCursorTracker *
meta_cursor_tracker_new (void)
static void
on_monitors_changed (MetaMonitorManager *monitors,
MetaCursorTracker *tracker)
{
return g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
MetaCRTC *crtcs;
unsigned int i, n_crtcs;
if (!tracker->has_hw_cursor)
return;
/* Go through the new list of monitors, find out where the cursor is */
meta_monitor_manager_get_resources (monitors, NULL, NULL, &crtcs, &n_crtcs, NULL, NULL);
for (i = 0; i < n_crtcs; i++)
{
MetaRectangle *rect = &crtcs[i].rect;
gboolean has;
has = meta_rectangle_overlap (&tracker->current_rect, rect);
/* Need to do it unconditionally here, our tracking is
wrong because we reloaded the CRTCs */
meta_cursor_tracker_set_crtc_has_hw_cursor (tracker, &crtcs[i], has);
}
}
static MetaCursorTracker *_cursor_tracker;
static MetaCursorTracker *
make_wayland_cursor_tracker (MetaScreen *screen)
{
MetaWaylandCompositor *compositor;
CoglContext *ctx;
MetaMonitorManager *monitors;
MetaCursorTracker *self;
self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
self->screen = screen;
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
self->pipeline = cogl_pipeline_new (ctx);
compositor = meta_wayland_compositor_get_default ();
compositor->seat->cursor_tracker = self;
meta_cursor_tracker_update_position (self,
wl_fixed_to_int (compositor->seat->pointer.x),
wl_fixed_to_int (compositor->seat->pointer.y));
#if defined(CLUTTER_WINDOWING_EGL)
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
{
CoglRenderer *cogl_renderer = cogl_display_get_renderer (cogl_context_get_display (ctx));
self->drm_fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
self->gbm = gbm_create_device (self->drm_fd);
}
#endif
monitors = meta_monitor_manager_get ();
g_signal_connect_object (monitors, "monitors-changed",
G_CALLBACK (on_monitors_changed), self, 0);
return self;
}
static MetaCursorTracker *
make_x11_cursor_tracker (MetaScreen *screen)
{
MetaCursorTracker *self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
self->screen = screen;
XFixesSelectCursorInput (screen->display->xdisplay,
screen->xroot,
XFixesDisplayCursorNotifyMask);
return self;
}
/**
* meta_cursor_tracker_get_for_screen:
@ -148,10 +197,18 @@ static MetaCursorTracker *_cursor_tracker;
MetaCursorTracker *
meta_cursor_tracker_get_for_screen (MetaScreen *screen)
{
if (!_cursor_tracker)
_cursor_tracker = meta_cursor_tracker_new ();
MetaCursorTracker *self;
return _cursor_tracker;
if (screen->cursor_tracker)
return screen->cursor_tracker;
if (meta_is_wayland_compositor ())
self = make_wayland_cursor_tracker (screen);
else
self = make_x11_cursor_tracker (screen);
screen->cursor_tracker = self;
return self;
}
static void
@ -170,20 +227,19 @@ gboolean
meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
XEvent *xevent)
{
MetaDisplay *display = meta_get_display ();
XFixesCursorNotifyEvent *notify_event;
if (meta_is_wayland_compositor ())
return FALSE;
if (xevent->xany.type != display->xfixes_event_base + XFixesCursorNotify)
if (xevent->xany.type != tracker->screen->display->xfixes_event_base + XFixesCursorNotify)
return FALSE;
notify_event = (XFixesCursorNotifyEvent *)xevent;
if (notify_event->subtype != XFixesDisplayCursorNotify)
return FALSE;
g_clear_pointer (&tracker->xfixes_cursor, meta_cursor_reference_unref);
set_window_cursor (tracker, FALSE, NULL);
return TRUE;
}
@ -207,17 +263,16 @@ meta_cursor_reference_take_texture (CoglTexture2D *texture,
static void
ensure_xfixes_cursor (MetaCursorTracker *tracker)
{
MetaDisplay *display = meta_get_display ();
XFixesCursorImage *cursor_image;
CoglTexture2D *sprite;
guint8 *cursor_data;
gboolean free_cursor_data;
CoglContext *ctx;
if (tracker->xfixes_cursor)
if (tracker->has_window_cursor)
return;
cursor_image = XFixesGetCursorImage (display->xdisplay);
cursor_image = XFixesGetCursorImage (tracker->screen->display->xdisplay);
if (!cursor_image)
return;
@ -264,7 +319,7 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
MetaCursorReference *cursor = meta_cursor_reference_take_texture (sprite,
cursor_image->xhot,
cursor_image->yhot);
tracker->xfixes_cursor = cursor;
set_window_cursor (tracker, TRUE, cursor);
}
XFree (cursor_image);
}
@ -277,22 +332,13 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
CoglTexture *
meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker)
{
MetaCursorReference *cursor;
g_return_val_if_fail (META_IS_CURSOR_TRACKER (tracker), NULL);
if (meta_is_wayland_compositor ())
{
cursor = tracker->displayed_cursor;
}
else
{
ensure_xfixes_cursor (tracker);
cursor = tracker->xfixes_cursor;
}
if (!meta_is_wayland_compositor ())
ensure_xfixes_cursor (tracker);
if (cursor)
return meta_cursor_reference_get_cogl_texture (cursor, NULL, NULL);
if (tracker->displayed_cursor)
return meta_cursor_reference_get_cogl_texture (tracker->displayed_cursor, NULL, NULL);
else
return NULL;
}
@ -309,22 +355,13 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
int *x,
int *y)
{
MetaCursorReference *cursor;
g_return_if_fail (META_IS_CURSOR_TRACKER (tracker));
if (meta_is_wayland_compositor ())
{
cursor = tracker->displayed_cursor;
}
else
{
ensure_xfixes_cursor (tracker);
cursor = tracker->xfixes_cursor;
}
if (!meta_is_wayland_compositor ())
ensure_xfixes_cursor (tracker);
if (cursor)
meta_cursor_reference_get_cogl_texture (cursor, x, y);
if (tracker->displayed_cursor)
meta_cursor_reference_get_cogl_texture (tracker->displayed_cursor, x, y);
else
{
if (x)
@ -334,6 +371,17 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
}
}
void
meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker,
MetaCursorReference *cursor)
{
g_clear_pointer (&tracker->grab_cursor, meta_cursor_reference_unref);
if (cursor)
tracker->grab_cursor = meta_cursor_reference_ref (cursor);
sync_cursor (tracker);
}
void
meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
MetaCursorReference *cursor)
@ -358,6 +406,184 @@ meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
sync_cursor (tracker);
}
static gboolean
should_have_hw_cursor (MetaCursorTracker *tracker)
{
if (tracker->displayed_cursor)
return (meta_cursor_reference_get_gbm_bo (tracker->displayed_cursor, NULL, NULL) != NULL);
else
return FALSE;
}
static void
update_hw_cursor (MetaCursorTracker *tracker)
{
MetaMonitorManager *monitors;
MetaCRTC *crtcs;
unsigned int i, n_crtcs;
gboolean enabled;
enabled = should_have_hw_cursor (tracker);
tracker->has_hw_cursor = enabled;
monitors = meta_monitor_manager_get ();
meta_monitor_manager_get_resources (monitors, NULL, NULL, &crtcs, &n_crtcs, NULL, NULL);
for (i = 0; i < n_crtcs; i++)
{
MetaRectangle *rect = &crtcs[i].rect;
gboolean has;
has = enabled && meta_rectangle_overlap (&tracker->current_rect, rect);
if (has || crtcs[i].has_hw_cursor)
meta_cursor_tracker_set_crtc_has_hw_cursor (tracker, &crtcs[i], has);
}
}
static void
move_hw_cursor (MetaCursorTracker *tracker)
{
MetaMonitorManager *monitors;
MetaCRTC *crtcs;
unsigned int i, n_crtcs;
monitors = meta_monitor_manager_get ();
meta_monitor_manager_get_resources (monitors, NULL, NULL, &crtcs, &n_crtcs, NULL, NULL);
g_assert (tracker->has_hw_cursor);
for (i = 0; i < n_crtcs; i++)
{
MetaRectangle *rect = &crtcs[i].rect;
gboolean has;
has = meta_rectangle_overlap (&tracker->current_rect, rect);
if (has != crtcs[i].has_hw_cursor)
meta_cursor_tracker_set_crtc_has_hw_cursor (tracker, &crtcs[i], has);
if (has)
drmModeMoveCursor (tracker->drm_fd, crtcs[i].crtc_id,
tracker->current_rect.x - rect->x,
tracker->current_rect.y - rect->y);
}
}
static MetaCursorReference *
get_displayed_cursor (MetaCursorTracker *tracker)
{
if (!tracker->is_showing)
return NULL;
if (tracker->grab_cursor)
return tracker->grab_cursor;
if (tracker->has_window_cursor)
return tracker->window_cursor;
return tracker->root_cursor;
}
static void
update_displayed_cursor (MetaCursorTracker *tracker)
{
if (meta_is_wayland_compositor ())
{
if (tracker->displayed_cursor)
{
CoglTexture *texture = meta_cursor_reference_get_cogl_texture (tracker->displayed_cursor, NULL, NULL);
cogl_pipeline_set_layer_texture (tracker->pipeline, 0, texture);
}
else
cogl_pipeline_set_layer_texture (tracker->pipeline, 0, NULL);
update_hw_cursor (tracker);
}
}
static void
sync_displayed_cursor (MetaCursorTracker *tracker)
{
MetaCursorReference *displayed_cursor = get_displayed_cursor (tracker);
if (tracker->displayed_cursor == displayed_cursor)
return;
g_clear_pointer (&tracker->displayed_cursor, meta_cursor_reference_unref);
if (displayed_cursor)
tracker->displayed_cursor = meta_cursor_reference_ref (displayed_cursor);
update_displayed_cursor (tracker);
g_signal_emit (tracker, signals[CURSOR_CHANGED], 0);
}
static void
meta_cursor_tracker_queue_redraw (MetaCursorTracker *tracker)
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
ClutterActor *stage = compositor->stage;
cairo_rectangle_int_t clip;
g_assert (meta_is_wayland_compositor ());
/* Clear the location the cursor was at before, if we need to. */
if (tracker->previous_is_valid)
{
clip.x = tracker->previous_rect.x;
clip.y = tracker->previous_rect.y;
clip.width = tracker->previous_rect.width;
clip.height = tracker->previous_rect.height;
clutter_actor_queue_redraw_with_clip (stage, &clip);
tracker->previous_is_valid = FALSE;
}
if (tracker->has_hw_cursor || !tracker->displayed_cursor)
return;
clip.x = tracker->current_rect.x;
clip.y = tracker->current_rect.y;
clip.width = tracker->current_rect.width;
clip.height = tracker->current_rect.height;
clutter_actor_queue_redraw_with_clip (stage, &clip);
}
static void
sync_cursor (MetaCursorTracker *tracker)
{
MetaCursorReference *displayed_cursor;
sync_displayed_cursor (tracker);
displayed_cursor = tracker->displayed_cursor;
if (displayed_cursor)
{
CoglTexture *texture;
int hot_x, hot_y;
texture = meta_cursor_reference_get_cogl_texture (displayed_cursor, &hot_x, &hot_y);
tracker->current_rect.x = tracker->current_x - hot_x;
tracker->current_rect.y = tracker->current_y - hot_y;
tracker->current_rect.width = cogl_texture_get_width (COGL_TEXTURE (texture));
tracker->current_rect.height = cogl_texture_get_height (COGL_TEXTURE (texture));
}
else
{
tracker->current_rect.x = 0;
tracker->current_rect.y = 0;
tracker->current_rect.width = 0;
tracker->current_rect.height = 0;
}
if (meta_is_wayland_compositor ())
{
if (tracker->has_hw_cursor)
move_hw_cursor (tracker);
else
meta_cursor_tracker_queue_redraw (tracker);
}
}
void
meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
int new_x,
@ -365,7 +591,61 @@ meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
{
g_assert (meta_is_wayland_compositor ());
meta_cursor_renderer_set_position (tracker->renderer, new_x, new_y);
tracker->current_x = new_x;
tracker->current_y = new_y;
sync_cursor (tracker);
}
void
meta_cursor_tracker_paint (MetaCursorTracker *tracker)
{
g_assert (meta_is_wayland_compositor ());
if (tracker->has_hw_cursor || !tracker->displayed_cursor)
return;
cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (),
tracker->pipeline,
tracker->current_rect.x,
tracker->current_rect.y,
tracker->current_rect.x +
tracker->current_rect.width,
tracker->current_rect.y +
tracker->current_rect.height);
tracker->previous_rect = tracker->current_rect;
tracker->previous_is_valid = TRUE;
}
static void
meta_cursor_tracker_set_crtc_has_hw_cursor (MetaCursorTracker *tracker,
MetaCRTC *crtc,
gboolean has)
{
if (has)
{
MetaCursorReference *displayed_cursor = tracker->displayed_cursor;
struct gbm_bo *bo;
union gbm_bo_handle handle;
int width, height;
int hot_x, hot_y;
bo = meta_cursor_reference_get_gbm_bo (displayed_cursor, &hot_x, &hot_y);
handle = gbm_bo_get_handle (bo);
width = gbm_bo_get_width (bo);
height = gbm_bo_get_height (bo);
drmModeSetCursor2 (tracker->drm_fd, crtc->crtc_id, handle.u32,
width, height, hot_x, hot_y);
crtc->has_hw_cursor = TRUE;
}
else
{
drmModeSetCursor2 (tracker->drm_fd, crtc->crtc_id, 0, 0, 0, 0, 0);
crtc->has_hw_cursor = FALSE;
}
}
static void
@ -433,11 +713,26 @@ meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker,
return;
tracker->is_showing = visible;
sync_cursor (tracker);
if (meta_is_wayland_compositor ())
{
sync_cursor (tracker);
}
else
{
if (visible)
XFixesShowCursor (tracker->screen->display->xdisplay,
tracker->screen->xroot);
else
XFixesHideCursor (tracker->screen->display->xdisplay,
tracker->screen->xroot);
}
}
MetaCursorReference *
meta_cursor_tracker_get_displayed_cursor (MetaCursorTracker *tracker)
void
meta_cursor_tracker_force_update (MetaCursorTracker *tracker)
{
return tracker->displayed_cursor;
g_assert (meta_is_wayland_compositor ());
update_hw_cursor (tracker);
sync_cursor (tracker);
}

View File

@ -27,11 +27,7 @@
#include "display-private.h"
#include "screen-private.h"
#include "meta-backend-private.h"
#ifdef HAVE_NATIVE_BACKEND
#include "backends/native/meta-cursor-renderer-native.h"
#endif
#include "meta-cursor-tracker-private.h" /* for tracker->gbm */
#include <string.h>
@ -39,9 +35,7 @@
#include <X11/extensions/Xfixes.h>
#include <X11/Xcursor/Xcursor.h>
#ifdef HAVE_WAYLAND
#include <cogl/cogl-wayland-server.h>
#endif
MetaCursorReference *
meta_cursor_reference_ref (MetaCursorReference *self)
@ -76,148 +70,170 @@ meta_cursor_reference_unref (MetaCursorReference *self)
meta_cursor_reference_free (self);
}
static const char *
translate_meta_cursor (MetaCursor cursor)
static void
translate_meta_cursor (MetaCursor cursor,
guint *glyph_out,
const char **name_out)
{
guint glyph = XC_num_glyphs;
const char *name = NULL;
switch (cursor)
{
case META_CURSOR_DEFAULT:
return "left_ptr";
glyph = XC_left_ptr;
break;
case META_CURSOR_NORTH_RESIZE:
return "top_side";
glyph = XC_top_side;
break;
case META_CURSOR_SOUTH_RESIZE:
return "bottom_side";
glyph = XC_bottom_side;
break;
case META_CURSOR_WEST_RESIZE:
return "left_side";
glyph = XC_left_side;
break;
case META_CURSOR_EAST_RESIZE:
return "right_side";
glyph = XC_right_side;
break;
case META_CURSOR_SE_RESIZE:
return "bottom_right_corner";
glyph = XC_bottom_right_corner;
break;
case META_CURSOR_SW_RESIZE:
return "bottom_left_corner";
glyph = XC_bottom_left_corner;
break;
case META_CURSOR_NE_RESIZE:
return "top_right_corner";
glyph = XC_top_right_corner;
break;
case META_CURSOR_NW_RESIZE:
return "top_left_corner";
glyph = XC_top_left_corner;
break;
case META_CURSOR_MOVE_OR_RESIZE_WINDOW:
return "fleur";
glyph = XC_fleur;
break;
case META_CURSOR_BUSY:
return "watch";
glyph = XC_watch;
break;
case META_CURSOR_DND_IN_DRAG:
return "dnd-none";
name = "dnd-none";
break;
case META_CURSOR_DND_MOVE:
return "dnd-move";
name = "dnd-move";
break;
case META_CURSOR_DND_COPY:
return "dnd-copy";
name = "dnd-copy";
break;
case META_CURSOR_DND_UNSUPPORTED_TARGET:
return "dnd-none";
name = "dnd-none";
break;
case META_CURSOR_POINTING_HAND:
return "hand2";
glyph = XC_hand2;
break;
case META_CURSOR_CROSSHAIR:
return "crosshair";
glyph = XC_crosshair;
break;
case META_CURSOR_IBEAM:
return "xterm";
glyph = XC_xterm;
break;
default:
g_assert_not_reached ();
glyph = 0; /* silence compiler */
break;
}
g_assert_not_reached ();
*glyph_out = glyph;
*name_out = name;
}
static Cursor
load_cursor_on_server (MetaDisplay *display,
MetaCursor cursor)
{
Cursor xcursor;
guint glyph;
const char *name;
translate_meta_cursor (cursor, &glyph, &name);
if (name != NULL)
xcursor = XcursorLibraryLoadCursor (display->xdisplay, name);
else
xcursor = XCreateFontCursor (display->xdisplay, glyph);
return xcursor;
}
Cursor
meta_cursor_create_x_cursor (Display *xdisplay,
MetaCursor cursor)
meta_display_create_x_cursor (MetaDisplay *display,
MetaCursor cursor)
{
return XcursorLibraryLoadCursor (xdisplay, translate_meta_cursor (cursor));
return load_cursor_on_server (display, cursor);
}
static XcursorImage *
load_cursor_on_client (MetaCursor cursor)
load_cursor_on_client (MetaDisplay *display,
MetaCursor cursor)
{
return XcursorLibraryLoadImage (translate_meta_cursor (cursor),
meta_prefs_get_cursor_theme (),
meta_prefs_get_cursor_size ());
}
XcursorImage *image;
guint glyph;
const char *name;
const char *theme = XcursorGetTheme (display->xdisplay);
int size = XcursorGetDefaultSize (display->xdisplay);
static void
get_hardware_cursor_size (uint64_t *cursor_width, uint64_t *cursor_height)
{
#ifdef HAVE_NATIVE_BACKEND
MetaBackend *meta_backend = meta_get_backend ();
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend);
translate_meta_cursor (cursor, &glyph, &name);
if (META_IS_CURSOR_RENDERER_NATIVE (renderer))
{
meta_cursor_renderer_native_get_cursor_size (META_CURSOR_RENDERER_NATIVE (renderer), cursor_width, cursor_height);
return;
}
#endif
if (name != NULL)
image = XcursorLibraryLoadImage (name, theme, size);
else
image = XcursorShapeLoadImage (glyph, theme, size);
g_assert_not_reached ();
return image;
}
static void
meta_cursor_image_load_gbm_buffer (struct gbm_device *gbm,
MetaCursorImage *image,
uint8_t *pixels,
uint width,
uint height,
int width,
int height,
int rowstride,
uint32_t gbm_format)
{
uint64_t cursor_width, cursor_height;
get_hardware_cursor_size (&cursor_width, &cursor_height);
if (width > cursor_width || height > cursor_height)
if (width > 64 || height > 64)
{
meta_warning ("Invalid theme cursor size (must be at most %ux%u)\n",
(unsigned int)cursor_width, (unsigned int)cursor_height);
meta_warning ("Invalid theme cursor size (must be at most 64x64)\n");
return;
}
if (gbm_device_is_format_supported (gbm, gbm_format,
GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE))
GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE))
{
uint8_t buf[4 * cursor_width * cursor_height];
uint i;
uint8_t buf[4 * 64 * 64];
int i;
image->bo = gbm_bo_create (gbm, cursor_width, cursor_height,
gbm_format, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
image->bo = gbm_bo_create (gbm, 64, 64,
gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
memset (buf, 0, sizeof(buf));
for (i = 0; i < height; i++)
memcpy (buf + i * 4 * 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
meta_warning ("HW cursor for format %d not supported\n", gbm_format);
}
static struct gbm_device *
get_gbm_device (void)
{
#ifdef HAVE_NATIVE_BACKEND
MetaBackend *meta_backend = meta_get_backend ();
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend);
if (META_IS_CURSOR_RENDERER_NATIVE (renderer))
return meta_cursor_renderer_native_get_gbm_device (META_CURSOR_RENDERER_NATIVE (renderer));
#endif
return NULL;
}
static void
meta_cursor_image_load_from_xcursor_image (MetaCursorImage *image,
meta_cursor_image_load_from_xcursor_image (MetaCursorTracker *tracker,
MetaCursorImage *image,
XcursorImage *xc_image)
{
uint width, height, rowstride;
int width, height, rowstride;
CoglPixelFormat cogl_format;
uint32_t gbm_format;
ClutterBackend *clutter_backend;
CoglContext *cogl_context;
struct gbm_device *gbm;
width = xc_image->width;
height = xc_image->height;
@ -242,9 +258,8 @@ meta_cursor_image_load_from_xcursor_image (MetaCursorImage *image,
(uint8_t *) xc_image->pixels,
NULL);
gbm = get_gbm_device ();
if (gbm)
meta_cursor_image_load_gbm_buffer (gbm,
if (tracker->gbm)
meta_cursor_image_load_gbm_buffer (tracker->gbm,
image,
(uint8_t *) xc_image->pixels,
width, height, rowstride,
@ -252,39 +267,39 @@ meta_cursor_image_load_from_xcursor_image (MetaCursorImage *image,
}
MetaCursorReference *
meta_cursor_reference_from_theme (MetaCursor cursor)
meta_cursor_reference_from_theme (MetaCursorTracker *tracker,
MetaCursor cursor)
{
MetaCursorReference *self;
XcursorImage *image;
image = load_cursor_on_client (cursor);
if (tracker->theme_cursors[cursor])
return meta_cursor_reference_ref (tracker->theme_cursors[cursor]);
image = load_cursor_on_client (tracker->screen->display, cursor);
if (!image)
return NULL;
self = g_slice_new0 (MetaCursorReference);
self->ref_count = 1;
self->cursor = cursor;
meta_cursor_image_load_from_xcursor_image (&self->image, image);
meta_cursor_image_load_from_xcursor_image (tracker, &self->image, image);
XcursorImageDestroy (image);
return self;
}
#ifdef HAVE_WAYLAND
static void
meta_cursor_image_load_from_buffer (MetaCursorImage *image,
meta_cursor_image_load_from_buffer (MetaCursorTracker *tracker,
MetaCursorImage *image,
struct wl_resource *buffer,
int hot_x,
int hot_y)
{
struct gbm_device *gbm = get_gbm_device ();
ClutterBackend *backend;
CoglContext *cogl_context;
struct wl_shm_buffer *shm_buffer;
uint32_t gbm_format;
uint64_t cursor_width, cursor_height;
uint width, height;
int width, height;
image->hot_x = hot_x;
image->hot_y = hot_y;
@ -300,7 +315,7 @@ meta_cursor_image_load_from_buffer (MetaCursorImage *image,
shm_buffer = wl_shm_buffer_get (buffer);
if (shm_buffer)
{
if (gbm)
if (tracker->gbm)
{
int rowstride = wl_shm_buffer_get_stride (shm_buffer);
@ -326,7 +341,7 @@ meta_cursor_image_load_from_buffer (MetaCursorImage *image,
gbm_format = GBM_FORMAT_ARGB8888;
}
meta_cursor_image_load_gbm_buffer (gbm,
meta_cursor_image_load_gbm_buffer (tracker->gbm,
image,
(uint8_t *) wl_shm_buffer_get_data (shm_buffer),
width, height, rowstride,
@ -335,23 +350,22 @@ meta_cursor_image_load_from_buffer (MetaCursorImage *image,
}
else
{
if (gbm)
/* 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
size, 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.
*/
get_hardware_cursor_size (&cursor_width, &cursor_height);
meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n");
return;
}
if (width != cursor_width || height != cursor_height)
{
meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n");
return;
}
image->bo = gbm_bo_import (gbm, GBM_BO_IMPORT_WL_BUFFER, buffer, GBM_BO_USE_CURSOR);
if (tracker->gbm)
{
image->bo = gbm_bo_import (tracker->gbm, GBM_BO_IMPORT_WL_BUFFER,
buffer, GBM_BO_USE_CURSOR_64X64);
if (!image->bo)
meta_warning ("Importing HW cursor from wl_buffer failed\n");
}
@ -359,7 +373,8 @@ meta_cursor_image_load_from_buffer (MetaCursorImage *image,
}
MetaCursorReference *
meta_cursor_reference_from_buffer (struct wl_resource *buffer,
meta_cursor_reference_from_buffer (MetaCursorTracker *tracker,
struct wl_resource *buffer,
int hot_x,
int hot_y)
{
@ -367,11 +382,10 @@ meta_cursor_reference_from_buffer (struct wl_resource *buffer,
self = g_slice_new0 (MetaCursorReference);
self->ref_count = 1;
meta_cursor_image_load_from_buffer (&self->image, buffer, hot_x, hot_y);
meta_cursor_image_load_from_buffer (tracker, &self->image, buffer, hot_x, hot_y);
return self;
}
#endif
CoglTexture *
meta_cursor_reference_get_cogl_texture (MetaCursorReference *cursor,
@ -396,9 +410,3 @@ meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
*hot_y = cursor->image.hot_y;
return cursor->image.bo;
}
MetaCursor
meta_cursor_reference_get_meta_cursor (MetaCursorReference *cursor)
{
return cursor->cursor;
}

View File

@ -27,20 +27,16 @@ typedef struct _MetaCursorReference MetaCursorReference;
MetaCursorReference * meta_cursor_reference_ref (MetaCursorReference *cursor);
void meta_cursor_reference_unref (MetaCursorReference *cursor);
#include <meta/meta-cursor-tracker.h>
#include <meta/common.h>
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_theme (MetaCursorTracker *tracker,
MetaCursor cursor);
MetaCursorReference * meta_cursor_reference_from_buffer (MetaCursorTracker *tracker,
struct wl_resource *buffer,
int hot_x,
int hot_y);
#endif
MetaCursor meta_cursor_reference_get_meta_cursor (MetaCursorReference *cursor);
Cursor meta_cursor_create_x_cursor (Display *xdisplay,
MetaCursor cursor);
#endif /* META_CURSOR_H */

View File

@ -1,7 +1,7 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
/*
* Copyright (C) 2013 Red Hat Inc.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
@ -11,7 +11,7 @@
* 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/>.
*/

View File

@ -180,9 +180,6 @@ create_monitor_skeleton (GDBusObjectManagerServer *manager,
meta_dbus_object_skeleton_set_idle_monitor (object, skeleton);
g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (object));
g_object_unref (skeleton);
g_object_unref (object);
}
static void

View File

@ -1,8 +1,8 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
/*
* Copyright 2013 Red Hat, Inc.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
@ -12,7 +12,7 @@
* 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/>.
*

View File

@ -1,8 +1,8 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
/*
* Copyright 2013 Red Hat, Inc.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
@ -12,7 +12,7 @@
* 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/>.
*
@ -38,7 +38,8 @@
#include <meta/meta-idle-monitor.h>
#include "meta-idle-monitor-private.h"
#include "meta-idle-monitor-dbus.h"
#include "meta-backend-private.h"
#include "backends/x11/meta-idle-monitor-xsync.h"
#include "backends/native/meta-idle-monitor-native.h"
G_STATIC_ASSERT(sizeof(unsigned long) == sizeof(gpointer));
@ -53,6 +54,9 @@ static GParamSpec *obj_props[PROP_LAST];
G_DEFINE_TYPE (MetaIdleMonitor, meta_idle_monitor, G_TYPE_OBJECT)
static MetaIdleMonitor *device_monitors[256];
static int device_id_max;
void
_meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch)
{
@ -156,6 +160,36 @@ meta_idle_monitor_init (MetaIdleMonitor *monitor)
{
}
static GType
get_idle_monitor_type (void)
{
if (meta_is_wayland_compositor ())
return META_TYPE_IDLE_MONITOR_NATIVE;
else
return META_TYPE_IDLE_MONITOR_XSYNC;
}
static void
ensure_device_monitor (int device_id)
{
if (device_monitors[device_id])
return;
device_monitors[device_id] = g_object_new (get_idle_monitor_type (),
"device-id", device_id,
NULL);
device_id_max = MAX (device_id_max, device_id);
}
/* FIXME -- destroy device monitors at some point */
G_GNUC_UNUSED static void
destroy_device_monitor (int device_id)
{
g_clear_object (&device_monitors[device_id]);
if (device_id == device_id_max)
device_id_max--;
}
/**
* meta_idle_monitor_get_core:
*
@ -166,8 +200,8 @@ meta_idle_monitor_init (MetaIdleMonitor *monitor)
MetaIdleMonitor *
meta_idle_monitor_get_core (void)
{
MetaBackend *backend = meta_get_backend ();
return meta_backend_get_idle_monitor (backend, 0);
ensure_device_monitor (0);
return device_monitors[0];
}
/**
@ -181,8 +215,10 @@ meta_idle_monitor_get_core (void)
MetaIdleMonitor *
meta_idle_monitor_get_for_device (int device_id)
{
MetaBackend *backend = meta_get_backend ();
return meta_backend_get_idle_monitor (backend, device_id);
g_return_val_if_fail (device_id > 0 && device_id < 256, NULL);
ensure_device_monitor (device_id);
return device_monitors[device_id];
}
static MetaIdleMonitorWatch *
@ -210,9 +246,9 @@ make_watch (MetaIdleMonitor *monitor,
* meta_idle_monitor_add_idle_watch:
* @monitor: A #MetaIdleMonitor
* @interval_msec: The idletime interval, in milliseconds
* @callback: (nullable): The callback to call when the user has
* @callback: (allow-none): The callback to call when the user has
* accumulated @interval_msec milliseconds of idle time.
* @user_data: (nullable): The user data to pass to the callback
* @user_data: (allow-none): The user data to pass to the callback
* @notify: A #GDestroyNotify
*
* Returns: a watch id
@ -252,9 +288,9 @@ meta_idle_monitor_add_idle_watch (MetaIdleMonitor *monitor,
/**
* meta_idle_monitor_add_user_active_watch:
* @monitor: A #MetaIdleMonitor
* @callback: (nullable): The callback to call when the user is
* @callback: (allow-none): The callback to call when the user is
* active again.
* @user_data: (nullable): The user data to pass to the callback
* @user_data: (allow-none): The user data to pass to the callback
* @notify: A #GDestroyNotify
*
* Returns: a watch id
@ -316,3 +352,16 @@ meta_idle_monitor_get_idletime (MetaIdleMonitor *monitor)
{
return META_IDLE_MONITOR_GET_CLASS (monitor)->get_idletime (monitor);
}
void
meta_idle_monitor_xsync_handle_xevent_all (XEvent *xevent)
{
int i;
if (meta_is_wayland_compositor ())
return;
for (i = 0; i <= device_id_max; i++)
if (device_monitors[i])
meta_idle_monitor_xsync_handle_xevent (device_monitors[i], (XSyncAlarmNotifyEvent*)xevent);
}

View File

@ -1,6 +1,6 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
/*
* Copyright (C) 2001, 2002 Havoc Pennington
* Copyright (C) 2002, 2003 Red Hat Inc.
* Some ICCCM manager selection code derived from fvwm2,
@ -8,7 +8,7 @@
* Copyright (C) 2003 Rob Adams
* Copyright (C) 2004-2006 Elijah Newren
* Copyright (C) 2013 Red Hat Inc.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
@ -18,7 +18,7 @@
* 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/>.
*/
@ -60,7 +60,7 @@ typedef struct {
gboolean enabled;
MetaRectangle rect;
float refresh_rate;
MetaMonitorTransform transform;
enum wl_output_transform transform;
gboolean is_primary;
gboolean is_presentation;
@ -78,7 +78,6 @@ struct _MetaMonitorConfig {
GHashTable *configs;
MetaConfiguration *current;
gboolean current_is_stored;
gboolean current_is_for_laptop_lid;
MetaConfiguration *previous;
GFile *file;
@ -571,7 +570,7 @@ is_all_whitespace (const char *text,
gsize text_len)
{
gsize i;
for (i = 0; i < text_len; i++)
if (!g_ascii_isspace (text[i]))
return FALSE;
@ -656,20 +655,20 @@ handle_text (GMarkupParseContext *context,
else if (strcmp (parser->output_field, "rotation") == 0)
{
if (strncmp (text, "normal", text_len) == 0)
parser->output.transform = META_MONITOR_TRANSFORM_NORMAL;
parser->output.transform = WL_OUTPUT_TRANSFORM_NORMAL;
else if (strncmp (text, "left", text_len) == 0)
parser->output.transform = META_MONITOR_TRANSFORM_90;
parser->output.transform = WL_OUTPUT_TRANSFORM_90;
else if (strncmp (text, "upside_down", text_len) == 0)
parser->output.transform = META_MONITOR_TRANSFORM_180;
parser->output.transform = WL_OUTPUT_TRANSFORM_180;
else if (strncmp (text, "right", text_len) == 0)
parser->output.transform = META_MONITOR_TRANSFORM_270;
parser->output.transform = WL_OUTPUT_TRANSFORM_270;
else
g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
"Invalid rotation type %.*s", (int)text_len, text);
}
else if (strcmp (parser->output_field, "reflect_x") == 0)
parser->output.transform += read_bool (text, text_len, error) ?
META_MONITOR_TRANSFORM_FLIPPED : 0;
WL_OUTPUT_TRANSFORM_FLIPPED : 0;
else if (strcmp (parser->output_field, "reflect_y") == 0)
{
/* FIXME (look at the rotation map in monitor.c) */
@ -841,9 +840,6 @@ meta_monitor_config_get_stored (MetaMonitorConfig *self,
MetaConfiguration key;
MetaConfiguration *stored;
if (n_outputs == 0)
return NULL;
make_config_key (&key, outputs, n_outputs, -1);
stored = g_hash_table_lookup (self->configs, &key);
@ -878,8 +874,7 @@ apply_configuration (MetaMonitorConfig *self,
/* 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.
about to become previous) is stored.
*/
if (stored ||
(self->current && self->current_is_stored))
@ -890,27 +885,11 @@ apply_configuration (MetaMonitorConfig *self,
}
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->previous = self->current;
}
self->current = config;
self->current_is_stored = stored;
/* If true, we'll be overridden at the end of this call
inside turn_off_laptop_display()
*/
self->current_is_for_laptop_lid = FALSE;
if (self->current == self->previous)
self->previous = NULL;
@ -1027,16 +1006,8 @@ meta_monitor_config_apply_stored (MetaMonitorConfig *self,
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;
}
return apply_configuration (self, make_laptop_lid_config (stored),
manager, FALSE);
else
return apply_configuration (self, stored, manager, TRUE);
}
@ -1115,7 +1086,7 @@ make_default_config (MetaMonitorConfig *self,
ret->outputs[0].rect.width = outputs[0].preferred_mode->width;
ret->outputs[0].rect.height = outputs[0].preferred_mode->height;
ret->outputs[0].refresh_rate = outputs[0].preferred_mode->refresh_rate;
ret->outputs[0].transform = META_MONITOR_TRANSFORM_NORMAL;
ret->outputs[0].transform = WL_OUTPUT_TRANSFORM_NORMAL;
ret->outputs[0].is_primary = TRUE;
return ret;
@ -1167,7 +1138,7 @@ make_default_config (MetaMonitorConfig *self,
ret->outputs[j].rect.width = outputs[0].preferred_mode->width;
ret->outputs[j].rect.height = outputs[0].preferred_mode->height;
ret->outputs[j].refresh_rate = outputs[0].preferred_mode->refresh_rate;
ret->outputs[j].transform = META_MONITOR_TRANSFORM_NORMAL;
ret->outputs[j].transform = WL_OUTPUT_TRANSFORM_NORMAL;
ret->outputs[j].is_primary = FALSE;
ret->outputs[j].is_presentation = FALSE;
}
@ -1202,7 +1173,7 @@ make_default_config (MetaMonitorConfig *self,
ret->outputs[i].rect.width = output->preferred_mode->width;
ret->outputs[i].rect.height = output->preferred_mode->height;
ret->outputs[i].refresh_rate = output->preferred_mode->refresh_rate;
ret->outputs[i].transform = META_MONITOR_TRANSFORM_NORMAL;
ret->outputs[i].transform = WL_OUTPUT_TRANSFORM_NORMAL;
ret->outputs[i].is_primary = (output == primary);
/* Disable outputs that would go beyond framebuffer limits */
@ -1250,7 +1221,7 @@ ensure_at_least_one_output (MetaMonitorConfig *self,
ret->outputs[i].rect.width = output->preferred_mode->width;
ret->outputs[i].rect.height = output->preferred_mode->height;
ret->outputs[i].refresh_rate = output->preferred_mode->refresh_rate;
ret->outputs[i].transform = META_MONITOR_TRANSFORM_NORMAL;
ret->outputs[i].transform = WL_OUTPUT_TRANSFORM_NORMAL;
ret->outputs[i].is_primary = TRUE;
}
else
@ -1276,12 +1247,6 @@ meta_monitor_config_make_default (MetaMonitorConfig *self,
outputs = meta_monitor_manager_get_outputs (manager, &n_outputs);
meta_monitor_manager_get_screen_limits (manager, &max_width, &max_height);
if (n_outputs == 0)
{
meta_verbose ("No output connected, not applying configuration\n");
return;
}
default_config = make_default_config (self, outputs, n_outputs, max_width, max_height);
if (default_config != NULL)
@ -1383,7 +1348,6 @@ turn_off_laptop_display (MetaMonitorConfig *self,
new = make_laptop_lid_config (self->current);
apply_configuration (self, new, manager, FALSE);
self->current_is_for_laptop_lid = TRUE;
}
static void
@ -1403,7 +1367,7 @@ power_client_changed_cb (UpClient *client,
if (is_closed)
turn_off_laptop_display (self, manager);
else if (self->current_is_for_laptop_lid)
else
meta_monitor_config_restore_previous (self, manager);
}
}
@ -1512,7 +1476,7 @@ meta_monitor_config_save (MetaMonitorConfig *self)
output->rect.x,
output->rect.y,
rotation_map[output->transform & 0x3],
output->transform >= META_MONITOR_TRANSFORM_FLIPPED ? "yes" : "no",
output->transform >= WL_OUTPUT_TRANSFORM_FLIPPED ? "yes" : "no",
output->is_primary ? "yes" : "no",
output->is_presentation ? "yes" : "no");
}
@ -1621,13 +1585,13 @@ output_supports_mode (MetaOutput *output,
}
static gboolean
crtc_assignment_assign (CrtcAssignment *assign,
MetaCRTC *crtc,
MetaMonitorMode *mode,
int x,
int y,
MetaMonitorTransform transform,
MetaOutput *output)
crtc_assignment_assign (CrtcAssignment *assign,
MetaCRTC *crtc,
MetaMonitorMode *mode,
int x,
int y,
enum wl_output_transform transform,
MetaOutput *output)
{
MetaCRTCInfo *info = g_hash_table_lookup (assign->info, crtc);
@ -1789,6 +1753,7 @@ real_assign_crtcs (CrtcAssignment *assignment,
output_config->transform,
pass);
if (crtc_assignment_assign (assignment, crtc, &modes[j],
output_config->rect.x, output_config->rect.y,
output_config->transform,

View File

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

View File

@ -1,6 +1,6 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
/*
* Copyright (C) 2001, 2002 Havoc Pennington
* Copyright (C) 2002, 2003 Red Hat Inc.
* Some ICCCM manager selection code derived from fvwm2,
@ -8,7 +8,7 @@
* Copyright (C) 2003 Rob Adams
* Copyright (C) 2004-2006 Elijah Newren
* Copyright (C) 2013 Red Hat Inc.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
@ -18,7 +18,7 @@
* 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/>.
*/
@ -36,14 +36,21 @@
#include "util-private.h"
#include <meta/errors.h>
#include "meta-monitor-config.h"
#include "backends/native/meta-monitor-manager-kms.h"
#include "backends/x11/meta-monitor-manager-xrandr.h"
#include "meta-backend-private.h"
#include "meta-monitor-manager-dummy.h"
enum {
CONFIRM_DISPLAY_CHANGE,
SIGNALS_LAST
};
enum {
PROP_0,
PROP_POWER_SAVE_MODE,
PROP_LAST
};
static int signals[SIGNALS_LAST];
static void meta_monitor_manager_display_config_init (MetaDBusDisplayConfigIface *iface);
@ -119,7 +126,7 @@ make_logical_config (MetaMonitorManager *manager)
*/
info.is_presentation = TRUE;
info.in_fullscreen = -1;
info.winsys_id = 0;
info.output_id = 0;
g_array_append_val (monitor_infos, info);
@ -150,8 +157,8 @@ make_logical_config (MetaMonitorManager *manager)
info->is_primary = info->is_primary || output->is_primary;
info->is_presentation = info->is_presentation && output->is_presentation;
if (output->is_primary || info->winsys_id == 0)
info->winsys_id = output->winsys_id;
if (output->is_primary || info->output_id == 0)
info->output_id = output->output_id;
if (info->is_primary)
manager->primary_monitor_index = info->number;
@ -161,29 +168,56 @@ make_logical_config (MetaMonitorManager *manager)
manager->monitor_infos = (void*)g_array_free (monitor_infos, FALSE);
}
static void
power_save_mode_changed (MetaMonitorManager *manager,
GParamSpec *pspec,
gpointer user_data)
static GType
get_default_backend (void)
{
MetaMonitorManagerClass *klass;
int mode = meta_dbus_display_config_get_power_save_mode (META_DBUS_DISPLAY_CONFIG (manager));
#if defined(CLUTTER_WINDOWING_EGL)
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
return META_TYPE_MONITOR_MANAGER_KMS;
#endif
if (mode == META_POWER_SAVE_UNSUPPORTED)
return;
/* If DPMS is unsupported, force the property back. */
if (manager->power_save_mode == META_POWER_SAVE_UNSUPPORTED)
#if defined(CLUTTER_WINDOWING_X11)
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_X11))
{
meta_dbus_display_config_set_power_save_mode (META_DBUS_DISPLAY_CONFIG (manager), META_POWER_SAVE_UNSUPPORTED);
return;
/* If we're a Wayland compositor using the X11 backend,
* we're a nested configuration, so return the dummy
* monitor setup. */
if (meta_is_wayland_compositor ())
return META_TYPE_MONITOR_MANAGER_DUMMY;
else
return META_TYPE_MONITOR_MANAGER_XRANDR;
}
#endif
klass = META_MONITOR_MANAGER_GET_CLASS (manager);
if (klass->set_power_save_mode)
klass->set_power_save_mode (manager, mode);
#if defined(CLUTTER_WINDOWING_WAYLAND)
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_WAYLAND))
{
/* Use the dummy implementation on Wayland for now.
* In the future, we should support wl_fullscreen_output
* which will have CRTC management in the protocol. */
return META_TYPE_MONITOR_MANAGER_DUMMY;
}
#endif
manager->power_save_mode = mode;
g_assert_not_reached ();
}
static MetaMonitorManager *
meta_monitor_manager_new (void)
{
const char *env;
GType type;
env = g_getenv ("META_DEBUG_MULTIMONITOR");
if (env == NULL)
type = get_default_backend ();
else if (strcmp (env, "xrandr") == 0)
type = META_TYPE_MONITOR_MANAGER_XRANDR;
else
type = META_TYPE_MONITOR_MANAGER;
return g_object_new (type, NULL);
}
static void
@ -191,9 +225,6 @@ meta_monitor_manager_constructed (GObject *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->config = meta_monitor_config_new ();
@ -236,6 +267,23 @@ meta_monitor_manager_constructed (GObject *object)
manager->in_init = FALSE;
}
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,
int n_old_outputs)
@ -303,6 +351,44 @@ meta_monitor_manager_dispose (GObject *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 *
meta_monitor_manager_real_read_edid (MetaMonitorManager *manager,
MetaOutput *output)
@ -323,6 +409,8 @@ meta_monitor_manager_class_init (MetaMonitorManagerClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
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->finalize = meta_monitor_manager_finalize;
@ -336,6 +424,8 @@ meta_monitor_manager_class_init (MetaMonitorManagerClass *klass)
0,
NULL, NULL, NULL,
G_TYPE_NONE, 0);
g_object_class_override_property (object_class, PROP_POWER_SAVE_MODE, "power-save-mode");
}
static const double known_diagonals[] = {
@ -440,19 +530,19 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
GVariantBuilder transforms;
g_variant_builder_init (&transforms, G_VARIANT_TYPE ("au"));
for (j = 0; j <= META_MONITOR_TRANSFORM_FLIPPED_270; j++)
for (j = 0; j <= WL_OUTPUT_TRANSFORM_FLIPPED_270; j++)
if (crtc->all_transforms & (1 << j))
g_variant_builder_add (&transforms, "u", j);
g_variant_builder_add (&crtc_builder, "(uxiiiiiuaua{sv})",
i, /* ID */
(gint64)crtc->crtc_id,
crtc->crtc_id,
(int)crtc->rect.x,
(int)crtc->rect.y,
(int)crtc->rect.width,
(int)crtc->rect.height,
(int)(crtc->current_mode ? crtc->current_mode - manager->modes : -1),
(guint32)crtc->transform,
crtc->transform,
&transforms,
NULL /* properties */);
}
@ -523,7 +613,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
g_variant_builder_add (&output_builder, "(uxiausauaua{sv})",
i, /* ID */
(gint64)output->winsys_id,
output->output_id,
(int)(output->crtc ? output->crtc - manager->crtcs : -1),
&crtcs,
output->name,
@ -538,9 +628,9 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
g_variant_builder_add (&mode_builder, "(uxuud)",
i, /* ID */
(gint64)mode->mode_id,
(guint32)mode->width,
(guint32)mode->height,
mode->mode_id,
mode->width,
mode->height,
(double)mode->refresh_rate);
}
@ -630,7 +720,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
int new_mode, x, y;
int new_screen_width, new_screen_height;
guint transform;
guint output_index;
guint output_id;
GPtrArray *crtc_infos, *output_infos;
if (serial != manager->serial)
@ -657,6 +747,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
MetaOutput *first_output;
MetaCRTC *crtc;
MetaMonitorMode *mode;
guint output_id;
crtc_info = g_slice_new (MetaCRTCInfo);
crtc_info->outputs = g_ptr_array_new ();
@ -718,8 +809,8 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
crtc_info->y = 0;
}
if (transform < META_MONITOR_TRANSFORM_NORMAL ||
transform > META_MONITOR_TRANSFORM_FLIPPED_270 ||
if (transform < WL_OUTPUT_TRANSFORM_NORMAL ||
transform > WL_OUTPUT_TRANSFORM_FLIPPED_270 ||
((crtc->all_transforms & (1 << transform)) == 0))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
@ -730,18 +821,18 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
crtc_info->transform = transform;
first_output = NULL;
while (g_variant_iter_loop (nested_outputs, "u", &output_index))
while (g_variant_iter_loop (nested_outputs, "u", &output_id))
{
MetaOutput *output;
if (output_index >= manager->n_outputs)
if (output_id >= manager->n_outputs)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_INVALID_ARGS,
"Invalid output id");
return TRUE;
}
output = &manager->outputs[output_index];
output = &manager->outputs[output_id];
if (!output_can_config (output, crtc, mode))
{
@ -786,12 +877,12 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
}
g_variant_iter_init (&output_iter, outputs);
while (g_variant_iter_loop (&output_iter, "(u@a{sv})", &output_index, &properties))
while (g_variant_iter_loop (&output_iter, "(u@a{sv})", &output_id, &properties))
{
MetaOutputInfo *output_info;
gboolean primary, presentation;
if (output_index >= manager->n_outputs)
if (output_id >= manager->n_outputs)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_INVALID_ARGS,
@ -800,7 +891,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
}
output_info = g_slice_new0 (MetaOutputInfo);
output_info->output = &manager->outputs[output_index];
output_info->output = &manager->outputs[output_id];
if (g_variant_lookup (properties, "primary", "b", &primary))
output_info->is_primary = primary;
@ -814,7 +905,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
/* If we were in progress of making a persistent change and we see a
new request, it's likely that the old one failed in some way, so
don't save it, but also don't queue for restoring it.
*/
*/
if (manager->persistent_timeout_id && persistent)
{
g_source_remove (manager->persistent_timeout_id);
@ -840,7 +931,6 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
if (persistent)
{
manager->persistent_timeout_id = g_timeout_add_seconds (20, save_config_timeout, manager);
g_source_set_name_by_id (manager->persistent_timeout_id, "[mutter] save_config_timeout");
g_signal_emit (manager, signals[CONFIRM_DISPLAY_CHANGE], 0);
}
@ -871,7 +961,7 @@ static gboolean
meta_monitor_manager_handle_change_backlight (MetaDBusDisplayConfig *skeleton,
GDBusMethodInvocation *invocation,
guint serial,
guint output_index,
guint output_id,
gint value)
{
MetaMonitorManager *manager = META_MONITOR_MANAGER (skeleton);
@ -885,14 +975,14 @@ meta_monitor_manager_handle_change_backlight (MetaDBusDisplayConfig *skeleton,
return TRUE;
}
if (output_index >= manager->n_outputs)
if (output_id >= manager->n_outputs)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_INVALID_ARGS,
"Invalid output id");
return TRUE;
}
output = &manager->outputs[output_index];
output = &manager->outputs[output_id];
if (value < 0 || value > 100)
{
@ -1088,12 +1178,20 @@ initialize_dbus_interface (MetaMonitorManager *manager)
g_object_unref);
}
static MetaMonitorManager *global_monitor_manager;
void
meta_monitor_manager_initialize (void)
{
global_monitor_manager = meta_monitor_manager_new ();
}
MetaMonitorManager *
meta_monitor_manager_get (void)
{
MetaBackend *backend = meta_get_backend ();
g_assert (global_monitor_manager != NULL);
return meta_backend_get_monitor_manager (backend);
return global_monitor_manager;
}
MetaMonitorInfo *
@ -1179,3 +1277,16 @@ meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager)
g_free (old_monitor_infos);
}
gboolean
meta_monitor_manager_handle_xevent (MetaMonitorManager *manager,
XEvent *event)
{
MetaMonitorManagerClass *klass;
klass = META_MONITOR_MANAGER_GET_CLASS (manager);
if (klass->handle_xevent)
return klass->handle_xevent (manager, event);
else
return FALSE;
}

View File

@ -12,12 +12,12 @@
* at MetaScreen instead.
*/
/*
/*
* Copyright (C) 2001 Havoc Pennington
* Copyright (C) 2003 Rob Adams
* Copyright (C) 2004-2006 Elijah Newren
* Copyright (C) 2013 Red Hat Inc.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
@ -27,7 +27,7 @@
* 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/>.
*/
@ -41,10 +41,11 @@
#include "display-private.h"
#include <meta/screen.h>
#include "stack-tracker.h"
#include "ui.h"
#include <wayland-server.h>
#include "meta-display-config-shared.h"
#include "meta-dbus-display-config.h"
#include "meta-cursor.h"
typedef struct _MetaMonitorManagerClass MetaMonitorManagerClass;
typedef struct _MetaMonitorManager MetaMonitorManager;
@ -58,23 +59,12 @@ typedef struct _MetaMonitorInfo MetaMonitorInfo;
typedef struct _MetaCRTCInfo MetaCRTCInfo;
typedef struct _MetaOutputInfo MetaOutputInfo;
typedef enum {
META_MONITOR_TRANSFORM_NORMAL,
META_MONITOR_TRANSFORM_90,
META_MONITOR_TRANSFORM_180,
META_MONITOR_TRANSFORM_270,
META_MONITOR_TRANSFORM_FLIPPED,
META_MONITOR_TRANSFORM_FLIPPED_90,
META_MONITOR_TRANSFORM_FLIPPED_180,
META_MONITOR_TRANSFORM_FLIPPED_270,
} MetaMonitorTransform;
struct _MetaOutput
{
/* The CRTC driving this output, NULL if the output is not enabled */
MetaCRTC *crtc;
/* The low-level ID of this output, used to apply back configuration */
glong winsys_id;
glong output_id;
char *name;
char *vendor;
char *product;
@ -82,7 +72,6 @@ struct _MetaOutput
int width_mm;
int height_mm;
CoglSubpixelOrder subpixel_order;
int scale;
MetaMonitorMode *preferred_mode;
MetaMonitorMode **modes;
@ -123,7 +112,7 @@ struct _MetaCRTC
glong crtc_id;
MetaRectangle rect;
MetaMonitorMode *current_mode;
MetaMonitorTransform transform;
enum wl_output_transform transform;
unsigned int all_transforms;
/* Only used to build the logical configuration
@ -134,7 +123,8 @@ struct _MetaCRTC
/* Used when changing configuration */
gboolean is_dirty;
MetaCursorReference *cursor;
/* Updated by MetaCursorTracker */
gboolean has_hw_cursor;
};
struct _MetaMonitorMode
@ -171,14 +161,14 @@ struct _MetaMonitorInfo
gboolean in_fullscreen;
/* The primary or first output for this monitor, 0 if we can't figure out.
It can be matched to a winsys_id of a MetaOutput.
It can be matched to an output_id of a MetaOutput.
This is used as an opaque token on reconfiguration when switching from
clone to extened, to decide on what output the windows should go next
(it's an attempt to keep windows on the same monitor, and preferably on
the primary one).
*/
glong winsys_id;
glong output_id;
};
/*
@ -194,7 +184,7 @@ struct _MetaCRTCInfo {
MetaMonitorMode *mode;
int x;
int y;
MetaMonitorTransform transform;
enum wl_output_transform transform;
GPtrArray *outputs;
};
@ -295,10 +285,14 @@ struct _MetaMonitorManagerClass
unsigned short *,
unsigned short *,
unsigned short *);
gboolean (*handle_xevent) (MetaMonitorManager *,
XEvent *);
};
GType meta_monitor_manager_get_type (void);
void meta_monitor_manager_initialize (void);
MetaMonitorManager *meta_monitor_manager_get (void);
void meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager);
@ -319,6 +313,9 @@ void meta_monitor_manager_get_resources (MetaMonitorManager
int meta_monitor_manager_get_primary_index (MetaMonitorManager *manager);
gboolean meta_monitor_manager_handle_xevent (MetaMonitorManager *manager,
XEvent *event);
void meta_monitor_manager_get_screen_size (MetaMonitorManager *manager,
int *width,
int *height);
@ -348,7 +345,7 @@ gboolean meta_monitor_manager_has_hotplug_mode_update (MetaMonitorMana
/* Returns true if transform causes width and height to be inverted
This is true for the odd transforms in the enum */
static inline gboolean
meta_monitor_transform_is_rotated (MetaMonitorTransform transform)
meta_monitor_transform_is_rotated (enum wl_output_transform transform)
{
return (transform % 2);
}

View File

@ -1,197 +0,0 @@
/*
* Copyright (C) 2014 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#include <config.h>
#include "meta-stage.h"
#include "meta-cursor-private.h"
#include <meta/meta-backend.h>
#include <meta/util.h>
typedef struct {
gboolean enabled;
CoglPipeline *pipeline;
CoglTexture *texture;
MetaRectangle current_rect;
MetaRectangle previous_rect;
gboolean previous_is_valid;
} MetaOverlay;
struct _MetaStagePrivate {
MetaOverlay cursor_overlay;
};
typedef struct _MetaStagePrivate MetaStagePrivate;
G_DEFINE_TYPE_WITH_PRIVATE (MetaStage, meta_stage, CLUTTER_TYPE_STAGE);
static void
meta_overlay_init (MetaOverlay *overlay)
{
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
overlay->pipeline = cogl_pipeline_new (ctx);
}
static void
meta_overlay_free (MetaOverlay *overlay)
{
if (overlay->pipeline)
cogl_object_unref (overlay->pipeline);
}
static void
meta_overlay_set (MetaOverlay *overlay,
CoglTexture *texture,
MetaRectangle *rect)
{
if (overlay->texture != texture)
{
overlay->texture = texture;
if (texture)
{
cogl_pipeline_set_layer_texture (overlay->pipeline, 0, texture);
overlay->enabled = TRUE;
}
else
{
cogl_pipeline_set_layer_texture (overlay->pipeline, 0, NULL);
overlay->enabled = FALSE;
}
}
overlay->current_rect = *rect;
}
static void
meta_overlay_paint (MetaOverlay *overlay)
{
if (!overlay->enabled)
return;
g_assert (meta_is_wayland_compositor ());
cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (),
overlay->pipeline,
overlay->current_rect.x,
overlay->current_rect.y,
overlay->current_rect.x +
overlay->current_rect.width,
overlay->current_rect.y +
overlay->current_rect.height);
overlay->previous_rect = overlay->current_rect;
overlay->previous_is_valid = TRUE;
}
static void
meta_stage_finalize (GObject *object)
{
MetaStage *stage = META_STAGE (object);
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
meta_overlay_free (&priv->cursor_overlay);
}
static void
meta_stage_paint (ClutterActor *actor)
{
MetaStage *stage = META_STAGE (actor);
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor);
meta_overlay_paint (&priv->cursor_overlay);
}
static void
meta_stage_class_init (MetaStageClass *klass)
{
ClutterActorClass *actor_class = (ClutterActorClass *) klass;
GObjectClass *object_class = (GObjectClass *) klass;
object_class->finalize = meta_stage_finalize;
actor_class->paint = meta_stage_paint;
}
static void
meta_stage_init (MetaStage *stage)
{
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
meta_overlay_init (&priv->cursor_overlay);
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), FALSE);
}
ClutterActor *
meta_stage_new (void)
{
return g_object_new (META_TYPE_STAGE,
"cursor-visible", FALSE,
NULL);
}
static void
queue_redraw_for_overlay (MetaStage *stage,
MetaOverlay *overlay)
{
cairo_rectangle_int_t clip;
/* Clear the location the overlay was at before, if we need to. */
if (overlay->previous_is_valid)
{
clip.x = overlay->previous_rect.x;
clip.y = overlay->previous_rect.y;
clip.width = overlay->previous_rect.width;
clip.height = overlay->previous_rect.height;
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &clip);
overlay->previous_is_valid = FALSE;
}
/* Draw the overlay at the new position */
if (overlay->enabled)
{
clip.x = overlay->current_rect.x;
clip.y = overlay->current_rect.y;
clip.width = overlay->current_rect.width;
clip.height = overlay->current_rect.height;
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &clip);
}
}
void
meta_stage_set_cursor (MetaStage *stage,
CoglTexture *texture,
MetaRectangle *rect)
{
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
g_assert (meta_is_wayland_compositor () || texture == NULL);
meta_overlay_set (&priv->cursor_overlay, texture, rect);
queue_redraw_for_overlay (stage, &priv->cursor_overlay);
}

View File

@ -1,59 +0,0 @@
/*
* Copyright (C) 2012 Intel Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_STAGE_H
#define META_STAGE_H
#include <clutter/clutter.h>
#include "meta-cursor.h"
#include <meta/boxes.h>
G_BEGIN_DECLS
#define META_TYPE_STAGE (meta_stage_get_type ())
#define META_STAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_STAGE, MetaStage))
#define META_STAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_STAGE, MetaStageClass))
#define META_IS_STAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_STAGE))
#define META_IS_STAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_STAGE))
#define META_STAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_STAGE, MetaStageClass))
typedef struct _MetaStage MetaStage;
typedef struct _MetaStageClass MetaStageClass;
struct _MetaStageClass
{
ClutterStageClass parent_class;
};
struct _MetaStage
{
ClutterStage parent;
};
GType meta_stage_get_type (void) G_GNUC_CONST;
ClutterActor *meta_stage_new (void);
void meta_stage_set_cursor (MetaStage *stage,
CoglTexture *texture,
MetaRectangle *rect);
G_END_DECLS
#endif /* META_STAGE_H */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,8 +1,8 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
/*
* Copyright (C) 2013 Red Hat Inc.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
@ -12,7 +12,7 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@ -40,6 +40,8 @@
#include <meta/errors.h>
#include "edid.h"
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
typedef struct {
drmModeConnector *connector;
@ -257,7 +259,7 @@ find_output_by_id (MetaOutput *outputs,
unsigned i;
for (i = 0; i < n_outputs; i++)
if (outputs[i].winsys_id == id)
if (outputs[i].output_id == id)
return &outputs[i];
return NULL;
@ -361,9 +363,9 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
meta_crtc->rect.width = crtc->width;
meta_crtc->rect.height = crtc->height;
meta_crtc->is_dirty = FALSE;
meta_crtc->transform = META_MONITOR_TRANSFORM_NORMAL;
meta_crtc->transform = WL_OUTPUT_TRANSFORM_NORMAL;
/* FIXME: implement! */
meta_crtc->all_transforms = 1 << META_MONITOR_TRANSFORM_NORMAL;
meta_crtc->all_transforms = 1 << WL_OUTPUT_TRANSFORM_NORMAL;
if (crtc->mode_valid)
{
@ -406,7 +408,7 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
meta_output->driver_private = output_kms = g_slice_new0 (MetaOutputKms);
meta_output->driver_notify = (GDestroyNotify)meta_output_destroy_notify;
meta_output->winsys_id = connector->connector_id;
meta_output->output_id = connector->connector_id;
meta_output->name = make_output_name (connector);
meta_output->width_mm = connector->mmWidth;
meta_output->height_mm = connector->mmHeight;
@ -489,7 +491,7 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
meta_output->crtc = NULL;
old_output = find_output_by_id (old_outputs, n_old_outputs,
meta_output->winsys_id);
meta_output->output_id);
if (old_output)
{
meta_output->is_primary = old_output->is_primary;
@ -665,7 +667,7 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
if (output_kms->dpms_prop_id != 0)
{
int ok = drmModeConnectorSetProperty(manager_kms->fd, meta_output->winsys_id,
int ok = drmModeConnectorSetProperty(manager_kms->fd, meta_output->output_id,
output_kms->dpms_prop_id, state);
if (ok < 0)
@ -746,7 +748,7 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
{
MetaOutput *output = g_ptr_array_index (crtc_info->outputs, j);
connectors[j] = output->winsys_id;
connectors[j] = output->output_id;
output->is_dirty = TRUE;
output->crtc = crtc;

View File

@ -0,0 +1,411 @@
/*
* Copyright (C) 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <config.h>
#include <gio/gio.h>
#include <gio/gunixfdmessage.h>
#include <clutter/clutter.h>
#include <clutter/egl/clutter-egl.h>
#include <clutter/evdev/clutter-evdev.h>
#include <glib.h>
#include <sys/time.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <drm.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include "wayland/meta-wayland-private.h"
#include "meta-cursor-tracker-private.h"
#include "meta-weston-launch.h"
struct _MetaLauncher
{
GSocket *weston_launch;
gboolean vt_switched;
GMainContext *nested_context;
GMainLoop *nested_loop;
GSource *inner_source;
GSource *outer_source;
};
static void handle_request_vt_switch (MetaLauncher *self);
static gboolean
request_vt_switch_idle (gpointer user_data)
{
handle_request_vt_switch (user_data);
return FALSE;
}
static gboolean
send_message_to_wl (MetaLauncher *self,
void *message,
gsize size,
GSocketControlMessage *out_cmsg,
GSocketControlMessage **in_cmsg,
GError **error)
{
struct weston_launcher_reply reply;
GInputVector in_iov = { &reply, sizeof (reply) };
GOutputVector out_iov = { message, size };
GSocketControlMessage *out_all_cmsg[2];
GSocketControlMessage **in_all_cmsg;
int flags = 0;
int i;
out_all_cmsg[0] = out_cmsg;
out_all_cmsg[1] = NULL;
if (g_socket_send_message (self->weston_launch, NULL,
&out_iov, 1,
out_all_cmsg, -1,
flags, NULL, error) != (gssize)size)
return FALSE;
if (g_socket_receive_message (self->weston_launch, NULL,
&in_iov, 1,
&in_all_cmsg, NULL,
&flags, NULL, error) != sizeof (reply))
return FALSE;
while (reply.header.opcode != ((struct weston_launcher_message*)message)->opcode)
{
/* There were events queued */
g_assert ((reply.header.opcode & WESTON_LAUNCHER_EVENT) == WESTON_LAUNCHER_EVENT);
/* This can never happen, because the only time mutter-launch can queue
this event is after confirming a VT switch, and we don't make requests
during that time.
Note that getting this event would be really bad, because we would be
in the wrong loop/context.
*/
g_assert (reply.header.opcode != WESTON_LAUNCHER_SERVER_VT_ENTER);
switch (reply.header.opcode)
{
case WESTON_LAUNCHER_SERVER_REQUEST_VT_SWITCH:
g_idle_add (request_vt_switch_idle, self);
break;
default:
g_assert_not_reached ();
}
if (g_socket_receive_message (self->weston_launch, NULL,
&in_iov, 1,
NULL, NULL,
&flags, NULL, error) != sizeof (reply))
return FALSE;
}
if (reply.ret != 0)
{
if (reply.ret == -1)
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Got failure from weston-launch");
else
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-reply.ret),
"Got failure from weston-launch: %s", strerror (-reply.ret));
for (i = 0; in_all_cmsg && in_all_cmsg[i]; i++)
g_object_unref (in_all_cmsg[i]);
g_free (in_all_cmsg);
return FALSE;
}
if (in_all_cmsg && in_all_cmsg[0])
{
for (i = 1; in_all_cmsg[i]; i++)
g_object_unref (in_all_cmsg[i]);
*in_cmsg = in_all_cmsg[0];
}
g_free (in_all_cmsg);
return TRUE;
}
static int
meta_launcher_open_device (MetaLauncher *self,
const char *name,
int flags,
GError **error)
{
struct weston_launcher_open *message;
GSocketControlMessage *cmsg;
gboolean ok;
gsize size;
int *fds, n_fd;
int ret;
size = sizeof (struct weston_launcher_open) + strlen (name) + 1;
message = g_malloc (size);
message->header.opcode = WESTON_LAUNCHER_OPEN;
message->flags = flags;
strcpy (message->path, name);
message->path[strlen(name)] = 0;
ok = send_message_to_wl (self, message, size, NULL, &cmsg, error);
if (ok)
{
g_assert (G_IS_UNIX_FD_MESSAGE (cmsg));
fds = g_unix_fd_message_steal_fds (G_UNIX_FD_MESSAGE (cmsg), &n_fd);
g_assert (n_fd == 1);
ret = fds[0];
g_free (fds);
g_object_unref (cmsg);
}
else
ret = -1;
g_free (message);
return ret;
}
static void
meta_launcher_enter (MetaLauncher *launcher)
{
ClutterBackend *backend;
CoglContext *cogl_context;
CoglDisplay *cogl_display;
backend = clutter_get_default_backend ();
cogl_context = clutter_backend_get_cogl_context (backend);
cogl_display = cogl_context_get_display (cogl_context);
cogl_kms_display_queue_modes_reset (cogl_display);
clutter_evdev_reclaim_devices ();
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
/* When we mode-switch back, we need to immediately queue a redraw
* in case nothing else queued one for us, and force the cursor to
* update. */
clutter_actor_queue_redraw (compositor->stage);
meta_cursor_tracker_force_update (compositor->seat->cursor_tracker);
}
}
static void
meta_launcher_leave (MetaLauncher *launcher)
{
clutter_evdev_release_devices ();
}
static int
on_evdev_device_open (const char *path,
int flags,
gpointer user_data,
GError **error)
{
MetaLauncher *launcher = user_data;
return meta_launcher_open_device (launcher, path, flags, error);
}
static void
on_evdev_device_close (int fd,
gpointer user_data)
{
close (fd);
}
static void
handle_vt_enter (MetaLauncher *launcher)
{
g_assert (launcher->vt_switched);
g_main_loop_quit (launcher->nested_loop);
}
static void
handle_request_vt_switch (MetaLauncher *launcher)
{
struct weston_launcher_message message;
GError *error;
gboolean ok;
meta_launcher_leave (launcher);
message.opcode = WESTON_LAUNCHER_CONFIRM_VT_SWITCH;
error = NULL;
ok = send_message_to_wl (launcher, &message, sizeof (message), NULL, NULL, &error);
if (!ok) {
g_warning ("Failed to acknowledge VT switch: %s", error->message);
g_error_free (error);
return;
}
g_assert (!launcher->vt_switched);
launcher->vt_switched = TRUE;
/* We can't do anything at this point, because we don't
have input devices and we don't have the DRM master,
so let's run a nested busy loop until the VT is reentered */
g_main_loop_run (launcher->nested_loop);
g_assert (launcher->vt_switched);
launcher->vt_switched = FALSE;
meta_launcher_enter (launcher);
}
static gboolean
on_socket_readable (GSocket *socket,
GIOCondition condition,
gpointer user_data)
{
MetaLauncher *launcher = user_data;
struct weston_launcher_event event;
gssize read;
GError *error;
if ((condition & G_IO_IN) == 0)
return TRUE;
error = NULL;
read = g_socket_receive (socket, (char*)&event, sizeof(event), NULL, &error);
if (read < (gssize)sizeof(event))
{
g_warning ("Error reading from weston-launcher socket: %s", error->message);
g_error_free (error);
return TRUE;
}
switch (event.header.opcode)
{
case WESTON_LAUNCHER_SERVER_REQUEST_VT_SWITCH:
handle_request_vt_switch (launcher);
break;
case WESTON_LAUNCHER_SERVER_VT_ENTER:
handle_vt_enter (launcher);
break;
}
return TRUE;
}
static int
env_get_fd (const char *env)
{
const char *value;
value = g_getenv (env);
if (value == NULL)
return -1;
else
return g_ascii_strtoll (value, NULL, 10);
}
MetaLauncher *
meta_launcher_new (void)
{
MetaLauncher *self = g_slice_new0 (MetaLauncher);
int launch_fd;
launch_fd = env_get_fd ("WESTON_LAUNCHER_SOCK");
if (launch_fd < 0)
g_error ("Invalid mutter-launch socket");
self->weston_launch = g_socket_new_from_fd (launch_fd, NULL);
self->nested_context = g_main_context_new ();
self->nested_loop = g_main_loop_new (self->nested_context, FALSE);
self->outer_source = g_socket_create_source (self->weston_launch, G_IO_IN, NULL);
g_source_set_callback (self->outer_source, (GSourceFunc)on_socket_readable, self, NULL);
g_source_attach (self->outer_source, NULL);
g_source_unref (self->outer_source);
self->inner_source = g_socket_create_source (self->weston_launch, G_IO_IN, NULL);
g_source_set_callback (self->inner_source, (GSourceFunc)on_socket_readable, self, NULL);
g_source_attach (self->inner_source, self->nested_context);
g_source_unref (self->inner_source);
clutter_evdev_set_device_callbacks (on_evdev_device_open,
on_evdev_device_close,
self);
#if defined(CLUTTER_WINDOWING_EGL)
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
{
GError *error = NULL;
int fd = meta_launcher_open_device (self, "/dev/dri/card0", O_RDWR, &error);
if (error)
g_error ("Failed to open /dev/dri/card0: %s", error->message);
clutter_egl_set_kms_fd (fd);
}
#endif
return self;
}
void
meta_launcher_free (MetaLauncher *launcher)
{
g_source_destroy (launcher->outer_source);
g_source_destroy (launcher->inner_source);
g_main_loop_unref (launcher->nested_loop);
g_main_context_unref (launcher->nested_context);
g_object_unref (launcher->weston_launch);
g_slice_free (MetaLauncher, launcher);
}
gboolean
meta_launcher_activate_vt (MetaLauncher *launcher,
signed char vt,
GError **error)
{
struct weston_launcher_activate_vt message;
message.header.opcode = WESTON_LAUNCHER_ACTIVATE_VT;
message.vt = vt;
return send_message_to_wl (launcher, &message, sizeof (message), NULL, NULL, error);
}

View File

@ -17,21 +17,18 @@
* 02111-1307, USA.
*/
#ifndef META_LAUNCHER_H
#define META_LAUNCHER_H
#ifndef META_WESTON_LAUNCH_H
#define META_WESTON_LAUNCH_H
#include <glib-object.h>
#include "weston-launch.h"
typedef struct _MetaLauncher MetaLauncher;
MetaLauncher *meta_launcher_new (void);
void meta_launcher_free (MetaLauncher *self);
gboolean meta_launcher_activate_session (MetaLauncher *self,
GError **error);
gboolean meta_launcher_activate_vt (MetaLauncher *self,
signed char vt,
GError **error);
#endif /* META_LAUNCHER_H */
#endif

View File

@ -0,0 +1,711 @@
/*
* Copyright © 2012 Benjamin Franzke
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee, provided
* that the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of the copyright holders not be used in
* advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The copyright holders make
* no representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <poll.h>
#include <errno.h>
#include <error.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/signalfd.h>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
#include <limits.h>
#include <termios.h>
#include <linux/vt.h>
#include <linux/major.h>
#include <linux/kd.h>
#include <pwd.h>
#include <grp.h>
#include <xf86drm.h>
#include <systemd/sd-login.h>
#include "weston-launch.h"
#define MAX_ARGV_SIZE 256
#define DRM_MAJOR 226
enum vt_state {
VT_HAS_VT,
VT_PENDING_CONFIRM,
VT_NOT_HAVE_VT,
};
struct weston_launch {
int tty;
int ttynr;
int sock[2];
struct passwd *pw;
int signalfd;
pid_t child;
int verbose;
struct termios terminal_attributes;
int kb_mode;
enum vt_state vt_state;
unsigned vt;
int drm_fd;
};
union cmsg_data { unsigned char b[4]; int fd; };
static void quit (struct weston_launch *wl, int status);
static int
weston_launch_allowed(struct weston_launch *wl)
{
char *session, *seat;
int err;
if (getuid() == 0)
return 1;
err = sd_pid_get_session(getpid(), &session);
if (err == 0 && session) {
if (sd_session_is_active(session) &&
sd_session_get_seat(session, &seat) == 0) {
free(seat);
free(session);
return 1;
}
free(session);
}
return 0;
}
static int
setup_launcher_socket(struct weston_launch *wl)
{
if (socketpair(AF_LOCAL, SOCK_DGRAM, 0, wl->sock) < 0)
error(1, errno, "socketpair failed");
fcntl(wl->sock[0], F_SETFD, O_CLOEXEC);
return 0;
}
static int
setup_signals(struct weston_launch *wl)
{
int ret;
sigset_t mask;
struct sigaction sa;
memset(&sa, 0, sizeof sa);
sa.sa_handler = SIG_DFL;
sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
ret = sigaction(SIGCHLD, &sa, NULL);
assert(ret == 0);
sa.sa_handler = SIG_IGN;
sa.sa_flags = 0;
sigaction(SIGHUP, &sa, NULL);
ret = sigemptyset(&mask);
assert(ret == 0);
sigaddset(&mask, SIGCHLD);
sigaddset(&mask, SIGINT);
sigaddset(&mask, SIGTERM);
sigaddset(&mask, SIGUSR1);
ret = sigprocmask(SIG_BLOCK, &mask, NULL);
assert(ret == 0);
wl->signalfd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC);
if (wl->signalfd < 0)
return -errno;
return 0;
}
static void
setenv_fd(const char *env, int fd)
{
char buf[32];
snprintf(buf, sizeof buf, "%d", fd);
setenv(env, buf, 1);
}
static int
handle_confirm_vt_switch(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
{
struct weston_launcher_reply reply;
reply.header.opcode = WESTON_LAUNCHER_CONFIRM_VT_SWITCH;
reply.ret = -1;
if (wl->vt_state != VT_PENDING_CONFIRM) {
error(0, 0, "unexpected CONFIRM_VT_SWITCH");
goto out;
}
if (wl->drm_fd != -1) {
int ret;
ret = drmDropMaster(wl->drm_fd);
if (ret < 0) {
fprintf(stderr, "failed to drop DRM master: %m\n");
} else if (wl->verbose) {
fprintf(stderr, "dropped DRM master for VT switch\n");
}
}
wl->vt_state = VT_NOT_HAVE_VT;
ioctl(wl->tty, VT_RELDISP, 1);
if (wl->verbose)
fprintf(stderr, "mutter-launcher: confirmed VT switch\n");
reply.ret = 0;
out:
do {
len = send(wl->sock[0], &reply, sizeof reply, 0);
} while (len < 0 && errno == EINTR);
if (len < 0)
return -1;
return 0;
}
static int
handle_activate_vt(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
{
struct weston_launcher_reply reply;
struct weston_launcher_activate_vt *message;
unsigned vt;
reply.header.opcode = WESTON_LAUNCHER_ACTIVATE_VT;
reply.ret = -1;
if (len != sizeof(*message)) {
error(0, 0, "missing value in activate_vt request");
goto out;
}
message = msg->msg_iov->iov_base;
/* Negative values mean that we're activating our own VT */
if (message->vt > 0)
vt = message->vt;
else
vt = wl->vt;
reply.ret = ioctl(wl->tty, VT_ACTIVATE, vt);
if (reply.ret < 0)
reply.ret = -errno;
if (wl->verbose)
fprintf(stderr, "mutter-launch: activate VT, ret: %d\n", reply.ret);
out:
do {
len = send(wl->sock[0], &reply, sizeof reply, 0);
} while (len < 0 && errno == EINTR);
if (len < 0)
return -1;
return 0;
}
static int
handle_open(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
{
struct weston_launcher_reply reply;
int fd = -1;
char control[CMSG_SPACE(sizeof(fd))];
struct cmsghdr *cmsg;
struct stat s;
struct msghdr nmsg;
struct iovec iov;
struct weston_launcher_open *message;
union cmsg_data *data;
int dev_major;
reply.header.opcode = WESTON_LAUNCHER_OPEN;
reply.ret = -1;
message = msg->msg_iov->iov_base;
if ((size_t)len < sizeof(*message))
goto err0;
/* Ensure path is null-terminated */
((char *) message)[len-1] = '\0';
if (stat(message->path, &s) < 0) {
reply.ret = -errno;
goto err0;
}
dev_major = major(s.st_rdev);
if (dev_major != INPUT_MAJOR &&
dev_major != DRM_MAJOR) {
fprintf(stderr, "Device %s is not an input or DRM device\n",
message->path);
reply.ret = -EPERM;
goto err0;
}
if (dev_major == DRM_MAJOR && wl->drm_fd != -1) {
fprintf(stderr, "Already have a DRM device open\n");
reply.ret = -EPERM;
goto err0;
}
fd = open(message->path, message->flags);
if (fd < 0) {
fprintf(stderr, "Error opening device %s: %m\n",
message->path);
reply.ret = -errno;
goto err0;
}
if (dev_major == DRM_MAJOR) {
wl->drm_fd = fd;
}
err0:
memset(&nmsg, 0, sizeof nmsg);
nmsg.msg_iov = &iov;
nmsg.msg_iovlen = 1;
if (fd != -1) {
nmsg.msg_control = control;
nmsg.msg_controllen = sizeof control;
cmsg = CMSG_FIRSTHDR(&nmsg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
data = (union cmsg_data *) CMSG_DATA(cmsg);
data->fd = fd;
nmsg.msg_controllen = cmsg->cmsg_len;
reply.ret = 0;
}
iov.iov_base = &reply;
iov.iov_len = sizeof reply;
if (wl->verbose)
fprintf(stderr, "mutter-launch: opened %s: ret: %d, fd: %d\n",
message->path, reply.ret, fd);
do {
len = sendmsg(wl->sock[0], &nmsg, 0);
} while (len < 0 && errno == EINTR);
close(fd);
if (len < 0)
return -1;
return 0;
}
static int
handle_socket_msg(struct weston_launch *wl)
{
char control[CMSG_SPACE(sizeof(int))];
char buf[BUFSIZ];
struct msghdr msg;
struct iovec iov;
int ret = -1;
ssize_t len;
struct weston_launcher_message *message;
memset(&msg, 0, sizeof(msg));
iov.iov_base = buf;
iov.iov_len = sizeof buf;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = control;
msg.msg_controllen = sizeof control;
do {
len = recvmsg(wl->sock[0], &msg, 0);
} while (len < 0 && errno == EINTR);
if (len < 1)
return -1;
message = (void *) buf;
switch (message->opcode) {
case WESTON_LAUNCHER_OPEN:
ret = handle_open(wl, &msg, len);
break;
case WESTON_LAUNCHER_CONFIRM_VT_SWITCH:
ret = handle_confirm_vt_switch(wl, &msg, len);
break;
case WESTON_LAUNCHER_ACTIVATE_VT:
ret = handle_activate_vt(wl, &msg, len);
break;
}
return ret;
}
static void
tty_reset(struct weston_launch *wl)
{
struct vt_mode mode = { 0 };
if (ioctl(wl->tty, KDSKBMODE, wl->kb_mode))
fprintf(stderr, "failed to restore keyboard mode: %m\n");
if (ioctl(wl->tty, KDSETMODE, KD_TEXT))
fprintf(stderr, "failed to set KD_TEXT mode on tty: %m\n");
if (tcsetattr(wl->tty, TCSANOW, &wl->terminal_attributes) < 0)
fprintf(stderr, "could not restore terminal to canonical mode\n");
mode.mode = VT_AUTO;
if (ioctl(wl->tty, VT_SETMODE, &mode) < 0)
fprintf(stderr, "could not reset vt handling\n");
}
static void
quit(struct weston_launch *wl, int status)
{
if (wl->child > 0)
kill(wl->child, SIGKILL);
close(wl->signalfd);
close(wl->sock[0]);
if (wl->drm_fd > 0)
close(wl->drm_fd);
tty_reset(wl);
exit(status);
}
static int
handle_vt_switch(struct weston_launch *wl)
{
struct weston_launcher_event message;
ssize_t len;
if (wl->vt_state == VT_HAS_VT) {
wl->vt_state = VT_PENDING_CONFIRM;
message.header.opcode = WESTON_LAUNCHER_SERVER_REQUEST_VT_SWITCH;
} else if (wl->vt_state == VT_NOT_HAVE_VT) {
wl->vt_state = VT_HAS_VT;
ioctl(wl->tty, VT_RELDISP, VT_ACKACQ);
if (wl->drm_fd != -1) {
int ret;
ret = drmSetMaster(wl->drm_fd);
if (ret < 0) {
fprintf(stderr, "failed to become DRM master: %m\n");
/* This is very, very bad, and the compositor will crash soon,
but oh well... */
} else if (wl->verbose) {
fprintf(stderr, "became DRM master after VT switch\n");
}
}
message.header.opcode = WESTON_LAUNCHER_SERVER_VT_ENTER;
} else
return -1;
message.detail = 0;
do {
len = send(wl->sock[0], &message, sizeof(message), 0);
} while (len < 0 && errno == EINTR);
return 0;
}
static int
handle_signal(struct weston_launch *wl)
{
struct signalfd_siginfo sig;
int pid, status, ret;
if (read(wl->signalfd, &sig, sizeof sig) != sizeof sig) {
error(0, errno, "reading signalfd failed");
return -1;
}
switch (sig.ssi_signo) {
case SIGCHLD:
pid = waitpid(-1, &status, 0);
if (pid == wl->child) {
wl->child = 0;
if (WIFEXITED(status))
ret = WEXITSTATUS(status);
else if (WIFSIGNALED(status))
/*
* If weston dies because of signal N, we
* return 10+N. This is distinct from
* weston-launch dying because of a signal
* (128+N).
*/
ret = 10 + WTERMSIG(status);
else
ret = 0;
quit(wl, ret);
}
break;
case SIGTERM:
case SIGINT:
if (wl->child)
kill(wl->child, sig.ssi_signo);
break;
case SIGUSR1:
return handle_vt_switch(wl);
default:
return -1;
}
return 0;
}
static int
setup_tty(struct weston_launch *wl)
{
struct stat buf;
struct termios raw_attributes;
struct vt_mode mode = { 0 };
char *session;
char path[PATH_MAX];
int ok;
ok = sd_pid_get_session(getpid(), &session);
if (ok < 0)
error(1, -ok, "could not determine current session");
ok = sd_session_get_vt(session, &wl->vt);
if (ok < 0)
error(1, -ok, "could not determine current TTY");
snprintf(path, PATH_MAX, "/dev/tty%u", wl->vt);
wl->tty = open(path, O_RDWR | O_NOCTTY | O_CLOEXEC);
if (wl->tty < 0)
error(1, errno, "failed to open tty");
if (fstat(wl->tty, &buf) < 0)
error(1, errno, "stat %s failed", path);
if (major(buf.st_rdev) != TTY_MAJOR)
error(1, 0, "invalid tty device: %s", path);
wl->ttynr = minor(buf.st_rdev);
if (tcgetattr(wl->tty, &wl->terminal_attributes) < 0)
error(1, errno, "could not get terminal attributes");
/* Ignore control characters and disable echo */
raw_attributes = wl->terminal_attributes;
cfmakeraw(&raw_attributes);
/* Fix up line endings to be normal (cfmakeraw hoses them) */
raw_attributes.c_oflag |= OPOST | OCRNL;
/* Don't generate ttou signals */
raw_attributes.c_oflag &= ~TOSTOP;
if (tcsetattr(wl->tty, TCSANOW, &raw_attributes) < 0)
error(1, errno, "could not put terminal into raw mode");
ioctl(wl->tty, KDGKBMODE, &wl->kb_mode);
ok = ioctl(wl->tty, KDSKBMODE, K_OFF);
if (ok < 0) {
ok = ioctl(wl->tty, KDSKBMODE, K_RAW);
if (ok < 0)
error(1, errno, "failed to set keyboard mode on tty");
}
ok = ioctl(wl->tty, KDSETMODE, KD_GRAPHICS);
if (ok < 0)
error(1, errno, "failed to set KD_GRAPHICS mode on tty");
wl->vt_state = VT_HAS_VT;
mode.mode = VT_PROCESS;
mode.relsig = SIGUSR1;
mode.acqsig = SIGUSR1;
ok = ioctl(wl->tty, VT_SETMODE, &mode);
if (ok < 0)
error(1, errno, "failed to take control of vt handling");
return 0;
}
static void
drop_privileges(struct weston_launch *wl)
{
if (setgid(wl->pw->pw_gid) < 0 ||
#ifdef HAVE_INITGROUPS
initgroups(wl->pw->pw_name, wl->pw->pw_gid) < 0 ||
#endif
setuid(wl->pw->pw_uid) < 0)
error(1, errno, "dropping privileges failed");
}
static void
launch_compositor(struct weston_launch *wl, int argc, char *argv[])
{
char command[PATH_MAX];
char *child_argv[MAX_ARGV_SIZE];
sigset_t mask;
int i;
if (wl->verbose)
printf("weston-launch: spawned weston with pid: %d\n", getpid());
drop_privileges(wl);
setenv_fd("WESTON_LAUNCHER_SOCK", wl->sock[1]);
setenv("LD_LIBRARY_PATH", LIBDIR, 1);
unsetenv("DISPLAY");
/* Do not give our signal mask to the new process. */
sigemptyset(&mask);
sigaddset(&mask, SIGTERM);
sigaddset(&mask, SIGCHLD);
sigaddset(&mask, SIGINT);
sigaddset(&mask, SIGUSR1);
sigprocmask(SIG_UNBLOCK, &mask, NULL);
snprintf (command, PATH_MAX, "%s \"$@\"", argv[0]);
child_argv[0] = wl->pw->pw_shell;
child_argv[1] = "-l";
child_argv[2] = "-c";
child_argv[3] = command;
for (i = 0; i < argc; ++i)
child_argv[4 + i] = argv[i];
child_argv[4 + i] = NULL;
execv(child_argv[0], child_argv);
error(1, errno, "exec failed");
}
static void
help(const char *name)
{
fprintf(stderr, "Usage: %s [args...] [-- [weston args..]]\n", name);
fprintf(stderr, " -u, --user Start session as specified username\n");
fprintf(stderr, " -v, --verbose Be verbose\n");
fprintf(stderr, " -h, --help Display this help message\n");
}
int
main(int argc, char *argv[])
{
struct weston_launch wl;
int i, c;
struct option opts[] = {
{ "verbose", no_argument, NULL, 'v' },
{ "help", no_argument, NULL, 'h' },
{ 0, 0, NULL, 0 }
};
memset(&wl, 0, sizeof wl);
wl.drm_fd = -1;
while ((c = getopt_long(argc, argv, "u:t::vh", opts, &i)) != -1) {
switch (c) {
case 'v':
wl.verbose = 1;
break;
case 'h':
help("mutter-launch");
exit(EXIT_FAILURE);
}
}
if ((argc - optind) > (MAX_ARGV_SIZE - 6))
error(1, E2BIG, "Too many arguments to pass to weston");
if (optind >= argc)
error(1, 0, "Expected program argument");
wl.pw = getpwuid(getuid());
if (wl.pw == NULL)
error(1, errno, "failed to get username");
if (!weston_launch_allowed(&wl))
error(1, 0, "Permission denied. You must run from an active and local (systemd) session.");
if (setup_tty(&wl) < 0)
exit(EXIT_FAILURE);
if (setup_launcher_socket(&wl) < 0)
exit(EXIT_FAILURE);
if (setup_signals(&wl) < 0)
exit(EXIT_FAILURE);
wl.child = fork();
if (wl.child == -1) {
error(1, errno, "fork failed");
exit(EXIT_FAILURE);
}
if (wl.child == 0)
launch_compositor(&wl, argc - optind, argv + optind);
close(wl.sock[1]);
while (1) {
struct pollfd fds[2];
int n;
fds[0].fd = wl.sock[0];
fds[0].events = POLLIN;
fds[1].fd = wl.signalfd;
fds[1].events = POLLIN;
n = poll(fds, 2, -1);
if (n < 0)
error(0, errno, "poll failed");
if (fds[0].revents & POLLIN)
handle_socket_msg(&wl);
if (fds[1].revents)
handle_signal(&wl);
}
return 0;
}

View File

@ -0,0 +1,68 @@
/*
* Copyright © 2012 Benjamin Franzke
* 2013 Red Hat, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee, provided
* that the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of the copyright holders not be used in
* advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The copyright holders make
* no representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _WESTON_LAUNCH_H_
#define _WESTON_LAUNCH_H_
enum weston_launcher_message_type {
WESTON_LAUNCHER_REQUEST,
WESTON_LAUNCHER_EVENT,
};
enum weston_launcher_opcode {
WESTON_LAUNCHER_OPEN = (1 << 1 | WESTON_LAUNCHER_REQUEST),
WESTON_LAUNCHER_ACTIVATE_VT = (2 << 1 | WESTON_LAUNCHER_REQUEST),
WESTON_LAUNCHER_CONFIRM_VT_SWITCH = (3 << 1 | WESTON_LAUNCHER_REQUEST),
};
enum weston_launcher_server_opcode {
WESTON_LAUNCHER_SERVER_REQUEST_VT_SWITCH = (1 << 1 | WESTON_LAUNCHER_EVENT),
WESTON_LAUNCHER_SERVER_VT_ENTER = (2 << 1 | WESTON_LAUNCHER_EVENT),
};
struct weston_launcher_message {
int opcode;
};
struct weston_launcher_open {
struct weston_launcher_message header;
int flags;
char path[0];
};
struct weston_launcher_activate_vt {
struct weston_launcher_message header;
signed char vt;
};
struct weston_launcher_reply {
struct weston_launcher_message header;
int ret;
};
struct weston_launcher_event {
struct weston_launcher_message header;
int detail; /* unused, but makes sure replies and events are serialized the same */
};
#endif

View File

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

View File

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

View File

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

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