Compare commits
3 Commits
3.13.2
...
3.12.1-way
Author | SHA1 | Date | |
---|---|---|---|
![]() |
e947d2f544 | ||
![]() |
12e8d04c16 | ||
![]() |
783dbf9390 |
10
.gitignore
vendored
10
.gitignore
vendored
@@ -22,7 +22,7 @@ missing
|
|||||||
src/50-mutter-navigation.xml
|
src/50-mutter-navigation.xml
|
||||||
src/50-mutter-system.xml
|
src/50-mutter-system.xml
|
||||||
src/50-mutter-windows.xml
|
src/50-mutter-windows.xml
|
||||||
src/mutter.desktop
|
src/mutter-wm.desktop
|
||||||
src/mutter-wayland.desktop
|
src/mutter-wayland.desktop
|
||||||
*.o
|
*.o
|
||||||
*.a
|
*.a
|
||||||
@@ -46,8 +46,9 @@ POTFILES
|
|||||||
po/*.pot
|
po/*.pot
|
||||||
50-metacity-desktop-key.xml
|
50-metacity-desktop-key.xml
|
||||||
50-metacity-key.xml
|
50-metacity-key.xml
|
||||||
libmutter.pc
|
libmutter-wayland.pc
|
||||||
mutter
|
mutter-wayland
|
||||||
|
mutter-launch
|
||||||
org.gnome.mutter.gschema.valid
|
org.gnome.mutter.gschema.valid
|
||||||
org.gnome.mutter.gschema.xml
|
org.gnome.mutter.gschema.xml
|
||||||
org.gnome.mutter.wayland.gschema.valid
|
org.gnome.mutter.wayland.gschema.valid
|
||||||
@@ -55,7 +56,6 @@ org.gnome.mutter.wayland.gschema.xml
|
|||||||
testasyncgetprop
|
testasyncgetprop
|
||||||
testboxes
|
testboxes
|
||||||
testgradient
|
testgradient
|
||||||
m4/*
|
|
||||||
mutter-grayscale
|
mutter-grayscale
|
||||||
mutter-mag
|
mutter-mag
|
||||||
mutter-message
|
mutter-message
|
||||||
@@ -77,7 +77,7 @@ src/mutter-marshal.[ch]
|
|||||||
src/stamp-mutter-marshal.h
|
src/stamp-mutter-marshal.h
|
||||||
src/meta-dbus-display-config.[ch]
|
src/meta-dbus-display-config.[ch]
|
||||||
src/meta-dbus-idle-monitor.[ch]
|
src/meta-dbus-idle-monitor.[ch]
|
||||||
src/meta-dbus-login1.[ch]
|
src/mutter-plugins.pc
|
||||||
src/gtk-shell-protocol.c
|
src/gtk-shell-protocol.c
|
||||||
src/gtk-shell-server-protocol.h
|
src/gtk-shell-server-protocol.h
|
||||||
src/xdg-shell-protocol.c
|
src/xdg-shell-protocol.c
|
||||||
|
@@ -1,8 +1,6 @@
|
|||||||
|
|
||||||
SUBDIRS=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
|
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
|
||||||
|
47
NEWS
47
NEWS
@@ -1,50 +1,9 @@
|
|||||||
3.13.2
|
3.12.1
|
||||||
======
|
======
|
||||||
* Add basic HiDPI support on wayland [Adel; #728902]
|
* Fix crash when running as X11 compositor [Adel; #727115]
|
||||||
* 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:
|
Contributors:
|
||||||
Jonas Ådahl, Giovanni Campagna, Adel Gadllah, Florian Müllner,
|
Matthias Clasen, Adel Gadllah, Florian Müllner, Jasper St. Pierre
|
||||||
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
|
3.12.0
|
||||||
======
|
======
|
||||||
|
86
configure.ac
86
configure.ac
@@ -2,8 +2,8 @@ AC_PREREQ(2.50)
|
|||||||
AC_CONFIG_MACRO_DIR([m4])
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
|
|
||||||
m4_define([mutter_major_version], [3])
|
m4_define([mutter_major_version], [3])
|
||||||
m4_define([mutter_minor_version], [13])
|
m4_define([mutter_minor_version], [12])
|
||||||
m4_define([mutter_micro_version], [2])
|
m4_define([mutter_micro_version], [1])
|
||||||
|
|
||||||
m4_define([mutter_version],
|
m4_define([mutter_version],
|
||||||
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
||||||
@@ -13,7 +13,6 @@ m4_define([mutter_plugin_api_version], [3])
|
|||||||
AC_INIT([mutter], [mutter_version],
|
AC_INIT([mutter], [mutter_version],
|
||||||
[http://bugzilla.gnome.org/enter_bug.cgi?product=mutter])
|
[http://bugzilla.gnome.org/enter_bug.cgi?product=mutter])
|
||||||
|
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
|
||||||
AC_CONFIG_SRCDIR(src/core/display.c)
|
AC_CONFIG_SRCDIR(src/core/display.c)
|
||||||
AC_CONFIG_HEADERS(config.h)
|
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])],)
|
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],)
|
||||||
AM_MAINTAINER_MODE([enable])
|
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_MAJOR_VERSION=mutter_major_version
|
||||||
MUTTER_MINOR_VERSION=mutter_minor_version
|
MUTTER_MINOR_VERSION=mutter_minor_version
|
||||||
MUTTER_MICRO_VERSION=mutter_micro_version
|
MUTTER_MICRO_VERSION=mutter_micro_version
|
||||||
@@ -36,7 +39,7 @@ AC_SUBST(MUTTER_PLUGIN_DIR)
|
|||||||
# Honor aclocal flags
|
# Honor aclocal flags
|
||||||
AC_SUBST(ACLOCAL_AMFLAGS, "\${ACLOCAL_FLAGS}")
|
AC_SUBST(ACLOCAL_AMFLAGS, "\${ACLOCAL_FLAGS}")
|
||||||
|
|
||||||
GETTEXT_PACKAGE=mutter
|
GETTEXT_PACKAGE=mutter-wayland
|
||||||
AC_SUBST(GETTEXT_PACKAGE)
|
AC_SUBST(GETTEXT_PACKAGE)
|
||||||
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[Name of default gettext domain])
|
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[Name of default gettext domain])
|
||||||
|
|
||||||
@@ -69,12 +72,12 @@ CANBERRA_GTK_VERSION=0.26
|
|||||||
CLUTTER_PACKAGE=clutter-1.0
|
CLUTTER_PACKAGE=clutter-1.0
|
||||||
|
|
||||||
MUTTER_PC_MODULES="
|
MUTTER_PC_MODULES="
|
||||||
gtk+-3.0 >= 3.9.11
|
gtk+-3.0 >= 3.3.7
|
||||||
gio-2.0 >= 2.25.10
|
gio-2.0 >= 2.25.10
|
||||||
pango >= 1.2.0
|
pango >= 1.2.0
|
||||||
cairo >= 1.10.0
|
cairo >= 1.10.0
|
||||||
gsettings-desktop-schemas >= 3.7.3
|
gsettings-desktop-schemas >= 3.7.3
|
||||||
xcomposite >= 0.2 xfixes xext xdamage xi >= 1.6.0
|
xcomposite >= 0.2 xfixes xrender xdamage xi >= 1.6.0
|
||||||
$CLUTTER_PACKAGE >= 1.17.5
|
$CLUTTER_PACKAGE >= 1.17.5
|
||||||
cogl-1.0 >= 1.17.1
|
cogl-1.0 >= 1.17.1
|
||||||
upower-glib >= 0.99.0
|
upower-glib >= 0.99.0
|
||||||
@@ -117,16 +120,27 @@ AC_ARG_ENABLE(shape,
|
|||||||
[disable mutter's use of the shaped window extension]),,
|
[disable mutter's use of the shaped window extension]),,
|
||||||
enable_shape=auto)
|
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],
|
AC_ARG_WITH([xwayland-path],
|
||||||
[AS_HELP_STRING([--with-xwayland-path], [Absolute path for an X Wayland server])],
|
[AS_HELP_STRING([--with-xwayland-path], [Absolute path for an X Wayland server])],
|
||||||
[XWAYLAND_PATH="$withval"],
|
[XWAYLAND_PATH="$withval"],
|
||||||
[XWAYLAND_PATH="$bindir/Xwayland"])
|
[XWAYLAND_PATH="$bindir/Xorg"])
|
||||||
|
|
||||||
AM_GLIB_GNU_GETTEXT
|
AM_GLIB_GNU_GETTEXT
|
||||||
|
|
||||||
## here we get the flags we'll actually use
|
## here we get the flags we'll actually use
|
||||||
# GRegex requires Glib-2.14.0
|
# GRegex requires Glib-2.14.0
|
||||||
PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.14.0)
|
PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.14.0)
|
||||||
|
PKG_CHECK_MODULES(MUTTER_LAUNCH, libdrm libsystemd-login)
|
||||||
|
|
||||||
# Unconditionally use this dir to avoid a circular dep with gnomecc
|
# Unconditionally use this dir to avoid a circular dep with gnomecc
|
||||||
GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings"
|
GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings"
|
||||||
@@ -199,7 +213,7 @@ AS_IF([test "x$WAYLAND_SCANNER" = "xno"],
|
|||||||
AC_SUBST([WAYLAND_SCANNER])
|
AC_SUBST([WAYLAND_SCANNER])
|
||||||
AC_SUBST(XWAYLAND_PATH)
|
AC_SUBST(XWAYLAND_PATH)
|
||||||
|
|
||||||
MUTTER_PC_MODULES="$MUTTER_PC_MODULES clutter-wayland-1.0 clutter-wayland-compositor-1.0 clutter-egl-1.0 wayland-server >= 1.4.93 libdrm libsystemd"
|
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, $MUTTER_PC_MODULES)
|
||||||
|
|
||||||
PKG_CHECK_EXISTS([xi >= 1.6.99.1],
|
PKG_CHECK_EXISTS([xi >= 1.6.99.1],
|
||||||
@@ -238,6 +252,28 @@ if test x$have_xinerama = xno; then
|
|||||||
AC_MSG_ERROR([Xinerama extension was not found])
|
AC_MSG_ERROR([Xinerama extension was not found])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
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
|
found_xkb=no
|
||||||
AC_CHECK_LIB(X11, XkbQueryExtension,
|
AC_CHECK_LIB(X11, XkbQueryExtension,
|
||||||
[AC_CHECK_HEADER(X11/XKBlib.h,
|
[AC_CHECK_HEADER(X11/XKBlib.h,
|
||||||
@@ -255,13 +291,37 @@ AC_CHECK_LIB(Xrandr, XRRUpdateConfiguration,
|
|||||||
[AC_CHECK_HEADER(X11/extensions/Xrandr.h,
|
[AC_CHECK_HEADER(X11/extensions/Xrandr.h,
|
||||||
RANDR_LIBS=-lXrandr found_randr=yes,,
|
RANDR_LIBS=-lXrandr found_randr=yes,,
|
||||||
[#include <X11/Xlib.h>])],
|
[#include <X11/Xlib.h>])],
|
||||||
, -lXext $ALL_X_LIBS)
|
, -lXrender -lXext $ALL_X_LIBS)
|
||||||
|
|
||||||
if test "x$found_randr" = "xyes"; then
|
if test "x$found_randr" = "xyes"; then
|
||||||
AC_DEFINE(HAVE_RANDR, , [Have the Xrandr extension library])
|
AC_DEFINE(HAVE_RANDR, , [Have the Xrandr extension library])
|
||||||
fi
|
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
|
found_sm=no
|
||||||
case "$MUTTER_LIBS" in
|
case "$MUTTER_LIBS" in
|
||||||
@@ -391,7 +451,7 @@ doc/man/Makefile
|
|||||||
doc/reference/Makefile
|
doc/reference/Makefile
|
||||||
doc/reference/meta-docs.sgml
|
doc/reference/meta-docs.sgml
|
||||||
src/Makefile
|
src/Makefile
|
||||||
src/libmutter.pc
|
src/libmutter-wayland.pc
|
||||||
src/compositor/plugins/Makefile
|
src/compositor/plugins/Makefile
|
||||||
po/Makefile.in
|
po/Makefile.in
|
||||||
])
|
])
|
||||||
@@ -408,7 +468,7 @@ fi
|
|||||||
|
|
||||||
dnl ==========================================================================
|
dnl ==========================================================================
|
||||||
echo "
|
echo "
|
||||||
mutter-$VERSION
|
mutter-wayland-$VERSION
|
||||||
|
|
||||||
prefix: ${prefix}
|
prefix: ${prefix}
|
||||||
source code location: ${srcdir}
|
source code location: ${srcdir}
|
||||||
@@ -418,6 +478,8 @@ mutter-$VERSION
|
|||||||
libcanberra: ${have_libcanberra}
|
libcanberra: ${have_libcanberra}
|
||||||
Introspection: ${found_introspection}
|
Introspection: ${found_introspection}
|
||||||
Session management: ${found_sm}
|
Session management: ${found_sm}
|
||||||
|
Shape extension: ${found_shape}
|
||||||
|
Xsync: ${found_xsync}
|
||||||
"
|
"
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
defaultcursordir = $(datadir)/mutter/cursors
|
|
||||||
|
|
||||||
dist_defaultcursor_DATA = left_ptr.png
|
|
@@ -79,6 +79,8 @@ IGNORE_HFILES= \
|
|||||||
iconcache.h \
|
iconcache.h \
|
||||||
inlinepixbufs.h \
|
inlinepixbufs.h \
|
||||||
keybindings-private.h \
|
keybindings-private.h \
|
||||||
|
menu.h \
|
||||||
|
metaaccellabel.h \
|
||||||
meta-background-actor-private.h \
|
meta-background-actor-private.h \
|
||||||
meta-background-group-private.h \
|
meta-background-group-private.h \
|
||||||
meta-module.h \
|
meta-module.h \
|
||||||
@@ -138,7 +140,7 @@ expand_content_files= \
|
|||||||
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
|
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
|
||||||
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
|
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
|
||||||
GTKDOC_CFLAGS=$(MUTTER_CFLAGS)
|
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.
|
# This includes the standard gtk-doc make rules, copied by gtkdocize.
|
||||||
include $(top_srcdir)/gtk-doc.make
|
include $(top_srcdir)/gtk-doc.make
|
||||||
|
@@ -21,6 +21,7 @@ environment.</description>
|
|||||||
-->
|
-->
|
||||||
<mailing-list rdf:resource="http://mail.gnome.org/mailman/listinfo/gnome-shell-list" />
|
<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/" />
|
||||||
|
<download-page rdf:resource="http://download.gnome.org/sources/mutter-wayland/" />
|
||||||
<bug-database rdf:resource="http://bugzilla.gnome.org/browse.cgi?product=mutter" />
|
<bug-database rdf:resource="http://bugzilla.gnome.org/browse.cgi?product=mutter" />
|
||||||
|
|
||||||
<category rdf:resource="http://api.gnome.org/doap-extensions#desktop" />
|
<category rdf:resource="http://api.gnome.org/doap-extensions#desktop" />
|
||||||
|
@@ -16,15 +16,17 @@ src/core/main.c
|
|||||||
src/core/mutter.c
|
src/core/mutter.c
|
||||||
src/core/prefs.c
|
src/core/prefs.c
|
||||||
src/core/screen.c
|
src/core/screen.c
|
||||||
|
src/x11/session.c
|
||||||
src/core/util.c
|
src/core/util.c
|
||||||
src/core/window.c
|
src/core/window.c
|
||||||
src/mutter.desktop.in
|
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.gschema.xml.in
|
||||||
src/org.gnome.mutter.wayland.gschema.xml.in
|
src/org.gnome.mutter.wayland.gschema.xml.in
|
||||||
src/ui/frames.c
|
src/ui/frames.c
|
||||||
|
src/ui/menu.c
|
||||||
|
src/ui/metaaccellabel.c
|
||||||
src/ui/resizepopup.c
|
src/ui/resizepopup.c
|
||||||
src/ui/theme.c
|
src/ui/theme.c
|
||||||
src/ui/theme-parser.c
|
src/ui/theme-parser.c
|
||||||
src/x11/session.c
|
|
||||||
src/x11/window-props.c
|
|
||||||
src/x11/xprops.c
|
|
||||||
|
@@ -1,2 +1,2 @@
|
|||||||
src/metacity.schemas.in
|
src/metacity.schemas.in
|
||||||
src/mutter-wayland.desktop.in
|
|
||||||
|
2834
po/ca@valencia.po
2834
po/ca@valencia.po
File diff suppressed because it is too large
Load Diff
805
po/pt_BR.po
805
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
417
po/sk.po
417
po/sk.po
@@ -13,9 +13,9 @@ msgstr ""
|
|||||||
"Project-Id-Version: mutter\n"
|
"Project-Id-Version: mutter\n"
|
||||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
|
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
|
||||||
"product=mutter&keywords=I18N+L10N&component=general\n"
|
"product=mutter&keywords=I18N+L10N&component=general\n"
|
||||||
"POT-Creation-Date: 2013-08-21 17:41+0000\n"
|
"POT-Creation-Date: 2013-05-24 21:44+0000\n"
|
||||||
"PO-Revision-Date: 2013-08-02 14:46+0200\n"
|
"PO-Revision-Date: 2013-05-18 16:53+0100\n"
|
||||||
"Last-Translator: Ján Kyselica <kyselica.jan@gmail.com>\n"
|
"Last-Translator: Jan Kyselica <kyselica.jan@gmail.com>\n"
|
||||||
"Language-Team: Slovak <gnome-sk-list@gnome.org>\n"
|
"Language-Team: Slovak <gnome-sk-list@gnome.org>\n"
|
||||||
"Language: sk\n"
|
"Language: sk\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
@@ -87,8 +87,9 @@ msgstr "Prepnúť okná aplikácie"
|
|||||||
# PK: zisti co to robi
|
# PK: zisti co to robi
|
||||||
# description
|
# description
|
||||||
#: ../src/50-mutter-navigation.xml.in.h:13
|
#: ../src/50-mutter-navigation.xml.in.h:13
|
||||||
|
#, fuzzy
|
||||||
msgid "Switch system controls"
|
msgid "Switch system controls"
|
||||||
msgstr "Prepnúť medzi ovládacími prvkami systému"
|
msgstr "Prepnúť medzi systémovými ovládacími prvkami"
|
||||||
|
|
||||||
# description
|
# description
|
||||||
#: ../src/50-mutter-navigation.xml.in.h:14
|
#: ../src/50-mutter-navigation.xml.in.h:14
|
||||||
@@ -103,8 +104,9 @@ msgstr "Prepnúť okná aplikácie priamo"
|
|||||||
# MČ: podobne ako vyššie: „cycle-panels“
|
# MČ: podobne ako vyššie: „cycle-panels“
|
||||||
# description
|
# description
|
||||||
#: ../src/50-mutter-navigation.xml.in.h:16
|
#: ../src/50-mutter-navigation.xml.in.h:16
|
||||||
|
#, fuzzy
|
||||||
msgid "Switch system controls directly"
|
msgid "Switch system controls directly"
|
||||||
msgstr "Prepnúť medzi ovládacími prvkami systému priamo"
|
msgstr "Prepnúť medzi systémovými ovládacími prvkami priamo"
|
||||||
|
|
||||||
# description
|
# description
|
||||||
#: ../src/50-mutter-navigation.xml.in.h:17
|
#: ../src/50-mutter-navigation.xml.in.h:17
|
||||||
@@ -265,13 +267,13 @@ msgstr "Zobraziť rozdelenie napravo"
|
|||||||
# PK: je %i cislo obrazovky? ak ano tak "č. %i"
|
# PK: je %i cislo obrazovky? ak ano tak "č. %i"
|
||||||
#. This probably means that a non-WM compositor like xcompmgr is running;
|
#. This probably means that a non-WM compositor like xcompmgr is running;
|
||||||
#. * we have no way to get it to exit
|
#. * we have no way to get it to exit
|
||||||
#: ../src/compositor/compositor.c:596
|
#: ../src/compositor/compositor.c:571
|
||||||
#, c-format
|
#, fuzzy, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Another compositing manager is already running on screen %i on display \"%s"
|
"Another compositing manager is already running on screen %i on display \"%s"
|
||||||
"\"."
|
"\"."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Pre obrazovku č. %i na displeji „%s“ je spustený už iný správca rozloženia."
|
"Pre obrazovku %i na displeji „%s“ je spustený už iný správca rozloženia."
|
||||||
|
|
||||||
#: ../src/compositor/meta-background.c:1076
|
#: ../src/compositor/meta-background.c:1076
|
||||||
msgid "background texture could not be created from file"
|
msgid "background texture could not be created from file"
|
||||||
@@ -311,18 +313,18 @@ msgstr "_Počkať"
|
|||||||
msgid "_Force Quit"
|
msgid "_Force Quit"
|
||||||
msgstr "_Vynútiť ukončenie"
|
msgstr "_Vynútiť ukončenie"
|
||||||
|
|
||||||
#: ../src/core/display.c:421
|
#: ../src/core/display.c:401
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Missing %s extension required for compositing"
|
msgid "Missing %s extension required for compositing"
|
||||||
msgstr "Rozšírenie %s, potrebné pre kompozitné prostredie, chýba"
|
msgstr "Rozšírenie %s, potrebné pre kompozitné prostredie, chýba"
|
||||||
|
|
||||||
# X window system preloz, napr. system na spravu okien X
|
# X window system preloz, napr. system na spravu okien X
|
||||||
#: ../src/core/display.c:513
|
#: ../src/core/display.c:493
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Failed to open X Window System display '%s'\n"
|
msgid "Failed to open X Window System display '%s'\n"
|
||||||
msgstr "Zlyhalo otvorenie displeja systému na správu okien X „%s“\n"
|
msgstr "Zlyhalo otvorenie displeja systému na správu okien X „%s“\n"
|
||||||
|
|
||||||
#: ../src/core/keybindings.c:1136
|
#: ../src/core/keybindings.c:970
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Some other program is already using the key %s with modifiers %x as a "
|
"Some other program is already using the key %s with modifiers %x as a "
|
||||||
@@ -330,7 +332,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Iný program už používa kláves %s s modifikátormi %x ako klávesovú skratku\n"
|
"Iný program už používa kláves %s s modifikátormi %x ako klávesovú skratku\n"
|
||||||
|
|
||||||
#: ../src/core/keybindings.c:1333
|
#: ../src/core/keybindings.c:1151
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "\"%s\" is not a valid accelerator\n"
|
msgid "\"%s\" is not a valid accelerator\n"
|
||||||
msgstr "„%s“ nie je platný akcelerátor\n"
|
msgstr "„%s“ nie je platný akcelerátor\n"
|
||||||
@@ -376,20 +378,6 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Nepodarilo sa nájsť tému! Overte, že %s existuje a obsahuje obvyklé témy.\n"
|
"Nepodarilo sa nájsť tému! Overte, že %s existuje a obsahuje obvyklé témy.\n"
|
||||||
|
|
||||||
#: ../src/core/monitor.c:702
|
|
||||||
msgid "Built-in display"
|
|
||||||
msgstr "Vstavaný displej"
|
|
||||||
|
|
||||||
#. TRANSLATORS: this is a monitor name (in case we don't know
|
|
||||||
#. the vendor), it's Unknown followed by a size in inches,
|
|
||||||
#. like 'Unknown 15"'
|
|
||||||
#.
|
|
||||||
#: ../src/core/monitor.c:730
|
|
||||||
#, c-format
|
|
||||||
#| msgid "Unknown element %s"
|
|
||||||
msgid "Unknown %s"
|
|
||||||
msgstr "Neznámy %s"
|
|
||||||
|
|
||||||
#: ../src/core/mutter.c:40
|
#: ../src/core/mutter.c:40
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
@@ -415,7 +403,7 @@ msgstr "Zobrazí verziu"
|
|||||||
msgid "Mutter plugin to use"
|
msgid "Mutter plugin to use"
|
||||||
msgstr "Použije zásuvný modul Mutter"
|
msgstr "Použije zásuvný modul Mutter"
|
||||||
|
|
||||||
#: ../src/core/prefs.c:1202
|
#: ../src/core/prefs.c:1193
|
||||||
msgid ""
|
msgid ""
|
||||||
"Workarounds for broken applications disabled. Some applications may not "
|
"Workarounds for broken applications disabled. Some applications may not "
|
||||||
"behave properly.\n"
|
"behave properly.\n"
|
||||||
@@ -423,12 +411,12 @@ msgstr ""
|
|||||||
"Náhradné riešenia pre chybné aplikácie nie sú povolené. Niektoré aplikácie "
|
"Náhradné riešenia pre chybné aplikácie nie sú povolené. Niektoré aplikácie "
|
||||||
"sa nemusia správať správne.\n"
|
"sa nemusia správať správne.\n"
|
||||||
|
|
||||||
#: ../src/core/prefs.c:1277
|
#: ../src/core/prefs.c:1268
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Could not parse font description \"%s\" from GSettings key %s\n"
|
msgid "Could not parse font description \"%s\" from GSettings key %s\n"
|
||||||
msgstr "Nepodarilo sa spracovať popis písma „%s“ z kľúča GSettings %s\n"
|
msgstr "Nepodarilo sa spracovať popis písma „%s“ z kľúča GSettings %s\n"
|
||||||
|
|
||||||
#: ../src/core/prefs.c:1343
|
#: ../src/core/prefs.c:1334
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"\"%s\" found in configuration database is not a valid value for mouse button "
|
"\"%s\" found in configuration database is not a valid value for mouse button "
|
||||||
@@ -437,7 +425,7 @@ msgstr ""
|
|||||||
"V konfiguračnej databáze sa našlo „%s“, čo nie je platná hodnota pre "
|
"V konfiguračnej databáze sa našlo „%s“, čo nie je platná hodnota pre "
|
||||||
"modifikátor tlačidla myši\n"
|
"modifikátor tlačidla myši\n"
|
||||||
|
|
||||||
#: ../src/core/prefs.c:1909
|
#: ../src/core/prefs.c:1881
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"\"%s\" found in configuration database is not a valid value for keybinding "
|
"\"%s\" found in configuration database is not a valid value for keybinding "
|
||||||
@@ -446,17 +434,17 @@ msgstr ""
|
|||||||
"V konfiguračnej databáze sa našlo „%s“, čo nie je platná hodnota pre "
|
"V konfiguračnej databáze sa našlo „%s“, čo nie je platná hodnota pre "
|
||||||
"klávesovú skratku „%s“\n"
|
"klávesovú skratku „%s“\n"
|
||||||
|
|
||||||
#: ../src/core/prefs.c:1999
|
#: ../src/core/prefs.c:1945
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Workspace %d"
|
msgid "Workspace %d"
|
||||||
msgstr "Pracovný priestor č. %d"
|
msgstr "Pracovný priestor č. %d"
|
||||||
|
|
||||||
#: ../src/core/screen.c:537
|
#: ../src/core/screen.c:691
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Screen %d on display '%s' is invalid\n"
|
msgid "Screen %d on display '%s' is invalid\n"
|
||||||
msgstr "Obrazovka č. %d na displeji „%s“ nie je platná\n"
|
msgstr "Obrazovka č. %d na displeji „%s“ nie je platná\n"
|
||||||
|
|
||||||
#: ../src/core/screen.c:553
|
#: ../src/core/screen.c:707
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Screen %d on display \"%s\" already has a window manager; try using the --"
|
"Screen %d on display \"%s\" already has a window manager; try using the --"
|
||||||
@@ -465,7 +453,7 @@ msgstr ""
|
|||||||
"Obrazovka č. %d na displeji „%s“ už má správcu okien. Skúste použiť prepínač "
|
"Obrazovka č. %d na displeji „%s“ už má správcu okien. Skúste použiť prepínač "
|
||||||
"--replace, aby sa aktuálny správca nahradil.\n"
|
"--replace, aby sa aktuálny správca nahradil.\n"
|
||||||
|
|
||||||
#: ../src/core/screen.c:580
|
#: ../src/core/screen.c:734
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Could not acquire window manager selection on screen %d display \"%s\"\n"
|
"Could not acquire window manager selection on screen %d display \"%s\"\n"
|
||||||
@@ -473,12 +461,12 @@ msgstr ""
|
|||||||
"Nepodarilo sa získať výber správcu okien pre obrazovku č. %d na displeji "
|
"Nepodarilo sa získať výber správcu okien pre obrazovku č. %d na displeji "
|
||||||
"„%s“\n"
|
"„%s“\n"
|
||||||
|
|
||||||
#: ../src/core/screen.c:658
|
#: ../src/core/screen.c:812
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Screen %d on display \"%s\" already has a window manager\n"
|
msgid "Screen %d on display \"%s\" already has a window manager\n"
|
||||||
msgstr "Obrazovka č. %d na displeji „%s“ už má správcu okien\n"
|
msgstr "Obrazovka č. %d na displeji „%s“ už má správcu okien\n"
|
||||||
|
|
||||||
#: ../src/core/screen.c:850
|
#: ../src/core/screen.c:998
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Could not release screen %d on display \"%s\"\n"
|
msgid "Could not release screen %d on display \"%s\"\n"
|
||||||
msgstr "Nepodarilo sa uvoľniť obrazovku č. %d na displeji „%s“\n"
|
msgstr "Nepodarilo sa uvoľniť obrazovku č. %d na displeji „%s“\n"
|
||||||
@@ -554,7 +542,8 @@ msgstr "Zlyhalo otvorenie súboru so záznamom pomocou fdopen() %s: %s\n"
|
|||||||
msgid "Opened log file %s\n"
|
msgid "Opened log file %s\n"
|
||||||
msgstr "Otvorený súbor so záznamom %s\n"
|
msgstr "Otvorený súbor so záznamom %s\n"
|
||||||
|
|
||||||
#: ../src/core/util.c:119
|
#: ../src/core/util.c:119 ../src/tools/mutter-message.c:149
|
||||||
|
#, c-format
|
||||||
msgid "Mutter was compiled without support for verbose mode\n"
|
msgid "Mutter was compiled without support for verbose mode\n"
|
||||||
msgstr "Mutter bol skompilovaný bez výpisu podrobností pri behu\n"
|
msgstr "Mutter bol skompilovaný bez výpisu podrobností pri behu\n"
|
||||||
|
|
||||||
@@ -562,20 +551,20 @@ msgstr "Mutter bol skompilovaný bez výpisu podrobností pri behu\n"
|
|||||||
msgid "Window manager: "
|
msgid "Window manager: "
|
||||||
msgstr "Správca okien: "
|
msgstr "Správca okien: "
|
||||||
|
|
||||||
#: ../src/core/util.c:414
|
#: ../src/core/util.c:412
|
||||||
msgid "Bug in window manager: "
|
msgid "Bug in window manager: "
|
||||||
msgstr "Chyba v správcovi okien: "
|
msgstr "Chyba v správcovi okien: "
|
||||||
|
|
||||||
#: ../src/core/util.c:445
|
#: ../src/core/util.c:443
|
||||||
msgid "Window manager warning: "
|
msgid "Window manager warning: "
|
||||||
msgstr "Varovanie správcu okien: "
|
msgstr "Varovanie správcu okien: "
|
||||||
|
|
||||||
#: ../src/core/util.c:473
|
#: ../src/core/util.c:471
|
||||||
msgid "Window manager error: "
|
msgid "Window manager error: "
|
||||||
msgstr "Chyba správcu okien: "
|
msgstr "Chyba správcu okien: "
|
||||||
|
|
||||||
#. first time through
|
#. first time through
|
||||||
#: ../src/core/window.c:7533
|
#: ../src/core/window.c:7505
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER "
|
"Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER "
|
||||||
@@ -591,7 +580,7 @@ msgstr ""
|
|||||||
#. * MWM but not WM_NORMAL_HINTS are basically broken. We complain
|
#. * MWM but not WM_NORMAL_HINTS are basically broken. We complain
|
||||||
#. * about these apps but make them work.
|
#. * about these apps but make them work.
|
||||||
#.
|
#.
|
||||||
#: ../src/core/window.c:8257
|
#: ../src/core/window.c:8229
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Window %s sets an MWM hint indicating it isn't resizable, but sets min size "
|
"Window %s sets an MWM hint indicating it isn't resizable, but sets min size "
|
||||||
@@ -601,7 +590,7 @@ msgstr ""
|
|||||||
"nastavuje minimálnu veľkosť %d x %d a maximálnu veľkosť %d x %d. To nedáva "
|
"nastavuje minimálnu veľkosť %d x %d a maximálnu veľkosť %d x %d. To nedáva "
|
||||||
"zmysel.\n"
|
"zmysel.\n"
|
||||||
|
|
||||||
#: ../src/core/window-props.c:347
|
#: ../src/core/window-props.c:318
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Application set a bogus _NET_WM_PID %lu\n"
|
msgid "Application set a bogus _NET_WM_PID %lu\n"
|
||||||
msgstr "Aplikácia nastavila neplatné _NET_WM_PID %lu\n"
|
msgstr "Aplikácia nastavila neplatné _NET_WM_PID %lu\n"
|
||||||
@@ -609,18 +598,18 @@ msgstr "Aplikácia nastavila neplatné _NET_WM_PID %lu\n"
|
|||||||
# PK: co je toto?
|
# PK: co je toto?
|
||||||
# JK: nedokazem zistit
|
# JK: nedokazem zistit
|
||||||
# PM: vyžiadaj komentár od vývojárov, pomožeme aj ostatným prekladateľom
|
# PM: vyžiadaj komentár od vývojárov, pomožeme aj ostatným prekladateľom
|
||||||
#: ../src/core/window-props.c:463
|
#: ../src/core/window-props.c:434
|
||||||
#, fuzzy, c-format
|
#, fuzzy, c-format
|
||||||
msgid "%s (on %s)"
|
msgid "%s (on %s)"
|
||||||
msgstr "%s (na %s)"
|
msgstr "%s (na %s)"
|
||||||
|
|
||||||
#: ../src/core/window-props.c:1546
|
#: ../src/core/window-props.c:1517
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n"
|
msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n"
|
||||||
msgstr "Neplatné WM_TRANSIENT_FOR okno 0x%lx nastavené pre %s.\n"
|
msgstr "Neplatné WM_TRANSIENT_FOR okno 0x%lx nastavené pre %s.\n"
|
||||||
|
|
||||||
# MČ: zacykliť sa, alebo vytvoriť slučku.
|
# MČ: zacykliť sa, alebo vytvoriť slučku.
|
||||||
#: ../src/core/window-props.c:1557
|
#: ../src/core/window-props.c:1528
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n"
|
msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n"
|
||||||
msgstr "WM_TRANSIENT_FOR okno 0x%lx pre %s môže vytvoriť slučku.\n"
|
msgstr "WM_TRANSIENT_FOR okno 0x%lx pre %s môže vytvoriť slučku.\n"
|
||||||
@@ -708,9 +697,9 @@ msgid ""
|
|||||||
"vertically and resizes them horizontally to cover half of the available "
|
"vertically and resizes them horizontally to cover half of the available "
|
||||||
"area. Dropping windows on the top screen edge maximizes them completely."
|
"area. Dropping windows on the top screen edge maximizes them completely."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Ak je povolené, upustenie okien pri zvislých okrajoch obrazovky ich zvislo "
|
"Ak je povolené, upustenie okien pri zvislých okrajoch obrazovky ich "
|
||||||
"maximalizuje a vodorovná veľkosť sa zmení na polovicu dostupnej plochy. "
|
"zvislo maximalizuje a vodorovná veľkosť sa zmení na polovicu dostupnej "
|
||||||
"Upustenie okien pri vrchnom okraji obrazovky ich maximalizuje úplne."
|
"plochy. Upustenie okien pri vrchnom okraji obrazovky ich maximalizuje úplne."
|
||||||
|
|
||||||
# summary
|
# summary
|
||||||
#: ../src/org.gnome.mutter.gschema.xml.in.h:7
|
#: ../src/org.gnome.mutter.gschema.xml.in.h:7
|
||||||
@@ -746,8 +735,9 @@ msgstr ""
|
|||||||
# PM: ja by som dal Bez vyvovlávania tabulátorom
|
# PM: ja by som dal Bez vyvovlávania tabulátorom
|
||||||
# summary
|
# summary
|
||||||
#: ../src/org.gnome.mutter.gschema.xml.in.h:11
|
#: ../src/org.gnome.mutter.gschema.xml.in.h:11
|
||||||
|
#, fuzzy
|
||||||
msgid "No tab popup"
|
msgid "No tab popup"
|
||||||
msgstr "Bez vyvolávania tabulátorom"
|
msgstr "Nepoužívať prekryvnú ponuku tabulátora"
|
||||||
|
|
||||||
# MČ: Neviem, čo to presne má robiť, ale popis som pochopil inak. „…či sa má používať rozbaľovacia ponuka a zvýraznenie rámikom sa má vypnúť…“
|
# MČ: Neviem, čo to presne má robiť, ale popis som pochopil inak. „…či sa má používať rozbaľovacia ponuka a zvýraznenie rámikom sa má vypnúť…“
|
||||||
# description
|
# description
|
||||||
@@ -816,104 +806,109 @@ msgstr "Vybrať okno z rozbaľovacej ponuky tabulátoru"
|
|||||||
msgid "Cancel tab popup"
|
msgid "Cancel tab popup"
|
||||||
msgstr "Zrušit rozbaľovaciu ponuku tabulátoru"
|
msgstr "Zrušit rozbaľovaciu ponuku tabulátoru"
|
||||||
|
|
||||||
|
#: ../src/tools/mutter-message.c:123
|
||||||
|
#, c-format
|
||||||
|
msgid "Usage: %s\n"
|
||||||
|
msgstr "Použitie: %s\n"
|
||||||
|
|
||||||
#. Translators: Translate this string the same way as you do in libwnck!
|
#. Translators: Translate this string the same way as you do in libwnck!
|
||||||
#: ../src/ui/menu.c:67
|
#: ../src/ui/menu.c:69
|
||||||
msgid "Mi_nimize"
|
msgid "Mi_nimize"
|
||||||
msgstr "Mi_nimalizovať"
|
msgstr "Mi_nimalizovať"
|
||||||
|
|
||||||
#. Translators: Translate this string the same way as you do in libwnck!
|
#. Translators: Translate this string the same way as you do in libwnck!
|
||||||
#: ../src/ui/menu.c:69
|
#: ../src/ui/menu.c:71
|
||||||
msgid "Ma_ximize"
|
msgid "Ma_ximize"
|
||||||
msgstr "Ma_ximalizovať"
|
msgstr "Ma_ximalizovať"
|
||||||
|
|
||||||
#. Translators: Translate this string the same way as you do in libwnck!
|
#. Translators: Translate this string the same way as you do in libwnck!
|
||||||
#: ../src/ui/menu.c:71
|
#: ../src/ui/menu.c:73
|
||||||
msgid "Unma_ximize"
|
msgid "Unma_ximize"
|
||||||
msgstr "Zrušiť ma_ximalizáciu"
|
msgstr "Zrušiť ma_ximalizáciu"
|
||||||
|
|
||||||
#. Translators: Translate this string the same way as you do in libwnck!
|
#. Translators: Translate this string the same way as you do in libwnck!
|
||||||
#: ../src/ui/menu.c:73
|
#: ../src/ui/menu.c:75
|
||||||
msgid "Roll _Up"
|
msgid "Roll _Up"
|
||||||
msgstr "_Zabaliť"
|
msgstr "_Zabaliť"
|
||||||
|
|
||||||
#. Translators: Translate this string the same way as you do in libwnck!
|
#. Translators: Translate this string the same way as you do in libwnck!
|
||||||
#: ../src/ui/menu.c:75
|
#: ../src/ui/menu.c:77
|
||||||
msgid "_Unroll"
|
msgid "_Unroll"
|
||||||
msgstr "_Rozbaliť"
|
msgstr "_Rozbaliť"
|
||||||
|
|
||||||
#. Translators: Translate this string the same way as you do in libwnck!
|
#. Translators: Translate this string the same way as you do in libwnck!
|
||||||
#: ../src/ui/menu.c:77
|
#: ../src/ui/menu.c:79
|
||||||
msgid "_Move"
|
msgid "_Move"
|
||||||
msgstr "Pre_miestniť"
|
msgstr "Pre_miestniť"
|
||||||
|
|
||||||
#. Translators: Translate this string the same way as you do in libwnck!
|
#. Translators: Translate this string the same way as you do in libwnck!
|
||||||
#: ../src/ui/menu.c:79
|
#: ../src/ui/menu.c:81
|
||||||
msgid "_Resize"
|
msgid "_Resize"
|
||||||
msgstr "Zmeniť veľko_sť"
|
msgstr "Zmeniť veľko_sť"
|
||||||
|
|
||||||
#. Translators: Translate this string the same way as you do in libwnck!
|
#. Translators: Translate this string the same way as you do in libwnck!
|
||||||
#: ../src/ui/menu.c:81
|
#: ../src/ui/menu.c:83
|
||||||
msgid "Move Titlebar On_screen"
|
msgid "Move Titlebar On_screen"
|
||||||
msgstr "Presunúť titulok na _obrazovku"
|
msgstr "Presunúť titulok na _obrazovku"
|
||||||
|
|
||||||
#. separator
|
#. separator
|
||||||
#. Translators: Translate this string the same way as you do in libwnck!
|
#. Translators: Translate this string the same way as you do in libwnck!
|
||||||
#: ../src/ui/menu.c:84 ../src/ui/menu.c:86
|
#: ../src/ui/menu.c:86 ../src/ui/menu.c:88
|
||||||
msgid "Always on _Top"
|
msgid "Always on _Top"
|
||||||
msgstr "Vždy na_vrchu"
|
msgstr "Vždy na_vrchu"
|
||||||
|
|
||||||
#. Translators: Translate this string the same way as you do in libwnck!
|
#. Translators: Translate this string the same way as you do in libwnck!
|
||||||
#: ../src/ui/menu.c:88
|
#: ../src/ui/menu.c:90
|
||||||
msgid "_Always on Visible Workspace"
|
msgid "_Always on Visible Workspace"
|
||||||
msgstr "Vž_dy na viditeľnom pracovnom priestore"
|
msgstr "Vž_dy na viditeľnom pracovnom priestore"
|
||||||
|
|
||||||
#. Translators: Translate this string the same way as you do in libwnck!
|
#. Translators: Translate this string the same way as you do in libwnck!
|
||||||
#: ../src/ui/menu.c:90
|
#: ../src/ui/menu.c:92
|
||||||
msgid "_Only on This Workspace"
|
msgid "_Only on This Workspace"
|
||||||
msgstr "_Len na tomto pracovnom priestore"
|
msgstr "_Len na tomto pracovnom priestore"
|
||||||
|
|
||||||
#. Translators: Translate this string the same way as you do in libwnck!
|
#. Translators: Translate this string the same way as you do in libwnck!
|
||||||
#: ../src/ui/menu.c:92
|
#: ../src/ui/menu.c:94
|
||||||
msgid "Move to Workspace _Left"
|
msgid "Move to Workspace _Left"
|
||||||
msgstr "Presunúť na pracovný priestor vľav_o"
|
msgstr "Presunúť na pracovný priestor vľav_o"
|
||||||
|
|
||||||
#. Translators: Translate this string the same way as you do in libwnck!
|
#. Translators: Translate this string the same way as you do in libwnck!
|
||||||
#: ../src/ui/menu.c:94
|
#: ../src/ui/menu.c:96
|
||||||
msgid "Move to Workspace R_ight"
|
msgid "Move to Workspace R_ight"
|
||||||
msgstr "Presunúť na pracovný priestor v_pravo"
|
msgstr "Presunúť na pracovný priestor v_pravo"
|
||||||
|
|
||||||
#. Translators: Translate this string the same way as you do in libwnck!
|
#. Translators: Translate this string the same way as you do in libwnck!
|
||||||
#: ../src/ui/menu.c:96
|
#: ../src/ui/menu.c:98
|
||||||
msgid "Move to Workspace _Up"
|
msgid "Move to Workspace _Up"
|
||||||
msgstr "Presunúť na pracovný priestor _hore"
|
msgstr "Presunúť na pracovný priestor _hore"
|
||||||
|
|
||||||
#. Translators: Translate this string the same way as you do in libwnck!
|
#. Translators: Translate this string the same way as you do in libwnck!
|
||||||
#: ../src/ui/menu.c:98
|
#: ../src/ui/menu.c:100
|
||||||
msgid "Move to Workspace _Down"
|
msgid "Move to Workspace _Down"
|
||||||
msgstr "Presunúť na pracovný priestor _dole"
|
msgstr "Presunúť na pracovný priestor _dole"
|
||||||
|
|
||||||
#. separator
|
#. separator
|
||||||
#. Translators: Translate this string the same way as you do in libwnck!
|
#. Translators: Translate this string the same way as you do in libwnck!
|
||||||
#: ../src/ui/menu.c:102
|
#: ../src/ui/menu.c:104
|
||||||
msgid "_Close"
|
msgid "_Close"
|
||||||
msgstr "_Zavrieť"
|
msgstr "_Zavrieť"
|
||||||
|
|
||||||
#: ../src/ui/menu.c:202
|
#: ../src/ui/menu.c:204
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Workspace %d%n"
|
msgid "Workspace %d%n"
|
||||||
msgstr "Pracovná priestor %d%n"
|
msgstr "Pracovná priestor %d%n"
|
||||||
|
|
||||||
#: ../src/ui/menu.c:212
|
#: ../src/ui/menu.c:214
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Workspace 1_0"
|
msgid "Workspace 1_0"
|
||||||
msgstr "Pracovný priestor 1_0"
|
msgstr "Pracovný priestor 1_0"
|
||||||
|
|
||||||
#: ../src/ui/menu.c:214
|
#: ../src/ui/menu.c:216
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Workspace %s%d"
|
msgid "Workspace %s%d"
|
||||||
msgstr "Pracovný priestor %s%d"
|
msgstr "Pracovný priestor %s%d"
|
||||||
|
|
||||||
#: ../src/ui/menu.c:384
|
#: ../src/ui/menu.c:397
|
||||||
msgid "Move to Another _Workspace"
|
msgid "Move to Another _Workspace"
|
||||||
msgstr "P_resunúť na iný pracovný priestor"
|
msgstr "P_resunúť na iný pracovný priestor"
|
||||||
|
|
||||||
@@ -1071,21 +1066,21 @@ msgstr ""
|
|||||||
# MČ: Preformuloval by som koniec: „platné sú len znaky A-Za-z0-9-_“
|
# MČ: Preformuloval by som koniec: „platné sú len znaky A-Za-z0-9-_“
|
||||||
# PK: color_name je asi nejaky atribut, to sa nepreklada, ked tak do zatvorky
|
# PK: color_name je asi nejaky atribut, to sa nepreklada, ked tak do zatvorky
|
||||||
#: ../src/ui/theme.c:1219
|
#: ../src/ui/theme.c:1219
|
||||||
#, c-format
|
#, fuzzy, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-"
|
"Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-"
|
||||||
"_ are valid"
|
"_ are valid"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"V parametri color_name (názov farby) pre gtk:custom je neplatný znak „%c“, platné sú len "
|
"V parametri názov_farby pre gtk:custom je neplatný znak „%c“, platné sú len "
|
||||||
"znaky A-Za-z0-9-_"
|
"znaky A-Za-z0-9-_"
|
||||||
|
|
||||||
#: ../src/ui/theme.c:1233
|
#: ../src/ui/theme.c:1233
|
||||||
#, c-format
|
#, fuzzy, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not "
|
"Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not "
|
||||||
"fit the format"
|
"fit the format"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Formát Gtk:custom je „gtk:custom(color_name,fallback)“, „%s“ tomu "
|
"Formát Gtk:custom je „gtk:custom(názov_farby,fallback)“, „%s“ tomu "
|
||||||
"nezodpovedá"
|
"nezodpovedá"
|
||||||
|
|
||||||
#: ../src/ui/theme.c:1278
|
#: ../src/ui/theme.c:1278
|
||||||
@@ -1271,20 +1266,20 @@ msgid ""
|
|||||||
"Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>"
|
"Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>"
|
||||||
msgstr "Chýbajúce <frame state=„%s“ resize=„%s“ focus=„%s“ style=„whatever“/>"
|
msgstr "Chýbajúce <frame state=„%s“ resize=„%s“ focus=„%s“ style=„whatever“/>"
|
||||||
|
|
||||||
#: ../src/ui/theme.c:5082
|
#: ../src/ui/theme.c:5084
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Failed to load theme \"%s\": %s\n"
|
msgid "Failed to load theme \"%s\": %s\n"
|
||||||
msgstr "Zlyhalo načítanie témy „%s“: %s\n"
|
msgstr "Zlyhalo načítanie témy „%s“: %s\n"
|
||||||
|
|
||||||
# PK: prvok?
|
# PK: prvok?
|
||||||
# JK: XML značka (XML tag)
|
# JK: XML značka (XML tag)
|
||||||
#: ../src/ui/theme.c:5218 ../src/ui/theme.c:5225 ../src/ui/theme.c:5232
|
#: ../src/ui/theme.c:5220 ../src/ui/theme.c:5227 ../src/ui/theme.c:5234
|
||||||
#: ../src/ui/theme.c:5239 ../src/ui/theme.c:5246
|
#: ../src/ui/theme.c:5241 ../src/ui/theme.c:5248
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "No <%s> set for theme \"%s\""
|
msgid "No <%s> set for theme \"%s\""
|
||||||
msgstr "Pre tému „%s“ nie je nastavená <%s>"
|
msgstr "Pre tému „%s“ nie je nastavená <%s>"
|
||||||
|
|
||||||
#: ../src/ui/theme.c:5254
|
#: ../src/ui/theme.c:5256
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"No frame style set for window type \"%s\" in theme \"%s\", add a <window "
|
"No frame style set for window type \"%s\" in theme \"%s\", add a <window "
|
||||||
@@ -1293,13 +1288,13 @@ msgstr ""
|
|||||||
"Pre typ okna „%s“ nie je sada štýlov v téme „%s“, pridajte prvok <window "
|
"Pre typ okna „%s“ nie je sada štýlov v téme „%s“, pridajte prvok <window "
|
||||||
"type=„%s“ style_set=„whatever“/>"
|
"type=„%s“ style_set=„whatever“/>"
|
||||||
|
|
||||||
#: ../src/ui/theme.c:5661 ../src/ui/theme.c:5723 ../src/ui/theme.c:5786
|
#: ../src/ui/theme.c:5663 ../src/ui/theme.c:5725 ../src/ui/theme.c:5788
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"User-defined constants must begin with a capital letter; \"%s\" does not"
|
"User-defined constants must begin with a capital letter; \"%s\" does not"
|
||||||
msgstr "Používateľské konštanty musia začínať veľkým písmenom, „%s“ nezačína"
|
msgstr "Používateľské konštanty musia začínať veľkým písmenom, „%s“ nezačína"
|
||||||
|
|
||||||
#: ../src/ui/theme.c:5669 ../src/ui/theme.c:5731 ../src/ui/theme.c:5794
|
#: ../src/ui/theme.c:5671 ../src/ui/theme.c:5733 ../src/ui/theme.c:5796
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Constant \"%s\" has already been defined"
|
msgid "Constant \"%s\" has already been defined"
|
||||||
msgstr "Konštanta „%s“ už je definovaná"
|
msgstr "Konštanta „%s“ už je definovaná"
|
||||||
@@ -1402,7 +1397,7 @@ msgstr "<%s> musí uvádzať buď geometriu alebo rodiča, ktorý má geometriu"
|
|||||||
msgid "You must specify a background for an alpha value to be meaningful"
|
msgid "You must specify a background for an alpha value to be meaningful"
|
||||||
msgstr "Ak má byť hodnota alpha zmysluplná, tak musíte vybrať nejaké pozadie"
|
msgstr "Ak má byť hodnota alpha zmysluplná, tak musíte vybrať nejaké pozadie"
|
||||||
|
|
||||||
# PM: asi atribút type
|
# PM: asi atribút type
|
||||||
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=698123
|
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=698123
|
||||||
#: ../src/ui/theme-parser.c:1264
|
#: ../src/ui/theme-parser.c:1264
|
||||||
#, fuzzy, c-format
|
#, fuzzy, c-format
|
||||||
@@ -1564,7 +1559,6 @@ msgid "\"%s\" is not a valid value for resize attribute"
|
|||||||
msgstr "„%s“ nie je platná hodnota pre atribút zmeny veľkosti"
|
msgstr "„%s“ nie je platná hodnota pre atribút zmeny veľkosti"
|
||||||
|
|
||||||
# PK: shaded states? to zatvorky daj popis co je resize
|
# PK: shaded states? to zatvorky daj popis co je resize
|
||||||
# PM: skôr "pre stavy maximized (maximalizovaný)/shaded (zatienený)"
|
|
||||||
#: ../src/ui/theme-parser.c:3147
|
#: ../src/ui/theme-parser.c:3147
|
||||||
#, fuzzy, c-format
|
#, fuzzy, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
@@ -1706,172 +1700,221 @@ msgstr "<%s> uvedený dvakrát pre túto tému"
|
|||||||
msgid "Failed to find a valid file for theme %s\n"
|
msgid "Failed to find a valid file for theme %s\n"
|
||||||
msgstr "Zlyhalo nájdenie platného súboru pre tému%s\n"
|
msgstr "Zlyhalo nájdenie platného súboru pre tému%s\n"
|
||||||
|
|
||||||
#~ msgid "Usage: %s\n"
|
#: ../src/ui/theme-viewer.c:99
|
||||||
#~ msgstr "Použitie: %s\n"
|
msgid "_Windows"
|
||||||
|
msgstr "_Okná"
|
||||||
|
|
||||||
#~ msgid "_Windows"
|
#: ../src/ui/theme-viewer.c:100
|
||||||
#~ msgstr "_Okná"
|
msgid "_Dialog"
|
||||||
|
msgstr "_Dialógové okno"
|
||||||
|
|
||||||
#~ msgid "_Dialog"
|
#: ../src/ui/theme-viewer.c:101
|
||||||
#~ msgstr "_Dialógové okno"
|
msgid "_Modal dialog"
|
||||||
|
msgstr "_Modálne dialógové okno"
|
||||||
|
|
||||||
#~ msgid "_Modal dialog"
|
#: ../src/ui/theme-viewer.c:102
|
||||||
#~ msgstr "_Modálne dialógové okno"
|
msgid "_Utility"
|
||||||
|
msgstr "_Nástroje"
|
||||||
|
|
||||||
#~ msgid "_Utility"
|
#: ../src/ui/theme-viewer.c:103
|
||||||
#~ msgstr "_Nástroje"
|
msgid "_Splashscreen"
|
||||||
|
msgstr "Ú_vodná obrazovka"
|
||||||
#~ msgid "_Splashscreen"
|
|
||||||
#~ msgstr "Ú_vodná obrazovka"
|
|
||||||
|
|
||||||
# MČ: nie som si istý prekladom „dok“, nemal by to byť „panel“?
|
# MČ: nie som si istý prekladom „dok“, nemal by to byť „panel“?
|
||||||
#~ msgid "_Top dock"
|
#: ../src/ui/theme-viewer.c:104
|
||||||
#~ msgstr "_Horný panel"
|
msgid "_Top dock"
|
||||||
|
msgstr "_Horný panel"
|
||||||
|
|
||||||
#~ msgid "_Bottom dock"
|
#: ../src/ui/theme-viewer.c:105
|
||||||
#~ msgstr "_Spodný panel"
|
msgid "_Bottom dock"
|
||||||
|
msgstr "_Spodný panel"
|
||||||
|
|
||||||
#~ msgid "_Left dock"
|
#: ../src/ui/theme-viewer.c:106
|
||||||
#~ msgstr "Ľ_avý panel"
|
msgid "_Left dock"
|
||||||
|
msgstr "Ľ_avý panel"
|
||||||
|
|
||||||
#~ msgid "_Right dock"
|
#: ../src/ui/theme-viewer.c:107
|
||||||
#~ msgstr "_Pravý panel"
|
msgid "_Right dock"
|
||||||
|
msgstr "_Pravý panel"
|
||||||
|
|
||||||
#~ msgid "_All docks"
|
#: ../src/ui/theme-viewer.c:108
|
||||||
#~ msgstr "_Všetky panely"
|
msgid "_All docks"
|
||||||
|
msgstr "_Všetky panely"
|
||||||
|
|
||||||
#~ msgid "Des_ktop"
|
#: ../src/ui/theme-viewer.c:109
|
||||||
#~ msgstr "P_racovná plocha"
|
msgid "Des_ktop"
|
||||||
|
msgstr "P_racovná plocha"
|
||||||
|
|
||||||
# tooltip
|
# tooltip
|
||||||
#~ msgid "Open another one of these windows"
|
#: ../src/ui/theme-viewer.c:115
|
||||||
#~ msgstr "Otvorí ďalšie z týchto okien"
|
msgid "Open another one of these windows"
|
||||||
|
msgstr "Otvorí ďalšie z týchto okien"
|
||||||
|
|
||||||
# PK: prekladat to v uvodzovkach? nahlas bug
|
# PK: prekladat to v uvodzovkach? nahlas bug
|
||||||
# tooltip
|
# tooltip
|
||||||
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=698123
|
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=698123
|
||||||
|
#: ../src/ui/theme-viewer.c:117
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#~ msgid "This is a demo button with an 'open' icon"
|
msgid "This is a demo button with an 'open' icon"
|
||||||
#~ msgstr "Toto je ukážkové tlačidlo s ikonou „open“"
|
msgstr "Toto je ukážkové tlačidlo s ikonou „open“"
|
||||||
|
|
||||||
# tooltip
|
# tooltip
|
||||||
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=698123
|
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=698123
|
||||||
|
#: ../src/ui/theme-viewer.c:119
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#~ msgid "This is a demo button with a 'quit' icon"
|
msgid "This is a demo button with a 'quit' icon"
|
||||||
#~ msgstr "Toto je ukážkové tlačidlo s ikonou „quit“"
|
msgstr "Toto je ukážkové tlačidlo s ikonou „quit“"
|
||||||
|
|
||||||
# label
|
# label
|
||||||
#~ msgid "This is a sample message in a sample dialog"
|
#: ../src/ui/theme-viewer.c:248
|
||||||
#~ msgstr "Toto je ukážková správa v ukážkovom dialógovom okne"
|
msgid "This is a sample message in a sample dialog"
|
||||||
|
msgstr "Toto je ukážková správa v ukážkovom dialógovom okne"
|
||||||
|
|
||||||
# PK: falosna
|
# PK: falosna
|
||||||
#~ msgid "Fake menu item %d\n"
|
#: ../src/ui/theme-viewer.c:328
|
||||||
#~ msgstr "Falošná položka ponuky č. %d\n"
|
#, c-format
|
||||||
|
msgid "Fake menu item %d\n"
|
||||||
|
msgstr "Falošná položka ponuky č. %d\n"
|
||||||
|
|
||||||
#~ msgid "Border-only window"
|
#: ../src/ui/theme-viewer.c:363
|
||||||
#~ msgstr "Okno len s okrajom"
|
msgid "Border-only window"
|
||||||
|
msgstr "Okno len s okrajom"
|
||||||
|
|
||||||
#~ msgid "Bar"
|
#: ../src/ui/theme-viewer.c:365
|
||||||
#~ msgstr "Lišta"
|
msgid "Bar"
|
||||||
|
msgstr "Lišta"
|
||||||
|
|
||||||
#~ msgid "Normal Application Window"
|
#: ../src/ui/theme-viewer.c:382
|
||||||
#~ msgstr "Normálne aplikačné okno"
|
msgid "Normal Application Window"
|
||||||
|
msgstr "Normálne aplikačné okno"
|
||||||
|
|
||||||
#~ msgid "Dialog Box"
|
#: ../src/ui/theme-viewer.c:386
|
||||||
#~ msgstr "Dialógové okno"
|
msgid "Dialog Box"
|
||||||
|
msgstr "Dialógové okno"
|
||||||
|
|
||||||
#~ msgid "Modal Dialog Box"
|
#: ../src/ui/theme-viewer.c:390
|
||||||
#~ msgstr "Modálne dialógové okno"
|
msgid "Modal Dialog Box"
|
||||||
|
msgstr "Modálne dialógové okno"
|
||||||
|
|
||||||
#~ msgid "Utility Palette"
|
#: ../src/ui/theme-viewer.c:394
|
||||||
#~ msgstr "Paleta nástrojov"
|
msgid "Utility Palette"
|
||||||
|
msgstr "Paleta nástrojov"
|
||||||
|
|
||||||
#~ msgid "Torn-off Menu"
|
#: ../src/ui/theme-viewer.c:398
|
||||||
#~ msgstr "Vypnúť ponuku"
|
msgid "Torn-off Menu"
|
||||||
|
msgstr "Vypnúť ponuku"
|
||||||
|
|
||||||
#~ msgid "Border"
|
#: ../src/ui/theme-viewer.c:402
|
||||||
#~ msgstr "Okraj"
|
msgid "Border"
|
||||||
|
msgstr "Okraj"
|
||||||
|
|
||||||
#~ msgid "Attached Modal Dialog"
|
#: ../src/ui/theme-viewer.c:406
|
||||||
#~ msgstr "Pričlenené modálne okno"
|
msgid "Attached Modal Dialog"
|
||||||
|
msgstr "Pričlenené modálne okno"
|
||||||
|
|
||||||
#~ msgid "Button layout test %d"
|
#: ../src/ui/theme-viewer.c:737
|
||||||
#~ msgstr "Test rozloženia tlačidiel č. %d"
|
#, c-format
|
||||||
|
msgid "Button layout test %d"
|
||||||
|
msgstr "Test rozloženia tlačidiel č. %d"
|
||||||
|
|
||||||
# PK: plural forms
|
# PK: plural forms
|
||||||
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=697987
|
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=697987
|
||||||
#, fuzzy
|
#: ../src/ui/theme-viewer.c:766
|
||||||
#~ msgid "%g milliseconds to draw one window frame"
|
#, fuzzy, c-format
|
||||||
#~ msgstr "%g milisekúnd pre vykreslenie jedného rámca okna"
|
msgid "%g milliseconds to draw one window frame"
|
||||||
|
msgstr "%g milisekúnd pre vykreslenie jedného rámca okna"
|
||||||
|
|
||||||
#~ msgid "Usage: metacity-theme-viewer [THEMENAME]\n"
|
#: ../src/ui/theme-viewer.c:811
|
||||||
#~ msgstr "Použitie: metacity-theme-viewer [NÁZOVTÉMY]\n"
|
#, c-format
|
||||||
|
msgid "Usage: metacity-theme-viewer [THEMENAME]\n"
|
||||||
|
msgstr "Použitie: metacity-theme-viewer [NÁZOVTÉMY]\n"
|
||||||
|
|
||||||
#~ msgid "Error loading theme: %s\n"
|
#: ../src/ui/theme-viewer.c:818
|
||||||
#~ msgstr "Chyba pri načítavaní témy: %s\n"
|
#, c-format
|
||||||
|
msgid "Error loading theme: %s\n"
|
||||||
|
msgstr "Chyba pri načítavaní témy: %s\n"
|
||||||
|
|
||||||
# PK: plural forms
|
# PK: plural forms
|
||||||
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=697987
|
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=697987
|
||||||
#, fuzzy
|
#: ../src/ui/theme-viewer.c:824
|
||||||
#~ msgid "Loaded theme \"%s\" in %g seconds\n"
|
#, fuzzy, c-format
|
||||||
#~ msgstr "Téma „%s“ načítaná za %g sekúnd\n"
|
msgid "Loaded theme \"%s\" in %g seconds\n"
|
||||||
|
msgstr "Téma „%s“ načítaná za %g sekúnd\n"
|
||||||
|
|
||||||
# PK: inde titulku, aky je rozdiel
|
# PK: inde titulku, aky je rozdiel
|
||||||
#~ msgid "Normal Title Font"
|
#: ../src/ui/theme-viewer.c:869
|
||||||
#~ msgstr "Obyčajné písmo titulku"
|
msgid "Normal Title Font"
|
||||||
|
msgstr "Obyčajné písmo titulku"
|
||||||
|
|
||||||
#~ msgid "Small Title Font"
|
#: ../src/ui/theme-viewer.c:875
|
||||||
#~ msgstr "Malé písmo titulku"
|
msgid "Small Title Font"
|
||||||
|
msgstr "Malé písmo titulku"
|
||||||
|
|
||||||
#~ msgid "Large Title Font"
|
#: ../src/ui/theme-viewer.c:881
|
||||||
#~ msgstr "Veľké písmo titulku"
|
msgid "Large Title Font"
|
||||||
|
msgstr "Veľké písmo titulku"
|
||||||
|
|
||||||
#~ msgid "Button Layouts"
|
#: ../src/ui/theme-viewer.c:886
|
||||||
#~ msgstr "Rozloženia tlačidiel"
|
msgid "Button Layouts"
|
||||||
|
msgstr "Rozloženia tlačidiel"
|
||||||
|
|
||||||
#~ msgid "Benchmark"
|
#: ../src/ui/theme-viewer.c:891
|
||||||
#~ msgstr "Test rýchlosti"
|
msgid "Benchmark"
|
||||||
|
msgstr "Test rýchlosti"
|
||||||
|
|
||||||
#~ msgid "Window Title Goes Here"
|
#: ../src/ui/theme-viewer.c:947
|
||||||
#~ msgstr "Sem príde názov okna"
|
msgid "Window Title Goes Here"
|
||||||
|
msgstr "Sem príde názov okna"
|
||||||
|
|
||||||
# PK: plural forms
|
# PK: plural forms
|
||||||
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=697987
|
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=697987
|
||||||
#, fuzzy
|
#: ../src/ui/theme-viewer.c:1053
|
||||||
#~ msgid ""
|
#, fuzzy, c-format
|
||||||
#~ "Drew %d frames in %g client-side seconds (%g milliseconds per frame) and "
|
msgid ""
|
||||||
#~ "%g seconds wall clock time including X server resources (%g milliseconds "
|
"Drew %d frames in %g client-side seconds (%g milliseconds per frame) and %g "
|
||||||
#~ "per frame)\n"
|
"seconds wall clock time including X server resources (%g milliseconds per "
|
||||||
#~ msgstr ""
|
"frame)\n"
|
||||||
#~ "Vykreslených %d rámcov za %g sekúnd na strane klienta (%g milisekúnd na "
|
msgstr ""
|
||||||
#~ "rámec) a %g sekúnd celkového času vrátane zdrojov servera X (%g "
|
"Vykreslených %d rámcov za %g sekúnd na strane klienta (%g milisekúnd na "
|
||||||
#~ "milisekúnd na rámec)\n"
|
"rámec) a %g sekúnd celkového času vrátane zdrojov servera X (%g milisekúnd "
|
||||||
|
"na rámec)\n"
|
||||||
|
|
||||||
#~ msgid "position expression test returned TRUE but set error"
|
#: ../src/ui/theme-viewer.c:1273
|
||||||
#~ msgstr "test výrazu polohy vrátil TRUE, ale nastavil chybu"
|
msgid "position expression test returned TRUE but set error"
|
||||||
|
msgstr "test výrazu polohy vrátil TRUE, ale nastavil chybu"
|
||||||
|
|
||||||
#~ msgid "position expression test returned FALSE but didn't set error"
|
#: ../src/ui/theme-viewer.c:1275
|
||||||
#~ msgstr "test výrazu polohy vrátil FALSE, ale nenastavil chybu"
|
msgid "position expression test returned FALSE but didn't set error"
|
||||||
|
msgstr "test výrazu polohy vrátil FALSE, ale nenastavil chybu"
|
||||||
|
|
||||||
#~ msgid "Error was expected but none given"
|
#: ../src/ui/theme-viewer.c:1279
|
||||||
#~ msgstr "Bola očakávaná chyba, ale žiadna nenastala"
|
msgid "Error was expected but none given"
|
||||||
|
msgstr "Bola očakávaná chyba, ale žiadna nenastala"
|
||||||
|
|
||||||
#~ msgid "Error %d was expected but %d given"
|
#: ../src/ui/theme-viewer.c:1281
|
||||||
#~ msgstr "Bola očakávaná chyba %d, ale nastala %d"
|
#, c-format
|
||||||
|
msgid "Error %d was expected but %d given"
|
||||||
|
msgstr "Bola očakávaná chyba %d, ale nastala %d"
|
||||||
|
|
||||||
#~ msgid "Error not expected but one was returned: %s"
|
#: ../src/ui/theme-viewer.c:1287
|
||||||
#~ msgstr "Chyba nebola očakávaná, ale bola vrátená: %s"
|
#, c-format
|
||||||
|
msgid "Error not expected but one was returned: %s"
|
||||||
|
msgstr "Chyba nebola očakávaná, ale bola vrátená: %s"
|
||||||
|
|
||||||
#~ msgid "x value was %d, %d was expected"
|
#: ../src/ui/theme-viewer.c:1291
|
||||||
#~ msgstr "hodnota x bola %d, očakávaná bola %d"
|
#, c-format
|
||||||
|
msgid "x value was %d, %d was expected"
|
||||||
|
msgstr "hodnota x bola %d, očakávaná bola %d"
|
||||||
|
|
||||||
#~ msgid "y value was %d, %d was expected"
|
#: ../src/ui/theme-viewer.c:1294
|
||||||
#~ msgstr "hodnota y bola %d, očakávaná bola %d"
|
#, c-format
|
||||||
|
msgid "y value was %d, %d was expected"
|
||||||
|
msgstr "hodnota y bola %d, očakávaná bola %d"
|
||||||
|
|
||||||
# PK: plural forms
|
# PK: plural forms
|
||||||
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=697987
|
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=697987
|
||||||
#, fuzzy
|
#: ../src/ui/theme-viewer.c:1359
|
||||||
#~ msgid ""
|
#, fuzzy, c-format
|
||||||
#~ "%d coordinate expressions parsed in %g seconds (%g seconds average)\n"
|
msgid "%d coordinate expressions parsed in %g seconds (%g seconds average)\n"
|
||||||
#~ msgstr ""
|
msgstr ""
|
||||||
#~ "%d výrazov pre súradnice analyzovaných za %g sekúnd (priemer %g sekúnd)\n"
|
"%d výrazov pre súradnice analyzovaných za %g sekúnd (priemer %g sekúnd)\n"
|
||||||
|
758
po/sr@latin.po
758
po/sr@latin.po
File diff suppressed because it is too large
Load Diff
1228
po/zh_CN.po
1228
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
524
po/zh_HK.po
524
po/zh_HK.po
File diff suppressed because it is too large
Load Diff
524
po/zh_TW.po
524
po/zh_TW.po
File diff suppressed because it is too large
Load Diff
@@ -17,9 +17,6 @@
|
|||||||
<KeyListEntry name="move-to-workspace-4"
|
<KeyListEntry name="move-to-workspace-4"
|
||||||
_description="Move window 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"
|
<KeyListEntry name="move-to-workspace-left"
|
||||||
_description="Move window one workspace to the left" />
|
_description="Move window one workspace to the left" />
|
||||||
|
|
||||||
@@ -80,9 +77,6 @@
|
|||||||
<KeyListEntry name="switch-to-workspace-4"
|
<KeyListEntry name="switch-to-workspace-4"
|
||||||
_description="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"
|
<KeyListEntry name="switch-to-workspace-left"
|
||||||
_description="Move to workspace left" />
|
_description="Move to workspace left" />
|
||||||
|
|
||||||
|
105
src/Makefile.am
105
src/Makefile.am
@@ -1,7 +1,7 @@
|
|||||||
# Flag build for parallelism; see https://savannah.gnu.org/patch/?6905
|
# Flag build for parallelism; see https://savannah.gnu.org/patch/?6905
|
||||||
.AUTOPARALLEL:
|
.AUTOPARALLEL:
|
||||||
|
|
||||||
lib_LTLIBRARIES = libmutter.la
|
lib_LTLIBRARIES = libmutter-wayland.la
|
||||||
|
|
||||||
SUBDIRS=compositor/plugins
|
SUBDIRS=compositor/plugins
|
||||||
|
|
||||||
@@ -11,6 +11,7 @@ INCLUDES= \
|
|||||||
-DCOGL_ENABLE_EXPERIMENTAL_API \
|
-DCOGL_ENABLE_EXPERIMENTAL_API \
|
||||||
-DCOGL_ENABLE_EXPERIMENTAL_2_0_API \
|
-DCOGL_ENABLE_EXPERIMENTAL_2_0_API \
|
||||||
$(MUTTER_CFLAGS) \
|
$(MUTTER_CFLAGS) \
|
||||||
|
-I$(top_builddir) \
|
||||||
-I$(srcdir) \
|
-I$(srcdir) \
|
||||||
-I$(srcdir)/backends \
|
-I$(srcdir)/backends \
|
||||||
-I$(srcdir)/core \
|
-I$(srcdir)/core \
|
||||||
@@ -35,29 +36,28 @@ INCLUDES= \
|
|||||||
mutter_built_sources = \
|
mutter_built_sources = \
|
||||||
$(dbus_idle_built_sources) \
|
$(dbus_idle_built_sources) \
|
||||||
$(dbus_display_config_built_sources) \
|
$(dbus_display_config_built_sources) \
|
||||||
$(dbus_login1_built_sources) \
|
|
||||||
mutter-enum-types.h \
|
mutter-enum-types.h \
|
||||||
mutter-enum-types.c \
|
mutter-enum-types.c \
|
||||||
gtk-shell-protocol.c \
|
gtk-shell-protocol.c \
|
||||||
gtk-shell-server-protocol.h \
|
gtk-shell-server-protocol.h \
|
||||||
xdg-shell-protocol.c \
|
xdg-shell-protocol.c \
|
||||||
xdg-shell-server-protocol.h
|
xdg-shell-server-protocol.h \
|
||||||
|
xserver-protocol.c \
|
||||||
|
xserver-server-protocol.h
|
||||||
|
|
||||||
wayland_protocols = \
|
wayland_protocols = \
|
||||||
wayland/protocol/gtk-shell.xml \
|
wayland/protocol/gtk-shell.xml \
|
||||||
wayland/protocol/xdg-shell.xml
|
wayland/protocol/xdg-shell.xml \
|
||||||
|
wayland/protocol/xserver.xml
|
||||||
|
|
||||||
libmutter_la_SOURCES = \
|
libmutter_wayland_la_SOURCES = \
|
||||||
backends/meta-backend.c \
|
backends/meta-backend.c \
|
||||||
backends/meta-backend.h \
|
backends/meta-backend.h \
|
||||||
backends/meta-backend-private.h \
|
|
||||||
backends/meta-cursor.c \
|
backends/meta-cursor.c \
|
||||||
backends/meta-cursor.h \
|
backends/meta-cursor.h \
|
||||||
backends/meta-cursor-private.h \
|
backends/meta-cursor-private.h \
|
||||||
backends/meta-cursor-tracker.c \
|
backends/meta-cursor-tracker.c \
|
||||||
backends/meta-cursor-tracker-private.h \
|
backends/meta-cursor-tracker-private.h \
|
||||||
backends/meta-cursor-renderer.c \
|
|
||||||
backends/meta-cursor-renderer.h \
|
|
||||||
backends/meta-display-config-shared.h \
|
backends/meta-display-config-shared.h \
|
||||||
backends/meta-idle-monitor.c \
|
backends/meta-idle-monitor.c \
|
||||||
backends/meta-idle-monitor-private.h \
|
backends/meta-idle-monitor-private.h \
|
||||||
@@ -71,28 +71,17 @@ libmutter_la_SOURCES = \
|
|||||||
backends/meta-monitor-manager-dummy.h \
|
backends/meta-monitor-manager-dummy.h \
|
||||||
backends/edid-parse.c \
|
backends/edid-parse.c \
|
||||||
backends/edid.h \
|
backends/edid.h \
|
||||||
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.c \
|
||||||
backends/native/meta-idle-monitor-native.h \
|
backends/native/meta-idle-monitor-native.h \
|
||||||
backends/native/meta-monitor-manager-kms.c \
|
backends/native/meta-monitor-manager-kms.c \
|
||||||
backends/native/meta-monitor-manager-kms.h \
|
backends/native/meta-monitor-manager-kms.h \
|
||||||
backends/native/meta-launcher.c \
|
backends/native/meta-weston-launch.c \
|
||||||
backends/native/meta-launcher.h \
|
backends/native/meta-weston-launch.h \
|
||||||
backends/native/dbus-utils.c \
|
|
||||||
backends/native/dbus-utils.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/x11/meta-idle-monitor-xsync.c \
|
backends/x11/meta-idle-monitor-xsync.c \
|
||||||
backends/x11/meta-idle-monitor-xsync.h \
|
backends/x11/meta-idle-monitor-xsync.h \
|
||||||
backends/x11/meta-monitor-manager-xrandr.c \
|
backends/x11/meta-monitor-manager-xrandr.c \
|
||||||
backends/x11/meta-monitor-manager-xrandr.h \
|
backends/x11/meta-monitor-manager-xrandr.h \
|
||||||
core/meta-accel-parse.c \
|
core/above-tab-keycode.c \
|
||||||
core/meta-accel-parse.h \
|
|
||||||
core/barrier.c \
|
core/barrier.c \
|
||||||
meta/barrier.h \
|
meta/barrier.h \
|
||||||
core/bell.c \
|
core/bell.c \
|
||||||
@@ -127,8 +116,6 @@ libmutter_la_SOURCES = \
|
|||||||
compositor/meta-surface-actor-x11.h \
|
compositor/meta-surface-actor-x11.h \
|
||||||
compositor/meta-surface-actor-wayland.c \
|
compositor/meta-surface-actor-wayland.c \
|
||||||
compositor/meta-surface-actor-wayland.h \
|
compositor/meta-surface-actor-wayland.h \
|
||||||
compositor/meta-stage.h \
|
|
||||||
compositor/meta-stage.c \
|
|
||||||
compositor/meta-texture-rectangle.c \
|
compositor/meta-texture-rectangle.c \
|
||||||
compositor/meta-texture-rectangle.h \
|
compositor/meta-texture-rectangle.h \
|
||||||
compositor/meta-texture-tower.c \
|
compositor/meta-texture-tower.c \
|
||||||
@@ -194,6 +181,10 @@ libmutter_la_SOURCES = \
|
|||||||
ui/ui.h \
|
ui/ui.h \
|
||||||
ui/frames.c \
|
ui/frames.c \
|
||||||
ui/frames.h \
|
ui/frames.h \
|
||||||
|
ui/menu.c \
|
||||||
|
ui/menu.h \
|
||||||
|
ui/metaaccellabel.c \
|
||||||
|
ui/metaaccellabel.h \
|
||||||
ui/resizepopup.c \
|
ui/resizepopup.c \
|
||||||
ui/resizepopup.h \
|
ui/resizepopup.h \
|
||||||
ui/theme-parser.c \
|
ui/theme-parser.c \
|
||||||
@@ -223,9 +214,8 @@ libmutter_la_SOURCES = \
|
|||||||
wayland/meta-wayland.c \
|
wayland/meta-wayland.c \
|
||||||
wayland/meta-wayland.h \
|
wayland/meta-wayland.h \
|
||||||
wayland/meta-wayland-private.h \
|
wayland/meta-wayland-private.h \
|
||||||
wayland/meta-xwayland.c \
|
|
||||||
wayland/meta-xwayland.h \
|
|
||||||
wayland/meta-xwayland-private.h \
|
wayland/meta-xwayland-private.h \
|
||||||
|
wayland/meta-xwayland.c \
|
||||||
wayland/meta-wayland-data-device.c \
|
wayland/meta-wayland-data-device.c \
|
||||||
wayland/meta-wayland-data-device.h \
|
wayland/meta-wayland-data-device.h \
|
||||||
wayland/meta-wayland-keyboard.c \
|
wayland/meta-wayland-keyboard.c \
|
||||||
@@ -234,20 +224,20 @@ libmutter_la_SOURCES = \
|
|||||||
wayland/meta-wayland-pointer.h \
|
wayland/meta-wayland-pointer.h \
|
||||||
wayland/meta-wayland-seat.c \
|
wayland/meta-wayland-seat.c \
|
||||||
wayland/meta-wayland-seat.h \
|
wayland/meta-wayland-seat.h \
|
||||||
|
wayland/meta-wayland-stage.h \
|
||||||
|
wayland/meta-wayland-stage.c \
|
||||||
wayland/meta-wayland-surface.c \
|
wayland/meta-wayland-surface.c \
|
||||||
wayland/meta-wayland-surface.h \
|
wayland/meta-wayland-surface.h \
|
||||||
wayland/meta-wayland-types.h \
|
wayland/meta-wayland-types.h \
|
||||||
wayland/meta-wayland-versions.h \
|
wayland/meta-wayland-versions.h \
|
||||||
wayland/meta-wayland-outputs.c \
|
|
||||||
wayland/meta-wayland-outputs.h \
|
|
||||||
wayland/window-wayland.c \
|
wayland/window-wayland.c \
|
||||||
wayland/window-wayland.h
|
wayland/window-wayland.h
|
||||||
|
|
||||||
nodist_libmutter_la_SOURCES = \
|
nodist_libmutter_wayland_la_SOURCES = \
|
||||||
$(mutter_built_sources)
|
$(mutter_built_sources)
|
||||||
|
|
||||||
libmutter_la_LDFLAGS = -no-undefined
|
libmutter_wayland_la_LDFLAGS = -no-undefined
|
||||||
libmutter_la_LIBADD = $(MUTTER_LIBS)
|
libmutter_wayland_la_LIBADD = $(MUTTER_LIBS)
|
||||||
|
|
||||||
# Headers installed for plugins; introspected information will
|
# Headers installed for plugins; introspected information will
|
||||||
# be extracted into Mutter-<version>.gir
|
# be extracted into Mutter-<version>.gir
|
||||||
@@ -285,16 +275,29 @@ libmutterinclude_base_headers = \
|
|||||||
libmutterinclude_extra_headers = \
|
libmutterinclude_extra_headers = \
|
||||||
meta/atomnames.h
|
meta/atomnames.h
|
||||||
|
|
||||||
libmutterincludedir = $(includedir)/mutter/meta
|
libmutterincludedir = $(includedir)/mutter-wayland/meta
|
||||||
|
|
||||||
libmutterinclude_HEADERS = \
|
libmutterinclude_HEADERS = \
|
||||||
$(libmutterinclude_base_headers) \
|
$(libmutterinclude_base_headers) \
|
||||||
$(libmutterinclude_extra_headers)
|
$(libmutterinclude_extra_headers)
|
||||||
|
|
||||||
bin_PROGRAMS=mutter
|
bin_PROGRAMS=mutter-wayland
|
||||||
|
|
||||||
mutter_SOURCES = core/mutter.c
|
mutter_wayland_SOURCES = core/mutter.c
|
||||||
mutter_LDADD = $(MUTTER_LIBS) libmutter.la
|
mutter_wayland_LDADD = $(MUTTER_LIBS) libmutter-wayland.la
|
||||||
|
|
||||||
|
bin_PROGRAMS+=mutter-launch
|
||||||
|
|
||||||
|
mutter_launch_SOURCES = \
|
||||||
|
backends/native/weston-launch.c \
|
||||||
|
backends/native/weston-launch.h
|
||||||
|
|
||||||
|
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
|
if HAVE_INTROSPECTION
|
||||||
include $(INTROSPECTION_MAKEFILE)
|
include $(INTROSPECTION_MAKEFILE)
|
||||||
@@ -316,15 +319,15 @@ typelib_DATA = Meta-$(api_version).typelib
|
|||||||
|
|
||||||
INTROSPECTION_GIRS = Meta-$(api_version).gir
|
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@_INCLUDES = GObject-2.0 GDesktopEnums-3.0 Gdk-3.0 Gtk-3.0 Clutter-1.0 xlib-2.0 xfixes-4.0 Cogl-1.0
|
||||||
@META_GIR@_EXPORT_PACKAGES = libmutter
|
@META_GIR@_EXPORT_PACKAGES = libmutter-wayland
|
||||||
@META_GIR@_CFLAGS = $(INCLUDES)
|
@META_GIR@_CFLAGS = $(INCLUDES)
|
||||||
@META_GIR@_LIBS = libmutter.la
|
@META_GIR@_LIBS = libmutter-wayland.la
|
||||||
@META_GIR@_FILES = \
|
@META_GIR@_FILES = \
|
||||||
mutter-enum-types.h \
|
mutter-enum-types.h \
|
||||||
$(libmutterinclude_base_headers) \
|
$(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
|
@META_GIR@_SCANNERFLAGS = --warn-all --warn-error
|
||||||
|
|
||||||
endif
|
endif
|
||||||
@@ -335,14 +338,14 @@ testasyncgetprop_SOURCES = x11/testasyncgetprop.c
|
|||||||
|
|
||||||
noinst_PROGRAMS=testboxes testgradient testasyncgetprop
|
noinst_PROGRAMS=testboxes testgradient testasyncgetprop
|
||||||
|
|
||||||
testboxes_LDADD = $(MUTTER_LIBS) libmutter.la
|
testboxes_LDADD = $(MUTTER_LIBS) libmutter-wayland.la
|
||||||
testgradient_LDADD = $(MUTTER_LIBS) libmutter.la
|
testgradient_LDADD = $(MUTTER_LIBS) libmutter-wayland.la
|
||||||
testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter.la
|
testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter-wayland.la
|
||||||
|
|
||||||
@INTLTOOL_DESKTOP_RULE@
|
@INTLTOOL_DESKTOP_RULE@
|
||||||
|
|
||||||
desktopfilesdir=$(datadir)/applications
|
desktopfilesdir=$(datadir)/applications
|
||||||
desktopfiles_in_files=mutter.desktop.in
|
desktopfiles_in_files=mutter-wayland.desktop.in
|
||||||
desktopfiles_files=$(desktopfiles_in_files:.desktop.in=.desktop)
|
desktopfiles_files=$(desktopfiles_in_files:.desktop.in=.desktop)
|
||||||
desktopfiles_DATA = $(desktopfiles_files)
|
desktopfiles_DATA = $(desktopfiles_files)
|
||||||
|
|
||||||
@@ -363,7 +366,7 @@ convertdir = $(datadir)/GConf/gsettings
|
|||||||
convert_DATA = mutter-schemas.convert
|
convert_DATA = mutter-schemas.convert
|
||||||
|
|
||||||
CLEANFILES = \
|
CLEANFILES = \
|
||||||
mutter.desktop \
|
mutter-wayland.desktop \
|
||||||
mutter-wm.desktop \
|
mutter-wm.desktop \
|
||||||
org.gnome.mutter.gschema.xml \
|
org.gnome.mutter.gschema.xml \
|
||||||
org.gnome.mutter.wayland.gschema.xml \
|
org.gnome.mutter.wayland.gschema.xml \
|
||||||
@@ -374,7 +377,7 @@ CLEANFILES = \
|
|||||||
|
|
||||||
pkgconfigdir = $(libdir)/pkgconfig
|
pkgconfigdir = $(libdir)/pkgconfig
|
||||||
|
|
||||||
pkgconfig_DATA = libmutter.pc
|
pkgconfig_DATA = libmutter-wayland.pc
|
||||||
|
|
||||||
EXTRA_DIST=$(desktopfiles_files) \
|
EXTRA_DIST=$(desktopfiles_files) \
|
||||||
$(wmproperties_files) \
|
$(wmproperties_files) \
|
||||||
@@ -386,10 +389,9 @@ EXTRA_DIST=$(desktopfiles_files) \
|
|||||||
org.gnome.mutter.gschema.xml.in \
|
org.gnome.mutter.gschema.xml.in \
|
||||||
org.gnome.mutter.wayland.gschema.xml.in \
|
org.gnome.mutter.wayland.gschema.xml.in \
|
||||||
mutter-schemas.convert \
|
mutter-schemas.convert \
|
||||||
libmutter.pc.in \
|
libmutter-wayland.pc.in \
|
||||||
mutter-enum-types.h.in \
|
mutter-enum-types.h.in \
|
||||||
mutter-enum-types.c.in \
|
mutter-enum-types.c.in \
|
||||||
org.freedesktop.login1.xml \
|
|
||||||
org.gnome.Mutter.DisplayConfig.xml \
|
org.gnome.Mutter.DisplayConfig.xml \
|
||||||
org.gnome.Mutter.IdleMonitor.xml
|
org.gnome.Mutter.IdleMonitor.xml
|
||||||
|
|
||||||
@@ -433,15 +435,6 @@ $(dbus_idle_built_sources) : Makefile.am org.gnome.Mutter.IdleMonitor.xml
|
|||||||
--c-generate-object-manager \
|
--c-generate-object-manager \
|
||||||
$(srcdir)/org.gnome.Mutter.IdleMonitor.xml
|
$(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
|
%-protocol.c : $(srcdir)/wayland/protocol/%.xml
|
||||||
$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
|
$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
|
||||||
%-server-protocol.h : $(srcdir)/wayland/protocol/%.xml
|
%-server-protocol.h : $(srcdir)/wayland/protocol/%.xml
|
||||||
|
@@ -1,71 +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 "meta-backend.h"
|
|
||||||
|
|
||||||
#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);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* META_BACKEND_PRIVATE_H */
|
|
@@ -25,210 +25,14 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "meta-backend.h"
|
#include "meta-backend.h"
|
||||||
#include "meta-backend-private.h"
|
#include <meta/main.h>
|
||||||
|
|
||||||
|
#include <gdk/gdkx.h>
|
||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
|
#include <clutter/x11/clutter-x11.h>
|
||||||
|
|
||||||
#include "backends/x11/meta-backend-x11.h"
|
#include "backends/native/meta-weston-launch.h"
|
||||||
#include "backends/native/meta-backend-native.h"
|
#include <meta/util.h>
|
||||||
|
|
||||||
static MetaBackend *_backend;
|
|
||||||
|
|
||||||
MetaBackend *
|
|
||||||
meta_get_backend (void)
|
|
||||||
{
|
|
||||||
return _backend;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct _MetaBackendPrivate
|
|
||||||
{
|
|
||||||
MetaMonitorManager *monitor_manager;
|
|
||||||
MetaCursorRenderer *cursor_renderer;
|
|
||||||
};
|
|
||||||
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_real_post_init (MetaBackend *backend)
|
|
||||||
{
|
|
||||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
||||||
|
|
||||||
priv->monitor_manager = META_BACKEND_GET_CLASS (backend)->create_monitor_manager (backend);
|
|
||||||
priv->cursor_renderer = META_BACKEND_GET_CLASS (backend)->create_cursor_renderer (backend);
|
|
||||||
}
|
|
||||||
|
|
||||||
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_warp_pointer (MetaBackend *backend,
|
|
||||||
int x,
|
|
||||||
int y)
|
|
||||||
{
|
|
||||||
/* 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->warp_pointer = meta_backend_real_warp_pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_backend_init (MetaBackend *backend)
|
|
||||||
{
|
|
||||||
_backend = backend;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME -- destroy device monitors at some point */
|
|
||||||
G_GNUC_UNUSED static void
|
|
||||||
destroy_device_monitor (MetaBackend *backend,
|
|
||||||
int device_id)
|
|
||||||
{
|
|
||||||
g_clear_object (&backend->device_monitors[device_id]);
|
|
||||||
if (device_id == backend->device_id_max)
|
|
||||||
backend->device_id_max--;
|
|
||||||
}
|
|
||||||
|
|
||||||
static MetaIdleMonitor *
|
|
||||||
meta_backend_create_idle_monitor (MetaBackend *backend,
|
|
||||||
int device_id)
|
|
||||||
{
|
|
||||||
return META_BACKEND_GET_CLASS (backend)->create_idle_monitor (backend, device_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_backend_post_init (MetaBackend *backend)
|
|
||||||
{
|
|
||||||
META_BACKEND_GET_CLASS (backend)->post_init (backend);
|
|
||||||
}
|
|
||||||
|
|
||||||
MetaIdleMonitor *
|
|
||||||
meta_backend_get_idle_monitor (MetaBackend *backend,
|
|
||||||
int device_id)
|
|
||||||
{
|
|
||||||
g_return_val_if_fail (device_id >= 0 && device_id < 256, NULL);
|
|
||||||
|
|
||||||
if (!backend->device_monitors[device_id])
|
|
||||||
{
|
|
||||||
backend->device_monitors[device_id] = meta_backend_create_idle_monitor (backend, device_id);
|
|
||||||
backend->device_id_max = MAX (backend->device_id_max, device_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return backend->device_monitors[device_id];
|
|
||||||
}
|
|
||||||
|
|
||||||
MetaMonitorManager *
|
|
||||||
meta_backend_get_monitor_manager (MetaBackend *backend)
|
|
||||||
{
|
|
||||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
||||||
|
|
||||||
return priv->monitor_manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
MetaCursorRenderer *
|
|
||||||
meta_backend_get_cursor_renderer (MetaBackend *backend)
|
|
||||||
{
|
|
||||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
||||||
|
|
||||||
return priv->cursor_renderer;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
meta_backend_warp_pointer (MetaBackend *backend,
|
|
||||||
int x,
|
|
||||||
int y)
|
|
||||||
{
|
|
||||||
META_BACKEND_GET_CLASS (backend)->warp_pointer (backend, x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Mutter is responsible for pulling events off the X queue, so Clutter
|
/* 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
|
* doesn't need (and shouldn't) run its normal event source which polls
|
||||||
@@ -278,12 +82,37 @@ static GSourceFuncs event_funcs = {
|
|||||||
event_dispatch
|
event_dispatch
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static MetaLauncher *launcher;
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_clutter_init (void)
|
meta_clutter_init (void)
|
||||||
{
|
{
|
||||||
GSource *source;
|
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)
|
if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
|
||||||
g_error ("Unable to initialize Clutter.\n");
|
g_error ("Unable to initialize Clutter.\n");
|
||||||
@@ -291,6 +120,38 @@ meta_clutter_init (void)
|
|||||||
source = g_source_new (&event_funcs, sizeof (GSource));
|
source = g_source_new (&event_funcs, sizeof (GSource));
|
||||||
g_source_attach (source, NULL);
|
g_source_attach (source, NULL);
|
||||||
g_source_unref (source);
|
g_source_unref (source);
|
||||||
|
}
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@@ -27,33 +27,8 @@
|
|||||||
|
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
|
|
||||||
#include <meta/meta-idle-monitor.h>
|
|
||||||
#include "meta-monitor-manager.h"
|
|
||||||
#include "meta-cursor-renderer.h"
|
|
||||||
|
|
||||||
typedef struct _MetaBackend MetaBackend;
|
|
||||||
typedef struct _MetaBackendClass MetaBackendClass;
|
|
||||||
|
|
||||||
GType meta_backend_get_type (void);
|
|
||||||
|
|
||||||
MetaBackend * meta_get_backend (void);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
void meta_clutter_init (void);
|
void meta_clutter_init (void);
|
||||||
|
|
||||||
|
gboolean meta_activate_vt (int vt, GError **error);
|
||||||
|
|
||||||
#endif /* META_BACKEND_H */
|
#endif /* META_BACKEND_H */
|
||||||
|
@@ -36,7 +36,6 @@ typedef struct {
|
|||||||
struct _MetaCursorReference {
|
struct _MetaCursorReference {
|
||||||
int ref_count;
|
int ref_count;
|
||||||
|
|
||||||
MetaCursor cursor;
|
|
||||||
MetaCursorImage image;
|
MetaCursorImage image;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -1,172 +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 <cogl/cogl.h>
|
|
||||||
#include <cogl/cogl-wayland-server.h>
|
|
||||||
#include <clutter/clutter.h>
|
|
||||||
|
|
||||||
#include "meta-stage.h"
|
|
||||||
|
|
||||||
#include "wayland/meta-wayland-private.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);
|
|
||||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
|
||||||
ClutterActor *stage = compositor->stage;
|
|
||||||
|
|
||||||
/* During early initialization, we can have no stage */
|
|
||||||
if (!stage)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (priv->handled_by_backend)
|
|
||||||
meta_stage_set_cursor (META_STAGE (stage), NULL, &priv->current_rect);
|
|
||||||
else
|
|
||||||
meta_stage_set_cursor (META_STAGE (stage), priv->displayed_cursor, &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;
|
|
||||||
}
|
|
@@ -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 */
|
|
@@ -24,21 +24,33 @@
|
|||||||
|
|
||||||
#include <meta/meta-cursor-tracker.h>
|
#include <meta/meta-cursor-tracker.h>
|
||||||
#include <wayland-server.h>
|
#include <wayland-server.h>
|
||||||
#include <gbm.h>
|
|
||||||
|
|
||||||
#include "meta-cursor.h"
|
#include "meta-cursor.h"
|
||||||
#include "meta-cursor-renderer.h"
|
|
||||||
|
|
||||||
struct _MetaCursorTracker {
|
struct _MetaCursorTracker {
|
||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
|
|
||||||
MetaScreen *screen;
|
MetaScreen *screen;
|
||||||
MetaCursorRenderer *renderer;
|
|
||||||
|
|
||||||
gboolean is_showing;
|
gboolean is_showing;
|
||||||
|
gboolean has_hw_cursor;
|
||||||
|
|
||||||
|
/* The cursor tracker stores the cursor for the current grab
|
||||||
|
* operation, the cursor for the window with pointer focus, and
|
||||||
|
* the cursor for the root window, which contains either the
|
||||||
|
* default arrow cursor or the 'busy' hourglass if we're launching
|
||||||
|
* an app.
|
||||||
|
*
|
||||||
|
* We choose the first one available -- if there's a grab cursor,
|
||||||
|
* we choose that cursor, if there's window cursor, we choose that,
|
||||||
|
* otherwise we choose the root cursor.
|
||||||
|
*
|
||||||
|
* The displayed_cursor contains the chosen cursor.
|
||||||
|
*/
|
||||||
MetaCursorReference *displayed_cursor;
|
MetaCursorReference *displayed_cursor;
|
||||||
|
|
||||||
|
MetaCursorReference *grab_cursor;
|
||||||
|
|
||||||
/* Wayland clients can set a NULL buffer as their cursor
|
/* Wayland clients can set a NULL buffer as their cursor
|
||||||
* explicitly, which means that we shouldn't display anything.
|
* explicitly, which means that we shouldn't display anything.
|
||||||
* So, we can't simply store a NULL in window_cursor to
|
* So, we can't simply store a NULL in window_cursor to
|
||||||
@@ -49,8 +61,16 @@ struct _MetaCursorTracker {
|
|||||||
|
|
||||||
MetaCursorReference *root_cursor;
|
MetaCursorReference *root_cursor;
|
||||||
|
|
||||||
/* The cursor from the X11 server. */
|
MetaCursorReference *theme_cursors[META_CURSOR_LAST];
|
||||||
MetaCursorReference *xfixes_cursor;
|
|
||||||
|
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 {
|
struct _MetaCursorTrackerClass {
|
||||||
@@ -60,6 +80,8 @@ struct _MetaCursorTrackerClass {
|
|||||||
gboolean meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
|
gboolean meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
|
||||||
XEvent *xevent);
|
XEvent *xevent);
|
||||||
|
|
||||||
|
void meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker,
|
||||||
|
MetaCursorReference *cursor);
|
||||||
void meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
|
void meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
|
||||||
MetaCursorReference *cursor);
|
MetaCursorReference *cursor);
|
||||||
void meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker);
|
void meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker);
|
||||||
@@ -69,7 +91,8 @@ void meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
|
|||||||
void meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
|
void meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
|
||||||
int new_x,
|
int new_x,
|
||||||
int new_y);
|
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
|
#endif
|
||||||
|
@@ -36,15 +36,15 @@
|
|||||||
#include <cogl/cogl.h>
|
#include <cogl/cogl.h>
|
||||||
#include <cogl/cogl-wayland-server.h>
|
#include <cogl/cogl-wayland-server.h>
|
||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
|
#include <gbm.h>
|
||||||
|
|
||||||
#include <gdk/gdk.h>
|
#include <gdk/gdk.h>
|
||||||
#include <gdk/gdkx.h>
|
#include <gdk/gdkx.h>
|
||||||
|
|
||||||
#include "meta-backend.h"
|
|
||||||
|
|
||||||
#include "meta-cursor-private.h"
|
#include "meta-cursor-private.h"
|
||||||
#include "meta-cursor-tracker-private.h"
|
#include "meta-cursor-tracker-private.h"
|
||||||
#include "screen-private.h"
|
#include "screen-private.h"
|
||||||
|
#include "meta-monitor-manager.h"
|
||||||
|
|
||||||
#include "wayland/meta-wayland-private.h"
|
#include "wayland/meta-wayland-private.h"
|
||||||
|
|
||||||
@@ -57,46 +57,19 @@ enum {
|
|||||||
|
|
||||||
static guint signals[LAST_SIGNAL];
|
static guint signals[LAST_SIGNAL];
|
||||||
|
|
||||||
static MetaCursorReference *
|
static void meta_cursor_tracker_set_crtc_has_hw_cursor (MetaCursorTracker *tracker,
|
||||||
get_displayed_cursor (MetaCursorTracker *tracker)
|
MetaCRTC *crtc,
|
||||||
{
|
gboolean has_hw_cursor);
|
||||||
if (!tracker->is_showing)
|
static void sync_cursor (MetaCursorTracker *tracker);
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (tracker->screen->display->grab_op == META_GRAB_OP_NONE)
|
|
||||||
{
|
|
||||||
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
|
static void
|
||||||
meta_cursor_tracker_init (MetaCursorTracker *self)
|
meta_cursor_tracker_init (MetaCursorTracker *self)
|
||||||
{
|
{
|
||||||
|
/* (JS) Best (?) that can be assumed since XFixes doesn't provide a way of
|
||||||
|
detecting if the system mouse cursor is showing or not.
|
||||||
|
|
||||||
|
On wayland we start with the cursor showing
|
||||||
|
*/
|
||||||
self->is_showing = TRUE;
|
self->is_showing = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,12 +77,22 @@ static void
|
|||||||
meta_cursor_tracker_finalize (GObject *object)
|
meta_cursor_tracker_finalize (GObject *object)
|
||||||
{
|
{
|
||||||
MetaCursorTracker *self = META_CURSOR_TRACKER (object);
|
MetaCursorTracker *self = META_CURSOR_TRACKER (object);
|
||||||
|
int i;
|
||||||
|
|
||||||
if (self->displayed_cursor)
|
if (self->displayed_cursor)
|
||||||
meta_cursor_reference_unref (self->displayed_cursor);
|
meta_cursor_reference_unref (self->displayed_cursor);
|
||||||
if (self->root_cursor)
|
if (self->root_cursor)
|
||||||
meta_cursor_reference_unref (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);
|
G_OBJECT_CLASS (meta_cursor_tracker_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,20 +111,64 @@ meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass)
|
|||||||
G_TYPE_NONE, 0);
|
G_TYPE_NONE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_monitors_changed (MetaMonitorManager *monitors,
|
||||||
|
MetaCursorTracker *tracker)
|
||||||
|
{
|
||||||
|
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 *
|
static MetaCursorTracker *
|
||||||
make_wayland_cursor_tracker (MetaScreen *screen)
|
make_wayland_cursor_tracker (MetaScreen *screen)
|
||||||
{
|
{
|
||||||
MetaBackend *backend = meta_get_backend ();
|
|
||||||
MetaWaylandCompositor *compositor;
|
MetaWaylandCompositor *compositor;
|
||||||
|
CoglContext *ctx;
|
||||||
|
MetaMonitorManager *monitors;
|
||||||
MetaCursorTracker *self;
|
MetaCursorTracker *self;
|
||||||
|
|
||||||
self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
|
self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
|
||||||
self->screen = screen;
|
self->screen = screen;
|
||||||
self->renderer = meta_backend_get_cursor_renderer (backend);
|
|
||||||
|
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||||
|
self->pipeline = cogl_pipeline_new (ctx);
|
||||||
|
|
||||||
compositor = meta_wayland_compositor_get_default ();
|
compositor = meta_wayland_compositor_get_default ();
|
||||||
compositor->seat->pointer.cursor_tracker = self;
|
compositor->seat->cursor_tracker = self;
|
||||||
meta_cursor_tracker_update_position (self, 0, 0);
|
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;
|
return self;
|
||||||
}
|
}
|
||||||
@@ -149,12 +176,8 @@ make_wayland_cursor_tracker (MetaScreen *screen)
|
|||||||
static MetaCursorTracker *
|
static MetaCursorTracker *
|
||||||
make_x11_cursor_tracker (MetaScreen *screen)
|
make_x11_cursor_tracker (MetaScreen *screen)
|
||||||
{
|
{
|
||||||
MetaBackend *backend = meta_get_backend ();
|
MetaCursorTracker *self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
|
||||||
MetaCursorTracker *self;
|
|
||||||
|
|
||||||
self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
|
|
||||||
self->screen = screen;
|
self->screen = screen;
|
||||||
self->renderer = meta_backend_get_cursor_renderer (backend);
|
|
||||||
|
|
||||||
XFixesSelectCursorInput (screen->display->xdisplay,
|
XFixesSelectCursorInput (screen->display->xdisplay,
|
||||||
screen->xroot,
|
screen->xroot,
|
||||||
@@ -163,17 +186,6 @@ make_x11_cursor_tracker (MetaScreen *screen)
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
static MetaCursorTracker *
|
|
||||||
meta_cursor_tracker_new (MetaScreen *screen)
|
|
||||||
{
|
|
||||||
if (meta_is_wayland_compositor ())
|
|
||||||
return make_wayland_cursor_tracker (screen);
|
|
||||||
else
|
|
||||||
return make_x11_cursor_tracker (screen);
|
|
||||||
}
|
|
||||||
|
|
||||||
static MetaCursorTracker *_cursor_tracker;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* meta_cursor_tracker_get_for_screen:
|
* meta_cursor_tracker_get_for_screen:
|
||||||
* @screen: the #MetaScreen
|
* @screen: the #MetaScreen
|
||||||
@@ -185,10 +197,18 @@ static MetaCursorTracker *_cursor_tracker;
|
|||||||
MetaCursorTracker *
|
MetaCursorTracker *
|
||||||
meta_cursor_tracker_get_for_screen (MetaScreen *screen)
|
meta_cursor_tracker_get_for_screen (MetaScreen *screen)
|
||||||
{
|
{
|
||||||
if (!_cursor_tracker)
|
MetaCursorTracker *self;
|
||||||
_cursor_tracker = meta_cursor_tracker_new (screen);
|
|
||||||
|
|
||||||
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
|
static void
|
||||||
@@ -219,7 +239,7 @@ meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
|
|||||||
if (notify_event->subtype != XFixesDisplayCursorNotify)
|
if (notify_event->subtype != XFixesDisplayCursorNotify)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
g_clear_pointer (&tracker->xfixes_cursor, meta_cursor_reference_unref);
|
set_window_cursor (tracker, FALSE, NULL);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -249,7 +269,7 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
|
|||||||
gboolean free_cursor_data;
|
gboolean free_cursor_data;
|
||||||
CoglContext *ctx;
|
CoglContext *ctx;
|
||||||
|
|
||||||
if (tracker->xfixes_cursor)
|
if (tracker->has_window_cursor)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cursor_image = XFixesGetCursorImage (tracker->screen->display->xdisplay);
|
cursor_image = XFixesGetCursorImage (tracker->screen->display->xdisplay);
|
||||||
@@ -299,7 +319,7 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
|
|||||||
MetaCursorReference *cursor = meta_cursor_reference_take_texture (sprite,
|
MetaCursorReference *cursor = meta_cursor_reference_take_texture (sprite,
|
||||||
cursor_image->xhot,
|
cursor_image->xhot,
|
||||||
cursor_image->yhot);
|
cursor_image->yhot);
|
||||||
tracker->xfixes_cursor = cursor;
|
set_window_cursor (tracker, TRUE, cursor);
|
||||||
}
|
}
|
||||||
XFree (cursor_image);
|
XFree (cursor_image);
|
||||||
}
|
}
|
||||||
@@ -312,22 +332,13 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
|
|||||||
CoglTexture *
|
CoglTexture *
|
||||||
meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker)
|
meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker)
|
||||||
{
|
{
|
||||||
MetaCursorReference *cursor;
|
|
||||||
|
|
||||||
g_return_val_if_fail (META_IS_CURSOR_TRACKER (tracker), NULL);
|
g_return_val_if_fail (META_IS_CURSOR_TRACKER (tracker), NULL);
|
||||||
|
|
||||||
if (meta_is_wayland_compositor ())
|
if (!meta_is_wayland_compositor ())
|
||||||
{
|
ensure_xfixes_cursor (tracker);
|
||||||
cursor = tracker->displayed_cursor;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ensure_xfixes_cursor (tracker);
|
|
||||||
cursor = tracker->xfixes_cursor;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cursor)
|
if (tracker->displayed_cursor)
|
||||||
return meta_cursor_reference_get_cogl_texture (cursor, NULL, NULL);
|
return meta_cursor_reference_get_cogl_texture (tracker->displayed_cursor, NULL, NULL);
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -344,22 +355,13 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
|
|||||||
int *x,
|
int *x,
|
||||||
int *y)
|
int *y)
|
||||||
{
|
{
|
||||||
MetaCursorReference *cursor;
|
|
||||||
|
|
||||||
g_return_if_fail (META_IS_CURSOR_TRACKER (tracker));
|
g_return_if_fail (META_IS_CURSOR_TRACKER (tracker));
|
||||||
|
|
||||||
if (meta_is_wayland_compositor ())
|
if (!meta_is_wayland_compositor ())
|
||||||
{
|
ensure_xfixes_cursor (tracker);
|
||||||
cursor = tracker->displayed_cursor;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ensure_xfixes_cursor (tracker);
|
|
||||||
cursor = tracker->xfixes_cursor;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cursor)
|
if (tracker->displayed_cursor)
|
||||||
meta_cursor_reference_get_cogl_texture (cursor, x, y);
|
meta_cursor_reference_get_cogl_texture (tracker->displayed_cursor, x, y);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (x)
|
if (x)
|
||||||
@@ -369,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
|
void
|
||||||
meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
|
meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
|
||||||
MetaCursorReference *cursor)
|
MetaCursorReference *cursor)
|
||||||
@@ -393,6 +406,184 @@ meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
|
|||||||
sync_cursor (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
|
void
|
||||||
meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
|
meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
|
||||||
int new_x,
|
int new_x,
|
||||||
@@ -400,7 +591,61 @@ meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
|
|||||||
{
|
{
|
||||||
g_assert (meta_is_wayland_compositor ());
|
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
|
static void
|
||||||
@@ -468,11 +713,26 @@ meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker,
|
|||||||
return;
|
return;
|
||||||
tracker->is_showing = visible;
|
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 *
|
void
|
||||||
meta_cursor_tracker_get_displayed_cursor (MetaCursorTracker *tracker)
|
meta_cursor_tracker_force_update (MetaCursorTracker *tracker)
|
||||||
{
|
{
|
||||||
return tracker->displayed_cursor;
|
g_assert (meta_is_wayland_compositor ());
|
||||||
|
|
||||||
|
update_hw_cursor (tracker);
|
||||||
|
sync_cursor (tracker);
|
||||||
}
|
}
|
||||||
|
@@ -27,8 +27,7 @@
|
|||||||
|
|
||||||
#include "display-private.h"
|
#include "display-private.h"
|
||||||
#include "screen-private.h"
|
#include "screen-private.h"
|
||||||
#include "meta-backend.h"
|
#include "meta-cursor-tracker-private.h" /* for tracker->gbm */
|
||||||
#include "backends/native/meta-cursor-renderer-native.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -71,67 +70,124 @@ meta_cursor_reference_unref (MetaCursorReference *self)
|
|||||||
meta_cursor_reference_free (self);
|
meta_cursor_reference_free (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
static void
|
||||||
translate_meta_cursor (MetaCursor cursor)
|
translate_meta_cursor (MetaCursor cursor,
|
||||||
|
guint *glyph_out,
|
||||||
|
const char **name_out)
|
||||||
{
|
{
|
||||||
|
guint glyph = XC_num_glyphs;
|
||||||
|
const char *name = NULL;
|
||||||
|
|
||||||
switch (cursor)
|
switch (cursor)
|
||||||
{
|
{
|
||||||
case META_CURSOR_DEFAULT:
|
case META_CURSOR_DEFAULT:
|
||||||
return "left_ptr";
|
glyph = XC_left_ptr;
|
||||||
|
break;
|
||||||
case META_CURSOR_NORTH_RESIZE:
|
case META_CURSOR_NORTH_RESIZE:
|
||||||
return "top_side";
|
glyph = XC_top_side;
|
||||||
|
break;
|
||||||
case META_CURSOR_SOUTH_RESIZE:
|
case META_CURSOR_SOUTH_RESIZE:
|
||||||
return "bottom_side";
|
glyph = XC_bottom_side;
|
||||||
|
break;
|
||||||
case META_CURSOR_WEST_RESIZE:
|
case META_CURSOR_WEST_RESIZE:
|
||||||
return "left_side";
|
glyph = XC_left_side;
|
||||||
|
break;
|
||||||
case META_CURSOR_EAST_RESIZE:
|
case META_CURSOR_EAST_RESIZE:
|
||||||
return "right_side";
|
glyph = XC_right_side;
|
||||||
|
break;
|
||||||
case META_CURSOR_SE_RESIZE:
|
case META_CURSOR_SE_RESIZE:
|
||||||
return "bottom_right_corner";
|
glyph = XC_bottom_right_corner;
|
||||||
|
break;
|
||||||
case META_CURSOR_SW_RESIZE:
|
case META_CURSOR_SW_RESIZE:
|
||||||
return "bottom_left_corner";
|
glyph = XC_bottom_left_corner;
|
||||||
|
break;
|
||||||
case META_CURSOR_NE_RESIZE:
|
case META_CURSOR_NE_RESIZE:
|
||||||
return "top_right_corner";
|
glyph = XC_top_right_corner;
|
||||||
|
break;
|
||||||
case META_CURSOR_NW_RESIZE:
|
case META_CURSOR_NW_RESIZE:
|
||||||
return "top_left_corner";
|
glyph = XC_top_left_corner;
|
||||||
|
break;
|
||||||
case META_CURSOR_MOVE_OR_RESIZE_WINDOW:
|
case META_CURSOR_MOVE_OR_RESIZE_WINDOW:
|
||||||
return "fleur";
|
glyph = XC_fleur;
|
||||||
|
break;
|
||||||
case META_CURSOR_BUSY:
|
case META_CURSOR_BUSY:
|
||||||
return "watch";
|
glyph = XC_watch;
|
||||||
|
break;
|
||||||
case META_CURSOR_DND_IN_DRAG:
|
case META_CURSOR_DND_IN_DRAG:
|
||||||
return "dnd-none";
|
name = "dnd-none";
|
||||||
|
break;
|
||||||
case META_CURSOR_DND_MOVE:
|
case META_CURSOR_DND_MOVE:
|
||||||
return "dnd-move";
|
name = "dnd-move";
|
||||||
|
break;
|
||||||
case META_CURSOR_DND_COPY:
|
case META_CURSOR_DND_COPY:
|
||||||
return "dnd-copy";
|
name = "dnd-copy";
|
||||||
|
break;
|
||||||
case META_CURSOR_DND_UNSUPPORTED_TARGET:
|
case META_CURSOR_DND_UNSUPPORTED_TARGET:
|
||||||
return "dnd-none";
|
name = "dnd-none";
|
||||||
|
break;
|
||||||
case META_CURSOR_POINTING_HAND:
|
case META_CURSOR_POINTING_HAND:
|
||||||
return "hand2";
|
glyph = XC_hand2;
|
||||||
|
break;
|
||||||
case META_CURSOR_CROSSHAIR:
|
case META_CURSOR_CROSSHAIR:
|
||||||
return "crosshair";
|
glyph = XC_crosshair;
|
||||||
|
break;
|
||||||
case META_CURSOR_IBEAM:
|
case META_CURSOR_IBEAM:
|
||||||
return "xterm";
|
glyph = XC_xterm;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
glyph = 0; /* silence compiler */
|
||||||
break;
|
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
|
Cursor
|
||||||
meta_cursor_create_x_cursor (Display *xdisplay,
|
meta_display_create_x_cursor (MetaDisplay *display,
|
||||||
MetaCursor cursor)
|
MetaCursor cursor)
|
||||||
{
|
{
|
||||||
return XcursorLibraryLoadCursor (xdisplay, translate_meta_cursor (cursor));
|
return load_cursor_on_server (display, cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
static XcursorImage *
|
static XcursorImage *
|
||||||
load_cursor_on_client (MetaCursor cursor)
|
load_cursor_on_client (MetaDisplay *display,
|
||||||
|
MetaCursor cursor)
|
||||||
{
|
{
|
||||||
return XcursorLibraryLoadImage (translate_meta_cursor (cursor),
|
XcursorImage *image;
|
||||||
meta_prefs_get_cursor_theme (),
|
guint glyph;
|
||||||
meta_prefs_get_cursor_size ());
|
const char *name;
|
||||||
|
const char *theme = XcursorGetTheme (display->xdisplay);
|
||||||
|
int size = XcursorGetDefaultSize (display->xdisplay);
|
||||||
|
|
||||||
|
translate_meta_cursor (cursor, &glyph, &name);
|
||||||
|
|
||||||
|
if (name != NULL)
|
||||||
|
image = XcursorLibraryLoadImage (name, theme, size);
|
||||||
|
else
|
||||||
|
image = XcursorShapeLoadImage (glyph, theme, size);
|
||||||
|
|
||||||
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -168,20 +224,9 @@ meta_cursor_image_load_gbm_buffer (struct gbm_device *gbm,
|
|||||||
meta_warning ("HW cursor for format %d not supported\n", gbm_format);
|
meta_warning ("HW cursor for format %d not supported\n", gbm_format);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct gbm_device *
|
|
||||||
get_gbm_device (void)
|
|
||||||
{
|
|
||||||
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));
|
|
||||||
else
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
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)
|
XcursorImage *xc_image)
|
||||||
{
|
{
|
||||||
int width, height, rowstride;
|
int width, height, rowstride;
|
||||||
@@ -189,7 +234,6 @@ meta_cursor_image_load_from_xcursor_image (MetaCursorImage *image,
|
|||||||
uint32_t gbm_format;
|
uint32_t gbm_format;
|
||||||
ClutterBackend *clutter_backend;
|
ClutterBackend *clutter_backend;
|
||||||
CoglContext *cogl_context;
|
CoglContext *cogl_context;
|
||||||
struct gbm_device *gbm;
|
|
||||||
|
|
||||||
width = xc_image->width;
|
width = xc_image->width;
|
||||||
height = xc_image->height;
|
height = xc_image->height;
|
||||||
@@ -214,9 +258,8 @@ meta_cursor_image_load_from_xcursor_image (MetaCursorImage *image,
|
|||||||
(uint8_t *) xc_image->pixels,
|
(uint8_t *) xc_image->pixels,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
gbm = get_gbm_device ();
|
if (tracker->gbm)
|
||||||
if (gbm)
|
meta_cursor_image_load_gbm_buffer (tracker->gbm,
|
||||||
meta_cursor_image_load_gbm_buffer (gbm,
|
|
||||||
image,
|
image,
|
||||||
(uint8_t *) xc_image->pixels,
|
(uint8_t *) xc_image->pixels,
|
||||||
width, height, rowstride,
|
width, height, rowstride,
|
||||||
@@ -224,32 +267,34 @@ meta_cursor_image_load_from_xcursor_image (MetaCursorImage *image,
|
|||||||
}
|
}
|
||||||
|
|
||||||
MetaCursorReference *
|
MetaCursorReference *
|
||||||
meta_cursor_reference_from_theme (MetaCursor cursor)
|
meta_cursor_reference_from_theme (MetaCursorTracker *tracker,
|
||||||
|
MetaCursor cursor)
|
||||||
{
|
{
|
||||||
MetaCursorReference *self;
|
MetaCursorReference *self;
|
||||||
XcursorImage *image;
|
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)
|
if (!image)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
self = g_slice_new0 (MetaCursorReference);
|
self = g_slice_new0 (MetaCursorReference);
|
||||||
self->ref_count = 1;
|
self->ref_count = 1;
|
||||||
self->cursor = cursor;
|
meta_cursor_image_load_from_xcursor_image (tracker, &self->image, image);
|
||||||
meta_cursor_image_load_from_xcursor_image (&self->image, image);
|
|
||||||
|
|
||||||
XcursorImageDestroy (image);
|
XcursorImageDestroy (image);
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_cursor_image_load_from_buffer (MetaCursorImage *image,
|
meta_cursor_image_load_from_buffer (MetaCursorTracker *tracker,
|
||||||
|
MetaCursorImage *image,
|
||||||
struct wl_resource *buffer,
|
struct wl_resource *buffer,
|
||||||
int hot_x,
|
int hot_x,
|
||||||
int hot_y)
|
int hot_y)
|
||||||
{
|
{
|
||||||
struct gbm_device *gbm = get_gbm_device ();
|
|
||||||
|
|
||||||
ClutterBackend *backend;
|
ClutterBackend *backend;
|
||||||
CoglContext *cogl_context;
|
CoglContext *cogl_context;
|
||||||
struct wl_shm_buffer *shm_buffer;
|
struct wl_shm_buffer *shm_buffer;
|
||||||
@@ -270,7 +315,7 @@ meta_cursor_image_load_from_buffer (MetaCursorImage *image,
|
|||||||
shm_buffer = wl_shm_buffer_get (buffer);
|
shm_buffer = wl_shm_buffer_get (buffer);
|
||||||
if (shm_buffer)
|
if (shm_buffer)
|
||||||
{
|
{
|
||||||
if (gbm)
|
if (tracker->gbm)
|
||||||
{
|
{
|
||||||
int rowstride = wl_shm_buffer_get_stride (shm_buffer);
|
int rowstride = wl_shm_buffer_get_stride (shm_buffer);
|
||||||
|
|
||||||
@@ -296,7 +341,7 @@ meta_cursor_image_load_from_buffer (MetaCursorImage *image,
|
|||||||
gbm_format = GBM_FORMAT_ARGB8888;
|
gbm_format = GBM_FORMAT_ARGB8888;
|
||||||
}
|
}
|
||||||
|
|
||||||
meta_cursor_image_load_gbm_buffer (gbm,
|
meta_cursor_image_load_gbm_buffer (tracker->gbm,
|
||||||
image,
|
image,
|
||||||
(uint8_t *) wl_shm_buffer_get_data (shm_buffer),
|
(uint8_t *) wl_shm_buffer_get_data (shm_buffer),
|
||||||
width, height, rowstride,
|
width, height, rowstride,
|
||||||
@@ -317,9 +362,9 @@ meta_cursor_image_load_from_buffer (MetaCursorImage *image,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gbm)
|
if (tracker->gbm)
|
||||||
{
|
{
|
||||||
image->bo = gbm_bo_import (gbm, GBM_BO_IMPORT_WL_BUFFER,
|
image->bo = gbm_bo_import (tracker->gbm, GBM_BO_IMPORT_WL_BUFFER,
|
||||||
buffer, GBM_BO_USE_CURSOR_64X64);
|
buffer, GBM_BO_USE_CURSOR_64X64);
|
||||||
if (!image->bo)
|
if (!image->bo)
|
||||||
meta_warning ("Importing HW cursor from wl_buffer failed\n");
|
meta_warning ("Importing HW cursor from wl_buffer failed\n");
|
||||||
@@ -328,7 +373,8 @@ meta_cursor_image_load_from_buffer (MetaCursorImage *image,
|
|||||||
}
|
}
|
||||||
|
|
||||||
MetaCursorReference *
|
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_x,
|
||||||
int hot_y)
|
int hot_y)
|
||||||
{
|
{
|
||||||
@@ -336,7 +382,7 @@ meta_cursor_reference_from_buffer (struct wl_resource *buffer,
|
|||||||
|
|
||||||
self = g_slice_new0 (MetaCursorReference);
|
self = g_slice_new0 (MetaCursorReference);
|
||||||
self->ref_count = 1;
|
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;
|
return self;
|
||||||
}
|
}
|
||||||
@@ -364,9 +410,3 @@ meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
|
|||||||
*hot_y = cursor->image.hot_y;
|
*hot_y = cursor->image.hot_y;
|
||||||
return cursor->image.bo;
|
return cursor->image.bo;
|
||||||
}
|
}
|
||||||
|
|
||||||
MetaCursor
|
|
||||||
meta_cursor_reference_get_meta_cursor (MetaCursorReference *cursor)
|
|
||||||
{
|
|
||||||
return cursor->cursor;
|
|
||||||
}
|
|
||||||
|
@@ -27,18 +27,16 @@ typedef struct _MetaCursorReference MetaCursorReference;
|
|||||||
MetaCursorReference * meta_cursor_reference_ref (MetaCursorReference *cursor);
|
MetaCursorReference * meta_cursor_reference_ref (MetaCursorReference *cursor);
|
||||||
void meta_cursor_reference_unref (MetaCursorReference *cursor);
|
void meta_cursor_reference_unref (MetaCursorReference *cursor);
|
||||||
|
|
||||||
|
#include <meta/meta-cursor-tracker.h>
|
||||||
#include <meta/common.h>
|
#include <meta/common.h>
|
||||||
#include <wayland-server.h>
|
#include <wayland-server.h>
|
||||||
|
|
||||||
MetaCursorReference * meta_cursor_reference_from_theme (MetaCursor cursor);
|
MetaCursorReference * meta_cursor_reference_from_theme (MetaCursorTracker *tracker,
|
||||||
|
MetaCursor cursor);
|
||||||
|
|
||||||
MetaCursorReference * meta_cursor_reference_from_buffer (struct wl_resource *buffer,
|
MetaCursorReference * meta_cursor_reference_from_buffer (MetaCursorTracker *tracker,
|
||||||
|
struct wl_resource *buffer,
|
||||||
int hot_x,
|
int hot_x,
|
||||||
int hot_y);
|
int hot_y);
|
||||||
|
|
||||||
MetaCursor meta_cursor_reference_get_meta_cursor (MetaCursorReference *cursor);
|
|
||||||
|
|
||||||
Cursor meta_cursor_create_x_cursor (Display *xdisplay,
|
|
||||||
MetaCursor cursor);
|
|
||||||
|
|
||||||
#endif /* META_CURSOR_H */
|
#endif /* META_CURSOR_H */
|
||||||
|
@@ -180,9 +180,6 @@ create_monitor_skeleton (GDBusObjectManagerServer *manager,
|
|||||||
meta_dbus_object_skeleton_set_idle_monitor (object, skeleton);
|
meta_dbus_object_skeleton_set_idle_monitor (object, skeleton);
|
||||||
|
|
||||||
g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (object));
|
g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (object));
|
||||||
|
|
||||||
g_object_unref (skeleton);
|
|
||||||
g_object_unref (object);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@@ -38,7 +38,8 @@
|
|||||||
#include <meta/meta-idle-monitor.h>
|
#include <meta/meta-idle-monitor.h>
|
||||||
#include "meta-idle-monitor-private.h"
|
#include "meta-idle-monitor-private.h"
|
||||||
#include "meta-idle-monitor-dbus.h"
|
#include "meta-idle-monitor-dbus.h"
|
||||||
#include "meta-backend.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));
|
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)
|
G_DEFINE_TYPE (MetaIdleMonitor, meta_idle_monitor, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
static MetaIdleMonitor *device_monitors[256];
|
||||||
|
static int device_id_max;
|
||||||
|
|
||||||
void
|
void
|
||||||
_meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch)
|
_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:
|
* meta_idle_monitor_get_core:
|
||||||
*
|
*
|
||||||
@@ -166,8 +200,8 @@ meta_idle_monitor_init (MetaIdleMonitor *monitor)
|
|||||||
MetaIdleMonitor *
|
MetaIdleMonitor *
|
||||||
meta_idle_monitor_get_core (void)
|
meta_idle_monitor_get_core (void)
|
||||||
{
|
{
|
||||||
MetaBackend *backend = meta_get_backend ();
|
ensure_device_monitor (0);
|
||||||
return meta_backend_get_idle_monitor (backend, 0);
|
return device_monitors[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -181,8 +215,10 @@ meta_idle_monitor_get_core (void)
|
|||||||
MetaIdleMonitor *
|
MetaIdleMonitor *
|
||||||
meta_idle_monitor_get_for_device (int device_id)
|
meta_idle_monitor_get_for_device (int device_id)
|
||||||
{
|
{
|
||||||
MetaBackend *backend = meta_get_backend ();
|
g_return_val_if_fail (device_id > 0 && device_id < 256, NULL);
|
||||||
return meta_backend_get_idle_monitor (backend, device_id);
|
|
||||||
|
ensure_device_monitor (device_id);
|
||||||
|
return device_monitors[device_id];
|
||||||
}
|
}
|
||||||
|
|
||||||
static MetaIdleMonitorWatch *
|
static MetaIdleMonitorWatch *
|
||||||
@@ -316,3 +352,16 @@ meta_idle_monitor_get_idletime (MetaIdleMonitor *monitor)
|
|||||||
{
|
{
|
||||||
return META_IDLE_MONITOR_GET_CLASS (monitor)->get_idletime (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);
|
||||||
|
}
|
||||||
|
@@ -78,7 +78,6 @@ struct _MetaMonitorConfig {
|
|||||||
GHashTable *configs;
|
GHashTable *configs;
|
||||||
MetaConfiguration *current;
|
MetaConfiguration *current;
|
||||||
gboolean current_is_stored;
|
gboolean current_is_stored;
|
||||||
gboolean current_is_for_laptop_lid;
|
|
||||||
MetaConfiguration *previous;
|
MetaConfiguration *previous;
|
||||||
|
|
||||||
GFile *file;
|
GFile *file;
|
||||||
@@ -841,9 +840,6 @@ meta_monitor_config_get_stored (MetaMonitorConfig *self,
|
|||||||
MetaConfiguration key;
|
MetaConfiguration key;
|
||||||
MetaConfiguration *stored;
|
MetaConfiguration *stored;
|
||||||
|
|
||||||
if (n_outputs == 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
make_config_key (&key, outputs, n_outputs, -1);
|
make_config_key (&key, outputs, n_outputs, -1);
|
||||||
stored = g_hash_table_lookup (self->configs, &key);
|
stored = g_hash_table_lookup (self->configs, &key);
|
||||||
|
|
||||||
@@ -878,8 +874,7 @@ apply_configuration (MetaMonitorConfig *self,
|
|||||||
|
|
||||||
/* Stored (persistent) configurations override the previous one always.
|
/* Stored (persistent) configurations override the previous one always.
|
||||||
Also, we clear the previous configuration if the current one (which is
|
Also, we clear the previous configuration if the current one (which is
|
||||||
about to become previous) is stored, or if the current one has
|
about to become previous) is stored.
|
||||||
different outputs.
|
|
||||||
*/
|
*/
|
||||||
if (stored ||
|
if (stored ||
|
||||||
(self->current && self->current_is_stored))
|
(self->current && self->current_is_stored))
|
||||||
@@ -890,27 +885,11 @@ apply_configuration (MetaMonitorConfig *self,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Despite the name, config_equal() only checks the set of outputs,
|
self->previous = self->current;
|
||||||
not their modes
|
|
||||||
*/
|
|
||||||
if (self->current && config_equal (self->current, config))
|
|
||||||
{
|
|
||||||
self->previous = self->current;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (self->current)
|
|
||||||
config_free (self->current);
|
|
||||||
self->previous = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self->current = config;
|
self->current = config;
|
||||||
self->current_is_stored = stored;
|
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)
|
if (self->current == self->previous)
|
||||||
self->previous = NULL;
|
self->previous = NULL;
|
||||||
@@ -1027,16 +1006,8 @@ meta_monitor_config_apply_stored (MetaMonitorConfig *self,
|
|||||||
if (self->lid_is_closed &&
|
if (self->lid_is_closed &&
|
||||||
stored->n_outputs > 1 &&
|
stored->n_outputs > 1 &&
|
||||||
laptop_display_is_on (stored))
|
laptop_display_is_on (stored))
|
||||||
{
|
return apply_configuration (self, make_laptop_lid_config (stored),
|
||||||
if (apply_configuration (self, make_laptop_lid_config (stored),
|
manager, FALSE);
|
||||||
manager, FALSE))
|
|
||||||
{
|
|
||||||
self->current_is_for_laptop_lid = TRUE;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
return apply_configuration (self, stored, manager, TRUE);
|
return apply_configuration (self, stored, manager, TRUE);
|
||||||
}
|
}
|
||||||
@@ -1276,12 +1247,6 @@ meta_monitor_config_make_default (MetaMonitorConfig *self,
|
|||||||
outputs = meta_monitor_manager_get_outputs (manager, &n_outputs);
|
outputs = meta_monitor_manager_get_outputs (manager, &n_outputs);
|
||||||
meta_monitor_manager_get_screen_limits (manager, &max_width, &max_height);
|
meta_monitor_manager_get_screen_limits (manager, &max_width, &max_height);
|
||||||
|
|
||||||
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);
|
default_config = make_default_config (self, outputs, n_outputs, max_width, max_height);
|
||||||
|
|
||||||
if (default_config != NULL)
|
if (default_config != NULL)
|
||||||
@@ -1383,7 +1348,6 @@ turn_off_laptop_display (MetaMonitorConfig *self,
|
|||||||
|
|
||||||
new = make_laptop_lid_config (self->current);
|
new = make_laptop_lid_config (self->current);
|
||||||
apply_configuration (self, new, manager, FALSE);
|
apply_configuration (self, new, manager, FALSE);
|
||||||
self->current_is_for_laptop_lid = TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1403,7 +1367,7 @@ power_client_changed_cb (UpClient *client,
|
|||||||
|
|
||||||
if (is_closed)
|
if (is_closed)
|
||||||
turn_off_laptop_display (self, manager);
|
turn_off_laptop_display (self, manager);
|
||||||
else if (self->current_is_for_laptop_lid)
|
else
|
||||||
meta_monitor_config_restore_previous (self, manager);
|
meta_monitor_config_restore_previous (self, manager);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -36,8 +36,9 @@
|
|||||||
#include "util-private.h"
|
#include "util-private.h"
|
||||||
#include <meta/errors.h>
|
#include <meta/errors.h>
|
||||||
#include "meta-monitor-config.h"
|
#include "meta-monitor-config.h"
|
||||||
|
#include "backends/native/meta-monitor-manager-kms.h"
|
||||||
#include "backends/x11/meta-monitor-manager-xrandr.h"
|
#include "backends/x11/meta-monitor-manager-xrandr.h"
|
||||||
#include "meta-backend.h"
|
#include "meta-monitor-manager-dummy.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
CONFIRM_DISPLAY_CHANGE,
|
CONFIRM_DISPLAY_CHANGE,
|
||||||
@@ -167,6 +168,58 @@ make_logical_config (MetaMonitorManager *manager)
|
|||||||
manager->monitor_infos = (void*)g_array_free (monitor_infos, FALSE);
|
manager->monitor_infos = (void*)g_array_free (monitor_infos, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GType
|
||||||
|
get_default_backend (void)
|
||||||
|
{
|
||||||
|
#if defined(CLUTTER_WINDOWING_EGL)
|
||||||
|
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
|
||||||
|
return META_TYPE_MONITOR_MANAGER_KMS;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CLUTTER_WINDOWING_X11)
|
||||||
|
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_X11))
|
||||||
|
{
|
||||||
|
/* 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
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
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
|
static void
|
||||||
meta_monitor_manager_constructed (GObject *object)
|
meta_monitor_manager_constructed (GObject *object)
|
||||||
{
|
{
|
||||||
@@ -483,13 +536,13 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
|
|||||||
|
|
||||||
g_variant_builder_add (&crtc_builder, "(uxiiiiiuaua{sv})",
|
g_variant_builder_add (&crtc_builder, "(uxiiiiiuaua{sv})",
|
||||||
i, /* ID */
|
i, /* ID */
|
||||||
(gint64)crtc->crtc_id,
|
crtc->crtc_id,
|
||||||
(int)crtc->rect.x,
|
(int)crtc->rect.x,
|
||||||
(int)crtc->rect.y,
|
(int)crtc->rect.y,
|
||||||
(int)crtc->rect.width,
|
(int)crtc->rect.width,
|
||||||
(int)crtc->rect.height,
|
(int)crtc->rect.height,
|
||||||
(int)(crtc->current_mode ? crtc->current_mode - manager->modes : -1),
|
(int)(crtc->current_mode ? crtc->current_mode - manager->modes : -1),
|
||||||
(guint32)crtc->transform,
|
crtc->transform,
|
||||||
&transforms,
|
&transforms,
|
||||||
NULL /* properties */);
|
NULL /* properties */);
|
||||||
}
|
}
|
||||||
@@ -560,7 +613,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
|
|||||||
|
|
||||||
g_variant_builder_add (&output_builder, "(uxiausauaua{sv})",
|
g_variant_builder_add (&output_builder, "(uxiausauaua{sv})",
|
||||||
i, /* ID */
|
i, /* ID */
|
||||||
(gint64)output->output_id,
|
output->output_id,
|
||||||
(int)(output->crtc ? output->crtc - manager->crtcs : -1),
|
(int)(output->crtc ? output->crtc - manager->crtcs : -1),
|
||||||
&crtcs,
|
&crtcs,
|
||||||
output->name,
|
output->name,
|
||||||
@@ -575,9 +628,9 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
|
|||||||
|
|
||||||
g_variant_builder_add (&mode_builder, "(uxuud)",
|
g_variant_builder_add (&mode_builder, "(uxuud)",
|
||||||
i, /* ID */
|
i, /* ID */
|
||||||
(gint64)mode->mode_id,
|
mode->mode_id,
|
||||||
(guint32)mode->width,
|
mode->width,
|
||||||
(guint32)mode->height,
|
mode->height,
|
||||||
(double)mode->refresh_rate);
|
(double)mode->refresh_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -878,7 +931,6 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
|||||||
if (persistent)
|
if (persistent)
|
||||||
{
|
{
|
||||||
manager->persistent_timeout_id = g_timeout_add_seconds (20, save_config_timeout, manager);
|
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);
|
g_signal_emit (manager, signals[CONFIRM_DISPLAY_CHANGE], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1126,12 +1178,20 @@ initialize_dbus_interface (MetaMonitorManager *manager)
|
|||||||
g_object_unref);
|
g_object_unref);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static MetaMonitorManager *global_monitor_manager;
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_monitor_manager_initialize (void)
|
||||||
|
{
|
||||||
|
global_monitor_manager = meta_monitor_manager_new ();
|
||||||
|
}
|
||||||
|
|
||||||
MetaMonitorManager *
|
MetaMonitorManager *
|
||||||
meta_monitor_manager_get (void)
|
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 *
|
MetaMonitorInfo *
|
||||||
@@ -1217,3 +1277,16 @@ meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager)
|
|||||||
g_free (old_monitor_infos);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -46,7 +46,6 @@
|
|||||||
|
|
||||||
#include "meta-display-config-shared.h"
|
#include "meta-display-config-shared.h"
|
||||||
#include "meta-dbus-display-config.h"
|
#include "meta-dbus-display-config.h"
|
||||||
#include "meta-cursor.h"
|
|
||||||
|
|
||||||
typedef struct _MetaMonitorManagerClass MetaMonitorManagerClass;
|
typedef struct _MetaMonitorManagerClass MetaMonitorManagerClass;
|
||||||
typedef struct _MetaMonitorManager MetaMonitorManager;
|
typedef struct _MetaMonitorManager MetaMonitorManager;
|
||||||
@@ -73,7 +72,6 @@ struct _MetaOutput
|
|||||||
int width_mm;
|
int width_mm;
|
||||||
int height_mm;
|
int height_mm;
|
||||||
CoglSubpixelOrder subpixel_order;
|
CoglSubpixelOrder subpixel_order;
|
||||||
int scale;
|
|
||||||
|
|
||||||
MetaMonitorMode *preferred_mode;
|
MetaMonitorMode *preferred_mode;
|
||||||
MetaMonitorMode **modes;
|
MetaMonitorMode **modes;
|
||||||
@@ -125,7 +123,8 @@ struct _MetaCRTC
|
|||||||
/* Used when changing configuration */
|
/* Used when changing configuration */
|
||||||
gboolean is_dirty;
|
gboolean is_dirty;
|
||||||
|
|
||||||
MetaCursorReference *cursor;
|
/* Updated by MetaCursorTracker */
|
||||||
|
gboolean has_hw_cursor;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _MetaMonitorMode
|
struct _MetaMonitorMode
|
||||||
@@ -286,10 +285,14 @@ struct _MetaMonitorManagerClass
|
|||||||
unsigned short *,
|
unsigned short *,
|
||||||
unsigned short *,
|
unsigned short *,
|
||||||
unsigned short *);
|
unsigned short *);
|
||||||
|
|
||||||
|
gboolean (*handle_xevent) (MetaMonitorManager *,
|
||||||
|
XEvent *);
|
||||||
};
|
};
|
||||||
|
|
||||||
GType meta_monitor_manager_get_type (void);
|
GType meta_monitor_manager_get_type (void);
|
||||||
|
|
||||||
|
void meta_monitor_manager_initialize (void);
|
||||||
MetaMonitorManager *meta_monitor_manager_get (void);
|
MetaMonitorManager *meta_monitor_manager_get (void);
|
||||||
|
|
||||||
void meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager);
|
void meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager);
|
||||||
@@ -310,6 +313,9 @@ void meta_monitor_manager_get_resources (MetaMonitorManager
|
|||||||
|
|
||||||
int meta_monitor_manager_get_primary_index (MetaMonitorManager *manager);
|
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,
|
void meta_monitor_manager_get_screen_size (MetaMonitorManager *manager,
|
||||||
int *width,
|
int *width,
|
||||||
int *height);
|
int *height);
|
||||||
|
@@ -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;
|
|
||||||
}
|
|
@@ -1,32 +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 DBUS_UTILS_H
|
|
||||||
#define DBUS_UTILS_H
|
|
||||||
|
|
||||||
char *
|
|
||||||
get_escaped_dbus_path (const char *prefix,
|
|
||||||
const char *component);
|
|
||||||
|
|
||||||
#endif /* DBUS_UTILS_H */
|
|
@@ -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/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;
|
|
||||||
};
|
|
||||||
typedef struct _MetaBackendNativePrivate MetaBackendNativePrivate;
|
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaBackendNative, meta_backend_native, META_TYPE_BACKEND);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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, ¤t);
|
|
||||||
|
|
||||||
/* 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
|
|
||||||
meta_backend_native_post_init (MetaBackend *backend)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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_class_init (MetaBackendNativeClass *klass)
|
|
||||||
{
|
|
||||||
MetaBackendClass *backend_class = META_BACKEND_CLASS (klass);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
* Wayland compositor, 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;
|
|
||||||
}
|
|
@@ -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 */
|
|
@@ -1,205 +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 "meta-cursor-private.h"
|
|
||||||
#include "meta-monitor-manager.h"
|
|
||||||
|
|
||||||
struct _MetaCursorRendererNativePrivate
|
|
||||||
{
|
|
||||||
gboolean has_hw_cursor;
|
|
||||||
|
|
||||||
int drm_fd;
|
|
||||||
struct gbm_device *gbm;
|
|
||||||
};
|
|
||||||
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 width, height;
|
|
||||||
int hot_x, hot_y;
|
|
||||||
|
|
||||||
bo = meta_cursor_reference_get_gbm_bo (cursor, &hot_x, &hot_y);
|
|
||||||
|
|
||||||
handle = gbm_bo_get_handle (bo);
|
|
||||||
width = gbm_bo_get_width (bo);
|
|
||||||
height = gbm_bo_get_height (bo);
|
|
||||||
|
|
||||||
drmModeSetCursor2 (priv->drm_fd, crtc->crtc_id, handle.u32,
|
|
||||||
width, 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);
|
|
||||||
}
|
|
||||||
#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_force_update (MetaCursorRendererNative *native)
|
|
||||||
{
|
|
||||||
update_hw_cursor (native, TRUE);
|
|
||||||
}
|
|
@@ -1,55 +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_force_update (MetaCursorRendererNative *renderer);
|
|
||||||
|
|
||||||
#endif /* META_CURSOR_RENDERER_NATIVE_H */
|
|
@@ -1,368 +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 "wayland/meta-wayland-private.h"
|
|
||||||
#include "backends/meta-backend.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 ();
|
|
||||||
|
|
||||||
{
|
|
||||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
|
||||||
MetaBackend *backend = meta_get_backend ();
|
|
||||||
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (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 (compositor->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);
|
|
||||||
}
|
|
411
src/backends/native/meta-weston-launch.c
Normal file
411
src/backends/native/meta-weston-launch.c
Normal 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);
|
||||||
|
}
|
||||||
|
|
@@ -17,21 +17,18 @@
|
|||||||
* 02111-1307, USA.
|
* 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef META_LAUNCHER_H
|
#ifndef META_WESTON_LAUNCH_H
|
||||||
#define META_LAUNCHER_H
|
#define META_WESTON_LAUNCH_H
|
||||||
|
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
|
#include "weston-launch.h"
|
||||||
|
|
||||||
typedef struct _MetaLauncher MetaLauncher;
|
typedef struct _MetaLauncher MetaLauncher;
|
||||||
|
|
||||||
MetaLauncher *meta_launcher_new (void);
|
MetaLauncher *meta_launcher_new (void);
|
||||||
void meta_launcher_free (MetaLauncher *self);
|
void meta_launcher_free (MetaLauncher *self);
|
||||||
|
|
||||||
gboolean meta_launcher_activate_session (MetaLauncher *self,
|
|
||||||
GError **error);
|
|
||||||
|
|
||||||
gboolean meta_launcher_activate_vt (MetaLauncher *self,
|
gboolean meta_launcher_activate_vt (MetaLauncher *self,
|
||||||
signed char vt,
|
signed char vt,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
#endif
|
||||||
#endif /* META_LAUNCHER_H */
|
|
711
src/backends/native/weston-launch.c
Normal file
711
src/backends/native/weston-launch.c
Normal 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;
|
||||||
|
}
|
68
src/backends/native/weston-launch.h
Normal file
68
src/backends/native/weston-launch.h
Normal 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
|
@@ -1,406 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2014 Red Hat
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
||||||
* 02111-1307, USA.
|
|
||||||
*
|
|
||||||
* Written by:
|
|
||||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include "meta-backend-x11.h"
|
|
||||||
|
|
||||||
#include <clutter/x11/clutter-x11.h>
|
|
||||||
|
|
||||||
#include <X11/extensions/sync.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;
|
|
||||||
GSource *source;
|
|
||||||
|
|
||||||
int xsync_event_base;
|
|
||||||
int xsync_error_base;
|
|
||||||
|
|
||||||
int xinput_opcode;
|
|
||||||
int xinput_event_base;
|
|
||||||
int xinput_error_base;
|
|
||||||
};
|
|
||||||
typedef struct _MetaBackendX11Private MetaBackendX11Private;
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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:
|
|
||||||
translate_device_event (x11, (XIDeviceEvent *) input_event);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
if (event->type == (priv->xsync_event_base + XSyncAlarmNotify))
|
|
||||||
handle_alarm_notify (backend, event);
|
|
||||||
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
maybe_spoof_event_as_stage_event (x11, event);
|
|
||||||
|
|
||||||
out:
|
|
||||||
if (!bypass_clutter)
|
|
||||||
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
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
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
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
MetaDisplay *display = meta_get_display ();
|
|
||||||
MetaCompositor *compositor = display->compositor;
|
|
||||||
|
|
||||||
if (compositor == NULL)
|
|
||||||
return None;
|
|
||||||
|
|
||||||
ClutterStage *stage = CLUTTER_STAGE (compositor->stage);
|
|
||||||
return clutter_x11_get_stage_window (stage);
|
|
||||||
}
|
|
@@ -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 */
|
|
@@ -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;
|
|
||||||
}
|
|
@@ -1,52 +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_X11_H
|
|
||||||
#define META_CURSOR_RENDERER_X11_H
|
|
||||||
|
|
||||||
#include "meta-cursor-renderer.h"
|
|
||||||
|
|
||||||
#define META_TYPE_CURSOR_RENDERER_X11 (meta_cursor_renderer_x11_get_type ())
|
|
||||||
#define META_CURSOR_RENDERER_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CURSOR_RENDERER_X11, MetaCursorRendererX11))
|
|
||||||
#define META_CURSOR_RENDERER_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_CURSOR_RENDERER_X11, MetaCursorRendererX11Class))
|
|
||||||
#define META_IS_CURSOR_RENDERER_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_CURSOR_RENDERER_X11))
|
|
||||||
#define META_IS_CURSOR_RENDERER_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_CURSOR_RENDERER_X11))
|
|
||||||
#define META_CURSOR_RENDERER_X11_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_CURSOR_RENDERER_X11, MetaCursorRendererX11Class))
|
|
||||||
|
|
||||||
typedef struct _MetaCursorRendererX11 MetaCursorRendererX11;
|
|
||||||
typedef struct _MetaCursorRendererX11Class MetaCursorRendererX11Class;
|
|
||||||
|
|
||||||
struct _MetaCursorRendererX11
|
|
||||||
{
|
|
||||||
MetaCursorRenderer parent;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _MetaCursorRendererX11Class
|
|
||||||
{
|
|
||||||
MetaCursorRendererClass parent_class;
|
|
||||||
};
|
|
||||||
|
|
||||||
GType meta_cursor_renderer_x11_get_type (void) G_GNUC_CONST;
|
|
||||||
|
|
||||||
#endif /* META_CURSOR_RENDERER_X11_H */
|
|
@@ -25,7 +25,8 @@
|
|||||||
#include "meta-idle-monitor-xsync.h"
|
#include "meta-idle-monitor-xsync.h"
|
||||||
#include "meta-idle-monitor-private.h"
|
#include "meta-idle-monitor-private.h"
|
||||||
|
|
||||||
#include "meta-backend-x11.h"
|
#include <meta/util.h>
|
||||||
|
#include "display-private.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -190,9 +191,10 @@ static void
|
|||||||
meta_idle_monitor_xsync_constructed (GObject *object)
|
meta_idle_monitor_xsync_constructed (GObject *object)
|
||||||
{
|
{
|
||||||
MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (object);
|
MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (object);
|
||||||
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
|
|
||||||
|
|
||||||
monitor_xsync->display = meta_backend_x11_get_xdisplay (backend);
|
g_assert (!meta_is_wayland_compositor ());
|
||||||
|
|
||||||
|
monitor_xsync->display = meta_get_display ()->xdisplay;
|
||||||
init_xsync (monitor_xsync);
|
init_xsync (monitor_xsync);
|
||||||
|
|
||||||
G_OBJECT_CLASS (meta_idle_monitor_xsync_parent_class)->constructed (object);
|
G_OBJECT_CLASS (meta_idle_monitor_xsync_parent_class)->constructed (object);
|
||||||
@@ -289,10 +291,7 @@ meta_idle_monitor_xsync_make_watch (MetaIdleMonitor *monitor,
|
|||||||
g_hash_table_add (monitor_xsync->alarms, (gpointer) watch_xsync->xalarm);
|
g_hash_table_add (monitor_xsync->alarms, (gpointer) watch_xsync->xalarm);
|
||||||
|
|
||||||
if (meta_idle_monitor_get_idletime (monitor) > (gint64)timeout_msec)
|
if (meta_idle_monitor_get_idletime (monitor) > (gint64)timeout_msec)
|
||||||
{
|
watch->idle_source_id = g_idle_add (fire_watch_idle, watch);
|
||||||
watch->idle_source_id = g_idle_add (fire_watch_idle, watch);
|
|
||||||
g_source_set_name_by_id (watch->idle_source_id, "[mutter] fire_watch_idle");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@@ -44,4 +44,6 @@ GType meta_idle_monitor_xsync_get_type (void);
|
|||||||
void meta_idle_monitor_xsync_handle_xevent (MetaIdleMonitor *monitor,
|
void meta_idle_monitor_xsync_handle_xevent (MetaIdleMonitor *monitor,
|
||||||
XSyncAlarmNotifyEvent *xevent);
|
XSyncAlarmNotifyEvent *xevent);
|
||||||
|
|
||||||
|
void meta_idle_monitor_xsync_handle_xevent_all (XEvent *xevent);
|
||||||
|
|
||||||
#endif /* META_IDLE_MONITOR_XSYNC_H */
|
#endif /* META_IDLE_MONITOR_XSYNC_H */
|
||||||
|
@@ -36,7 +36,6 @@
|
|||||||
#include <X11/extensions/Xrandr.h>
|
#include <X11/extensions/Xrandr.h>
|
||||||
#include <X11/extensions/dpms.h>
|
#include <X11/extensions/dpms.h>
|
||||||
|
|
||||||
#include "meta-backend-x11.h"
|
|
||||||
#include <meta/main.h>
|
#include <meta/main.h>
|
||||||
#include <meta/errors.h>
|
#include <meta/errors.h>
|
||||||
#include "edid.h"
|
#include "edid.h"
|
||||||
@@ -142,16 +141,16 @@ static gboolean
|
|||||||
output_get_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
output_get_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||||
MetaOutput *output)
|
MetaOutput *output)
|
||||||
{
|
{
|
||||||
|
MetaDisplay *display = meta_get_display ();
|
||||||
gboolean value;
|
gboolean value;
|
||||||
Atom atom, actual_type;
|
Atom actual_type;
|
||||||
int actual_format;
|
int actual_format;
|
||||||
unsigned long nitems, bytes_after;
|
unsigned long nitems, bytes_after;
|
||||||
unsigned char *buffer;
|
unsigned char *buffer;
|
||||||
|
|
||||||
atom = XInternAtom (manager_xrandr->xdisplay, "_MUTTER_PRESENTATION_OUTPUT", False);
|
|
||||||
XRRGetOutputProperty (manager_xrandr->xdisplay,
|
XRRGetOutputProperty (manager_xrandr->xdisplay,
|
||||||
(XID)output->output_id,
|
(XID)output->output_id,
|
||||||
atom,
|
display->atom__MUTTER_PRESENTATION_OUTPUT,
|
||||||
0, G_MAXLONG, False, False, XA_CARDINAL,
|
0, G_MAXLONG, False, False, XA_CARDINAL,
|
||||||
&actual_type, &actual_format,
|
&actual_type, &actual_format,
|
||||||
&nitems, &bytes_after, &buffer);
|
&nitems, &bytes_after, &buffer);
|
||||||
@@ -178,16 +177,16 @@ static int
|
|||||||
output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||||
MetaOutput *output)
|
MetaOutput *output)
|
||||||
{
|
{
|
||||||
|
MetaDisplay *display = meta_get_display ();
|
||||||
gboolean value;
|
gboolean value;
|
||||||
Atom atom, actual_type;
|
Atom actual_type;
|
||||||
int actual_format;
|
int actual_format;
|
||||||
unsigned long nitems, bytes_after;
|
unsigned long nitems, bytes_after;
|
||||||
unsigned char *buffer;
|
unsigned char *buffer;
|
||||||
|
|
||||||
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
|
|
||||||
XRRGetOutputProperty (manager_xrandr->xdisplay,
|
XRRGetOutputProperty (manager_xrandr->xdisplay,
|
||||||
(XID)output->output_id,
|
(XID)output->output_id,
|
||||||
atom,
|
display->atom_BACKLIGHT,
|
||||||
0, G_MAXLONG, False, False, XA_INTEGER,
|
0, G_MAXLONG, False, False, XA_INTEGER,
|
||||||
&actual_type, &actual_format,
|
&actual_type, &actual_format,
|
||||||
&nitems, &bytes_after, &buffer);
|
&nitems, &bytes_after, &buffer);
|
||||||
@@ -206,13 +205,14 @@ static void
|
|||||||
output_get_backlight_limits_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
output_get_backlight_limits_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||||
MetaOutput *output)
|
MetaOutput *output)
|
||||||
{
|
{
|
||||||
Atom atom;
|
MetaDisplay *display = meta_get_display ();
|
||||||
XRRPropertyInfo *info;
|
XRRPropertyInfo *info;
|
||||||
|
|
||||||
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
|
meta_error_trap_push (display);
|
||||||
info = XRRQueryOutputProperty (manager_xrandr->xdisplay,
|
info = XRRQueryOutputProperty (manager_xrandr->xdisplay,
|
||||||
(XID)output->output_id,
|
(XID)output->output_id,
|
||||||
atom);
|
display->atom_BACKLIGHT);
|
||||||
|
meta_error_trap_pop (display);
|
||||||
|
|
||||||
if (info == NULL)
|
if (info == NULL)
|
||||||
{
|
{
|
||||||
@@ -314,13 +314,14 @@ static gboolean
|
|||||||
output_get_hotplug_mode_update (MetaMonitorManagerXrandr *manager_xrandr,
|
output_get_hotplug_mode_update (MetaMonitorManagerXrandr *manager_xrandr,
|
||||||
XID output_id)
|
XID output_id)
|
||||||
{
|
{
|
||||||
Atom atom;
|
MetaDisplay *display = meta_get_display ();
|
||||||
XRRPropertyInfo *info;
|
XRRPropertyInfo *info;
|
||||||
gboolean result = FALSE;
|
gboolean result = FALSE;
|
||||||
|
|
||||||
atom = XInternAtom (manager_xrandr->xdisplay, "hotplug_mode_update", False);
|
meta_error_trap_push (display);
|
||||||
info = XRRQueryOutputProperty (manager_xrandr->xdisplay, output_id,
|
info = XRRQueryOutputProperty (manager_xrandr->xdisplay, output_id,
|
||||||
atom);
|
display->atom_hotplug_mode_update);
|
||||||
|
meta_error_trap_pop (display);
|
||||||
|
|
||||||
if (info)
|
if (info)
|
||||||
{
|
{
|
||||||
@@ -349,7 +350,9 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
|||||||
XRRFreeScreenResources (manager_xrandr->resources);
|
XRRFreeScreenResources (manager_xrandr->resources);
|
||||||
manager_xrandr->resources = NULL;
|
manager_xrandr->resources = NULL;
|
||||||
|
|
||||||
|
meta_error_trap_push (meta_get_display ());
|
||||||
dpms_capable = DPMSCapable (manager_xrandr->xdisplay);
|
dpms_capable = DPMSCapable (manager_xrandr->xdisplay);
|
||||||
|
meta_error_trap_pop (meta_get_display ());
|
||||||
|
|
||||||
if (dpms_capable &&
|
if (dpms_capable &&
|
||||||
DPMSInfo (manager_xrandr->xdisplay, &dpms_state, &dpms_enabled) &&
|
DPMSInfo (manager_xrandr->xdisplay, &dpms_state, &dpms_enabled) &&
|
||||||
@@ -449,8 +452,10 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
|||||||
XRRFreeCrtcInfo (crtc);
|
XRRFreeCrtcInfo (crtc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
meta_error_trap_push (meta_get_display ());
|
||||||
primary_output = XRRGetOutputPrimary (manager_xrandr->xdisplay,
|
primary_output = XRRGetOutputPrimary (manager_xrandr->xdisplay,
|
||||||
DefaultRootWindow (manager_xrandr->xdisplay));
|
DefaultRootWindow (manager_xrandr->xdisplay));
|
||||||
|
meta_error_trap_pop (meta_get_display ());
|
||||||
|
|
||||||
n_actual_outputs = 0;
|
n_actual_outputs = 0;
|
||||||
for (i = 0; i < (unsigned)resources->noutput; i++)
|
for (i = 0; i < (unsigned)resources->noutput; i++)
|
||||||
@@ -632,8 +637,10 @@ meta_monitor_manager_xrandr_set_power_save_mode (MetaMonitorManager *manager,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
meta_error_trap_push (meta_get_display ());
|
||||||
DPMSForceLevel (manager_xrandr->xdisplay, state);
|
DPMSForceLevel (manager_xrandr->xdisplay, state);
|
||||||
DPMSSetTimeouts (manager_xrandr->xdisplay, 0, 0, 0);
|
DPMSSetTimeouts (manager_xrandr->xdisplay, 0, 0, 0);
|
||||||
|
meta_error_trap_pop (meta_get_display ());
|
||||||
}
|
}
|
||||||
|
|
||||||
static Rotation
|
static Rotation
|
||||||
@@ -667,13 +674,12 @@ output_set_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
|||||||
MetaOutput *output,
|
MetaOutput *output,
|
||||||
gboolean presentation)
|
gboolean presentation)
|
||||||
{
|
{
|
||||||
Atom atom;
|
MetaDisplay *display = meta_get_display ();
|
||||||
int value = presentation;
|
int value = presentation;
|
||||||
|
|
||||||
atom = XInternAtom (manager_xrandr->xdisplay, "_MUTTER_PRESENTATION_OUTPUT", False);
|
|
||||||
XRRChangeOutputProperty (manager_xrandr->xdisplay,
|
XRRChangeOutputProperty (manager_xrandr->xdisplay,
|
||||||
(XID)output->output_id,
|
(XID)output->output_id,
|
||||||
atom,
|
display->atom__MUTTER_PRESENTATION_OUTPUT,
|
||||||
XA_CARDINAL, 32, PropModeReplace,
|
XA_CARDINAL, 32, PropModeReplace,
|
||||||
(unsigned char*) &value, 1);
|
(unsigned char*) &value, 1);
|
||||||
}
|
}
|
||||||
@@ -686,10 +692,11 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
|||||||
unsigned int n_outputs)
|
unsigned int n_outputs)
|
||||||
{
|
{
|
||||||
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
|
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
|
||||||
|
MetaDisplay *display = meta_get_display ();
|
||||||
unsigned i;
|
unsigned i;
|
||||||
int width, height, width_mm, height_mm;
|
int width, height, width_mm, height_mm;
|
||||||
|
|
||||||
XGrabServer (manager_xrandr->xdisplay);
|
meta_display_grab (display);
|
||||||
|
|
||||||
/* First compute the new size of the screen (framebuffer) */
|
/* First compute the new size of the screen (framebuffer) */
|
||||||
width = 0; height = 0;
|
width = 0; height = 0;
|
||||||
@@ -783,8 +790,10 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
|||||||
*/
|
*/
|
||||||
width_mm = (width / DPI_FALLBACK) * 25.4 + 0.5;
|
width_mm = (width / DPI_FALLBACK) * 25.4 + 0.5;
|
||||||
height_mm = (height / DPI_FALLBACK) * 25.4 + 0.5;
|
height_mm = (height / DPI_FALLBACK) * 25.4 + 0.5;
|
||||||
|
meta_error_trap_push (display);
|
||||||
XRRSetScreenSize (manager_xrandr->xdisplay, DefaultRootWindow (manager_xrandr->xdisplay),
|
XRRSetScreenSize (manager_xrandr->xdisplay, DefaultRootWindow (manager_xrandr->xdisplay),
|
||||||
width, height, width_mm, height_mm);
|
width, height, width_mm, height_mm);
|
||||||
|
meta_error_trap_pop (display);
|
||||||
|
|
||||||
for (i = 0; i < n_crtcs; i++)
|
for (i = 0; i < n_crtcs; i++)
|
||||||
{
|
{
|
||||||
@@ -841,6 +850,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
|||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
meta_error_trap_push (display);
|
||||||
ok = XRRSetCrtcConfig (manager_xrandr->xdisplay,
|
ok = XRRSetCrtcConfig (manager_xrandr->xdisplay,
|
||||||
manager_xrandr->resources,
|
manager_xrandr->resources,
|
||||||
(XID)crtc->crtc_id,
|
(XID)crtc->crtc_id,
|
||||||
@@ -849,6 +859,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
|||||||
(XID)mode->mode_id,
|
(XID)mode->mode_id,
|
||||||
wl_transform_to_xrandr (crtc_info->transform),
|
wl_transform_to_xrandr (crtc_info->transform),
|
||||||
outputs, n_outputs);
|
outputs, n_outputs);
|
||||||
|
meta_error_trap_pop (display);
|
||||||
|
|
||||||
if (ok != Success)
|
if (ok != Success)
|
||||||
{
|
{
|
||||||
@@ -889,9 +900,11 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
|||||||
|
|
||||||
if (output_info->is_primary)
|
if (output_info->is_primary)
|
||||||
{
|
{
|
||||||
|
meta_error_trap_push (display);
|
||||||
XRRSetOutputPrimary (manager_xrandr->xdisplay,
|
XRRSetOutputPrimary (manager_xrandr->xdisplay,
|
||||||
DefaultRootWindow (manager_xrandr->xdisplay),
|
DefaultRootWindow (manager_xrandr->xdisplay),
|
||||||
(XID)output_info->output->output_id);
|
(XID)output_info->output->output_id);
|
||||||
|
meta_error_trap_pop (display);
|
||||||
}
|
}
|
||||||
|
|
||||||
output_set_presentation_xrandr (manager_xrandr,
|
output_set_presentation_xrandr (manager_xrandr,
|
||||||
@@ -917,8 +930,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
|||||||
output->is_primary = FALSE;
|
output->is_primary = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
XUngrabServer (manager_xrandr->xdisplay);
|
meta_display_ungrab (display);
|
||||||
XFlush (manager_xrandr->xdisplay);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -927,17 +939,18 @@ meta_monitor_manager_xrandr_change_backlight (MetaMonitorManager *manager,
|
|||||||
gint value)
|
gint value)
|
||||||
{
|
{
|
||||||
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
|
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
|
||||||
Atom atom;
|
MetaDisplay *display = meta_get_display ();
|
||||||
int hw_value;
|
int hw_value;
|
||||||
|
|
||||||
hw_value = round ((double)value / 100.0 * output->backlight_max + output->backlight_min);
|
hw_value = round ((double)value / 100.0 * output->backlight_max + output->backlight_min);
|
||||||
|
|
||||||
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
|
meta_error_trap_push (display);
|
||||||
XRRChangeOutputProperty (manager_xrandr->xdisplay,
|
XRRChangeOutputProperty (manager_xrandr->xdisplay,
|
||||||
(XID)output->output_id,
|
(XID)output->output_id,
|
||||||
atom,
|
display->atom_BACKLIGHT,
|
||||||
XA_INTEGER, 32, PropModeReplace,
|
XA_INTEGER, 32, PropModeReplace,
|
||||||
(unsigned char *) &hw_value, 1);
|
(unsigned char *) &hw_value, 1);
|
||||||
|
meta_error_trap_pop (display);
|
||||||
|
|
||||||
/* We're not selecting for property notifies, so update the value immediately */
|
/* We're not selecting for property notifies, so update the value immediately */
|
||||||
output->backlight = normalize_backlight (output, hw_value);
|
output->backlight = normalize_backlight (output, hw_value);
|
||||||
@@ -995,65 +1008,11 @@ meta_monitor_manager_xrandr_rebuild_derived (MetaMonitorManager *manager)
|
|||||||
meta_monitor_manager_rebuild_derived (manager);
|
meta_monitor_manager_rebuild_derived (manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static gboolean
|
||||||
meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr)
|
meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManager *manager,
|
||||||
|
XEvent *event)
|
||||||
{
|
{
|
||||||
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
|
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
|
||||||
|
|
||||||
manager_xrandr->xdisplay = meta_backend_x11_get_xdisplay (backend);
|
|
||||||
|
|
||||||
if (!XRRQueryExtension (manager_xrandr->xdisplay,
|
|
||||||
&manager_xrandr->rr_event_base,
|
|
||||||
&manager_xrandr->rr_error_base))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* We only use ScreenChangeNotify, but GDK uses the others,
|
|
||||||
and we don't want to step on its toes */
|
|
||||||
XRRSelectInput (manager_xrandr->xdisplay,
|
|
||||||
DefaultRootWindow (manager_xrandr->xdisplay),
|
|
||||||
RRScreenChangeNotifyMask
|
|
||||||
| RRCrtcChangeNotifyMask
|
|
||||||
| RROutputPropertyNotifyMask);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_monitor_manager_xrandr_finalize (GObject *object)
|
|
||||||
{
|
|
||||||
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (object);
|
|
||||||
|
|
||||||
if (manager_xrandr->resources)
|
|
||||||
XRRFreeScreenResources (manager_xrandr->resources);
|
|
||||||
manager_xrandr->resources = NULL;
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (meta_monitor_manager_xrandr_parent_class)->finalize (object);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass)
|
|
||||||
{
|
|
||||||
MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass);
|
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
||||||
|
|
||||||
object_class->finalize = meta_monitor_manager_xrandr_finalize;
|
|
||||||
|
|
||||||
manager_class->read_current = meta_monitor_manager_xrandr_read_current;
|
|
||||||
manager_class->read_edid = meta_monitor_manager_xrandr_read_edid;
|
|
||||||
manager_class->apply_configuration = meta_monitor_manager_xrandr_apply_configuration;
|
|
||||||
manager_class->set_power_save_mode = meta_monitor_manager_xrandr_set_power_save_mode;
|
|
||||||
manager_class->change_backlight = meta_monitor_manager_xrandr_change_backlight;
|
|
||||||
manager_class->get_crtc_gamma = meta_monitor_manager_xrandr_get_crtc_gamma;
|
|
||||||
manager_class->set_crtc_gamma = meta_monitor_manager_xrandr_set_crtc_gamma;
|
|
||||||
}
|
|
||||||
|
|
||||||
gboolean
|
|
||||||
meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xrandr,
|
|
||||||
XEvent *event)
|
|
||||||
{
|
|
||||||
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr);
|
|
||||||
MetaOutput *old_outputs;
|
MetaOutput *old_outputs;
|
||||||
MetaCRTC *old_crtcs;
|
MetaCRTC *old_crtcs;
|
||||||
MetaMonitorMode *old_modes;
|
MetaMonitorMode *old_modes;
|
||||||
@@ -1114,3 +1073,59 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra
|
|||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr)
|
||||||
|
{
|
||||||
|
MetaDisplay *display = meta_get_display ();
|
||||||
|
|
||||||
|
manager_xrandr->xdisplay = display->xdisplay;
|
||||||
|
|
||||||
|
if (!XRRQueryExtension (manager_xrandr->xdisplay,
|
||||||
|
&manager_xrandr->rr_event_base,
|
||||||
|
&manager_xrandr->rr_error_base))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* We only use ScreenChangeNotify, but GDK uses the others,
|
||||||
|
and we don't want to step on its toes */
|
||||||
|
XRRSelectInput (manager_xrandr->xdisplay,
|
||||||
|
DefaultRootWindow (manager_xrandr->xdisplay),
|
||||||
|
RRScreenChangeNotifyMask
|
||||||
|
| RRCrtcChangeNotifyMask
|
||||||
|
| RROutputPropertyNotifyMask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_monitor_manager_xrandr_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (object);
|
||||||
|
|
||||||
|
if (manager_xrandr->resources)
|
||||||
|
XRRFreeScreenResources (manager_xrandr->resources);
|
||||||
|
manager_xrandr->resources = NULL;
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (meta_monitor_manager_xrandr_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass)
|
||||||
|
{
|
||||||
|
MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass);
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->finalize = meta_monitor_manager_xrandr_finalize;
|
||||||
|
|
||||||
|
manager_class->read_current = meta_monitor_manager_xrandr_read_current;
|
||||||
|
manager_class->read_edid = meta_monitor_manager_xrandr_read_edid;
|
||||||
|
manager_class->apply_configuration = meta_monitor_manager_xrandr_apply_configuration;
|
||||||
|
manager_class->set_power_save_mode = meta_monitor_manager_xrandr_set_power_save_mode;
|
||||||
|
manager_class->change_backlight = meta_monitor_manager_xrandr_change_backlight;
|
||||||
|
manager_class->get_crtc_gamma = meta_monitor_manager_xrandr_get_crtc_gamma;
|
||||||
|
manager_class->set_crtc_gamma = meta_monitor_manager_xrandr_set_crtc_gamma;
|
||||||
|
manager_class->handle_xevent = meta_monitor_manager_xrandr_handle_xevent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -37,7 +37,4 @@ typedef struct _MetaMonitorManagerXrandr MetaMonitorManagerXrandr;
|
|||||||
|
|
||||||
GType meta_monitor_manager_xrandr_get_type (void);
|
GType meta_monitor_manager_xrandr_get_type (void);
|
||||||
|
|
||||||
gboolean meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager,
|
|
||||||
XEvent *event);
|
|
||||||
|
|
||||||
#endif /* META_MONITOR_MANAGER_XRANDR_H */
|
#endif /* META_MONITOR_MANAGER_XRANDR_H */
|
||||||
|
@@ -72,7 +72,6 @@
|
|||||||
#include <meta/meta-shadow-factory.h>
|
#include <meta/meta-shadow-factory.h>
|
||||||
#include "meta-window-actor-private.h"
|
#include "meta-window-actor-private.h"
|
||||||
#include "meta-window-group.h"
|
#include "meta-window-group.h"
|
||||||
#include "meta-stage.h"
|
|
||||||
#include "window-private.h" /* to check window->hidden */
|
#include "window-private.h" /* to check window->hidden */
|
||||||
#include "display-private.h" /* for meta_display_lookup_x_window() */
|
#include "display-private.h" /* for meta_display_lookup_x_window() */
|
||||||
#include "util-private.h"
|
#include "util-private.h"
|
||||||
@@ -80,9 +79,6 @@
|
|||||||
#include <X11/extensions/shape.h>
|
#include <X11/extensions/shape.h>
|
||||||
#include <X11/extensions/Xcomposite.h>
|
#include <X11/extensions/Xcomposite.h>
|
||||||
|
|
||||||
#include "backends/meta-backend.h"
|
|
||||||
#include "backends/x11/meta-backend-x11.h"
|
|
||||||
|
|
||||||
#include "wayland/meta-wayland-private.h"
|
#include "wayland/meta-wayland-private.h"
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@@ -151,13 +147,16 @@ process_damage (MetaCompositor *compositor,
|
|||||||
static Window
|
static Window
|
||||||
get_output_window (MetaCompositor *compositor)
|
get_output_window (MetaCompositor *compositor)
|
||||||
{
|
{
|
||||||
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
|
MetaDisplay *display = compositor->display;
|
||||||
Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
|
Display *xdisplay = display->xdisplay;
|
||||||
Window output;
|
Window output, xroot;
|
||||||
|
XWindowAttributes attr;
|
||||||
|
long event_mask;
|
||||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||||
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||||
|
|
||||||
output = XCompositeGetOverlayWindow (xdisplay, DefaultRootWindow (xdisplay));
|
xroot = display->screen->xroot;
|
||||||
|
output = XCompositeGetOverlayWindow (xdisplay, xroot);
|
||||||
|
|
||||||
meta_core_add_old_event_mask (xdisplay, output, &mask);
|
meta_core_add_old_event_mask (xdisplay, output, &mask);
|
||||||
|
|
||||||
@@ -172,6 +171,12 @@ get_output_window (MetaCompositor *compositor)
|
|||||||
XISetMask (mask.mask, XI_Motion);
|
XISetMask (mask.mask, XI_Motion);
|
||||||
XISelectEvents (xdisplay, output, &mask, 1);
|
XISelectEvents (xdisplay, output, &mask, 1);
|
||||||
|
|
||||||
|
event_mask = ExposureMask | PropertyChangeMask;
|
||||||
|
if (XGetWindowAttributes (xdisplay, output, &attr))
|
||||||
|
event_mask |= attr.your_event_mask;
|
||||||
|
|
||||||
|
XSelectInput (xdisplay, output, event_mask);
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,16 +327,38 @@ meta_stage_is_focused (MetaScreen *screen)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
grab_devices (MetaModalOptions options,
|
begin_modal_x11 (MetaCompositor *compositor,
|
||||||
guint32 timestamp)
|
MetaPlugin *plugin,
|
||||||
|
MetaModalOptions options,
|
||||||
|
guint32 timestamp)
|
||||||
{
|
{
|
||||||
MetaBackend *backend = META_BACKEND (meta_get_backend ());
|
MetaDisplay *display = compositor->display;
|
||||||
gboolean pointer_grabbed = FALSE;
|
Display *xdpy = meta_display_get_xdisplay (display);
|
||||||
gboolean keyboard_grabbed = FALSE;
|
Window grab_window = clutter_x11_get_stage_window (CLUTTER_STAGE (compositor->stage));
|
||||||
|
int result;
|
||||||
|
gboolean pointer_grabbed = FALSE;
|
||||||
|
gboolean keyboard_grabbed = FALSE;
|
||||||
|
|
||||||
if ((options & META_MODAL_POINTER_ALREADY_GRABBED) == 0)
|
if ((options & META_MODAL_POINTER_ALREADY_GRABBED) == 0)
|
||||||
{
|
{
|
||||||
if (!meta_backend_grab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp))
|
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||||
|
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||||
|
|
||||||
|
XISetMask (mask.mask, XI_ButtonPress);
|
||||||
|
XISetMask (mask.mask, XI_ButtonRelease);
|
||||||
|
XISetMask (mask.mask, XI_Enter);
|
||||||
|
XISetMask (mask.mask, XI_Leave);
|
||||||
|
XISetMask (mask.mask, XI_Motion);
|
||||||
|
|
||||||
|
result = XIGrabDevice (xdpy,
|
||||||
|
META_VIRTUAL_CORE_POINTER_ID,
|
||||||
|
grab_window,
|
||||||
|
timestamp,
|
||||||
|
None,
|
||||||
|
XIGrabModeAsync, XIGrabModeAsync,
|
||||||
|
False, /* owner_events */
|
||||||
|
&mask);
|
||||||
|
if (result != Success)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
pointer_grabbed = TRUE;
|
pointer_grabbed = TRUE;
|
||||||
@@ -339,7 +366,22 @@ grab_devices (MetaModalOptions options,
|
|||||||
|
|
||||||
if ((options & META_MODAL_KEYBOARD_ALREADY_GRABBED) == 0)
|
if ((options & META_MODAL_KEYBOARD_ALREADY_GRABBED) == 0)
|
||||||
{
|
{
|
||||||
if (!meta_backend_grab_device (backend, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp))
|
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);
|
||||||
|
|
||||||
|
result = XIGrabDevice (xdpy,
|
||||||
|
META_VIRTUAL_CORE_KEYBOARD_ID,
|
||||||
|
grab_window,
|
||||||
|
timestamp,
|
||||||
|
None,
|
||||||
|
XIGrabModeAsync, XIGrabModeAsync,
|
||||||
|
False, /* owner_events */
|
||||||
|
&mask);
|
||||||
|
|
||||||
|
if (result != Success)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
keyboard_grabbed = TRUE;
|
keyboard_grabbed = TRUE;
|
||||||
@@ -349,9 +391,9 @@ grab_devices (MetaModalOptions options,
|
|||||||
|
|
||||||
fail:
|
fail:
|
||||||
if (pointer_grabbed)
|
if (pointer_grabbed)
|
||||||
meta_backend_ungrab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp);
|
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_POINTER_ID, timestamp);
|
||||||
if (keyboard_grabbed)
|
if (keyboard_grabbed)
|
||||||
meta_backend_ungrab_device (backend, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
|
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@@ -371,14 +413,9 @@ meta_begin_modal_for_plugin (MetaCompositor *compositor,
|
|||||||
if (is_modal (display) || display->grab_op != META_GRAB_OP_NONE)
|
if (is_modal (display) || display->grab_op != META_GRAB_OP_NONE)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* XXX: why is this needed? */
|
if (!meta_is_wayland_compositor ())
|
||||||
XIUngrabDevice (display->xdisplay,
|
if (!begin_modal_x11 (compositor, plugin, options, timestamp))
|
||||||
META_VIRTUAL_CORE_POINTER_ID,
|
return FALSE;
|
||||||
timestamp);
|
|
||||||
XSync (display->xdisplay, False);
|
|
||||||
|
|
||||||
if (!grab_devices (options, timestamp))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
display->grab_op = META_GRAB_OP_COMPOSITOR;
|
display->grab_op = META_GRAB_OP_COMPOSITOR;
|
||||||
display->grab_window = NULL;
|
display->grab_window = NULL;
|
||||||
@@ -397,7 +434,7 @@ meta_end_modal_for_plugin (MetaCompositor *compositor,
|
|||||||
guint32 timestamp)
|
guint32 timestamp)
|
||||||
{
|
{
|
||||||
MetaDisplay *display = compositor->display;
|
MetaDisplay *display = compositor->display;
|
||||||
MetaBackend *backend = meta_get_backend ();
|
Display *xdpy = meta_display_get_xdisplay (display);
|
||||||
|
|
||||||
g_return_if_fail (is_modal (display));
|
g_return_if_fail (is_modal (display));
|
||||||
|
|
||||||
@@ -406,11 +443,15 @@ meta_end_modal_for_plugin (MetaCompositor *compositor,
|
|||||||
display->grab_have_pointer = FALSE;
|
display->grab_have_pointer = FALSE;
|
||||||
display->grab_have_keyboard = FALSE;
|
display->grab_have_keyboard = FALSE;
|
||||||
|
|
||||||
meta_backend_ungrab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp);
|
|
||||||
meta_backend_ungrab_device (backend, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
|
|
||||||
|
|
||||||
if (meta_is_wayland_compositor ())
|
if (meta_is_wayland_compositor ())
|
||||||
meta_display_sync_wayland_input_focus (display);
|
{
|
||||||
|
meta_display_sync_wayland_input_focus (display);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_POINTER_ID, timestamp);
|
||||||
|
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -450,7 +491,7 @@ redirect_windows (MetaScreen *screen)
|
|||||||
*/
|
*/
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
meta_error_trap_push (display);
|
meta_error_trap_push_with_return (display);
|
||||||
XCompositeRedirectSubwindows (xdisplay, xroot, CompositeRedirectManual);
|
XCompositeRedirectSubwindows (xdisplay, xroot, CompositeRedirectManual);
|
||||||
XSync (xdisplay, FALSE);
|
XSync (xdisplay, FALSE);
|
||||||
|
|
||||||
@@ -478,17 +519,16 @@ meta_compositor_manage (MetaCompositor *compositor)
|
|||||||
MetaScreen *screen = display->screen;
|
MetaScreen *screen = display->screen;
|
||||||
Window xwin = 0;
|
Window xwin = 0;
|
||||||
gint width, height;
|
gint width, height;
|
||||||
|
MetaWaylandCompositor *wayland_compositor;
|
||||||
|
|
||||||
meta_screen_set_cm_selection (display->screen);
|
meta_screen_set_cm_selection (display->screen);
|
||||||
|
|
||||||
|
/* We will have already created a stage if running as a wayland
|
||||||
|
* compositor... */
|
||||||
if (meta_is_wayland_compositor ())
|
if (meta_is_wayland_compositor ())
|
||||||
{
|
{
|
||||||
MetaWaylandCompositor *wayland_compositor = meta_wayland_compositor_get_default ();
|
wayland_compositor = meta_wayland_compositor_get_default ();
|
||||||
|
compositor->stage = wayland_compositor->stage;
|
||||||
compositor->stage = meta_stage_new ();
|
|
||||||
clutter_actor_show (compositor->stage);
|
|
||||||
|
|
||||||
wayland_compositor->stage = compositor->stage;
|
|
||||||
|
|
||||||
meta_screen_get_size (screen, &width, &height);
|
meta_screen_get_size (screen, &width, &height);
|
||||||
clutter_actor_set_size (compositor->stage, width, height);
|
clutter_actor_set_size (compositor->stage, width, height);
|
||||||
@@ -505,12 +545,12 @@ meta_compositor_manage (MetaCompositor *compositor)
|
|||||||
XResizeWindow (xdisplay, xwin, width, height);
|
XResizeWindow (xdisplay, xwin, width, height);
|
||||||
|
|
||||||
{
|
{
|
||||||
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
|
long event_mask;
|
||||||
Display *backend_xdisplay = meta_backend_x11_get_xdisplay (backend);
|
|
||||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||||
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||||
|
XWindowAttributes attr;
|
||||||
|
|
||||||
meta_core_add_old_event_mask (backend_xdisplay, xwin, &mask);
|
meta_core_add_old_event_mask (xdisplay, xwin, &mask);
|
||||||
|
|
||||||
XISetMask (mask.mask, XI_KeyPress);
|
XISetMask (mask.mask, XI_KeyPress);
|
||||||
XISetMask (mask.mask, XI_KeyRelease);
|
XISetMask (mask.mask, XI_KeyRelease);
|
||||||
@@ -524,7 +564,13 @@ meta_compositor_manage (MetaCompositor *compositor)
|
|||||||
XIClearMask (mask.mask, XI_TouchBegin);
|
XIClearMask (mask.mask, XI_TouchBegin);
|
||||||
XIClearMask (mask.mask, XI_TouchEnd);
|
XIClearMask (mask.mask, XI_TouchEnd);
|
||||||
XIClearMask (mask.mask, XI_TouchUpdate);
|
XIClearMask (mask.mask, XI_TouchUpdate);
|
||||||
XISelectEvents (backend_xdisplay, xwin, &mask, 1);
|
XISelectEvents (xdisplay, xwin, &mask, 1);
|
||||||
|
|
||||||
|
event_mask = ExposureMask | PropertyChangeMask | StructureNotifyMask;
|
||||||
|
if (XGetWindowAttributes (xdisplay, xwin, &attr))
|
||||||
|
event_mask |= attr.your_event_mask;
|
||||||
|
|
||||||
|
XSelectInput (xdisplay, xwin, event_mask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -708,6 +754,29 @@ meta_compositor_queue_frame_drawn (MetaCompositor *compositor,
|
|||||||
meta_window_actor_queue_frame_drawn (window_actor, no_delay_frame);
|
meta_window_actor_queue_frame_drawn (window_actor, no_delay_frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
is_grabbed_event (MetaDisplay *display,
|
||||||
|
XEvent *event)
|
||||||
|
{
|
||||||
|
if (event->type == GenericEvent &&
|
||||||
|
event->xcookie.extension == display->xinput_opcode)
|
||||||
|
{
|
||||||
|
XIEvent *xev = (XIEvent *) event->xcookie.data;
|
||||||
|
|
||||||
|
switch (xev->evtype)
|
||||||
|
{
|
||||||
|
case XI_Motion:
|
||||||
|
case XI_ButtonPress:
|
||||||
|
case XI_ButtonRelease:
|
||||||
|
case XI_KeyPress:
|
||||||
|
case XI_KeyRelease:
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_compositor_window_shape_changed (MetaCompositor *compositor,
|
meta_compositor_window_shape_changed (MetaCompositor *compositor,
|
||||||
MetaWindow *window)
|
MetaWindow *window)
|
||||||
@@ -744,6 +813,82 @@ meta_compositor_window_surface_changed (MetaCompositor *compositor,
|
|||||||
meta_window_actor_update_surface (window_actor);
|
meta_window_actor_update_surface (window_actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
event_is_passive_button_grab (MetaDisplay *display,
|
||||||
|
XIDeviceEvent *device_event)
|
||||||
|
{
|
||||||
|
/* see display.c for which events are passive button
|
||||||
|
grabs (meta_display_grab_window_buttons() and
|
||||||
|
meta_display_handle_events())
|
||||||
|
we need to filter them here because normally they
|
||||||
|
would be sent to gtk+ (they are on gtk+ frame xwindow),
|
||||||
|
but we want to redirect them to clutter
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (device_event->evtype != XI_ButtonPress)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (display->window_grab_modifiers == 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if ((device_event->mods.effective & display->window_grab_modifiers) !=
|
||||||
|
display->window_grab_modifiers)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return device_event->detail < 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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 (MetaCompositor *compositor,
|
||||||
|
MetaWindow *window,
|
||||||
|
XEvent *event)
|
||||||
|
{
|
||||||
|
MetaDisplay *display = compositor->display;
|
||||||
|
|
||||||
|
if (event->type == GenericEvent &&
|
||||||
|
event->xcookie.extension == display->xinput_opcode)
|
||||||
|
{
|
||||||
|
XIEvent *input_event = (XIEvent *) event->xcookie.data;
|
||||||
|
XIDeviceEvent *device_event = ((XIDeviceEvent *) input_event);
|
||||||
|
|
||||||
|
switch (input_event->evtype)
|
||||||
|
{
|
||||||
|
case XI_Motion:
|
||||||
|
case XI_ButtonPress:
|
||||||
|
case XI_ButtonRelease:
|
||||||
|
/* If this is a window frame, and we think GTK+ needs to handle the event,
|
||||||
|
let GTK+ handle it without mangling */
|
||||||
|
if (window && window->frame && device_event->event == window->frame->xwindow &&
|
||||||
|
(meta_grab_op_is_clicking (display->grab_op) ||
|
||||||
|
(display->grab_op == META_GRAB_OP_NONE && !event_is_passive_button_grab (display, device_event))))
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XI_KeyPress:
|
||||||
|
case XI_KeyRelease:
|
||||||
|
/* If this is a GTK+ widget, like a window menu, let GTK+ handle
|
||||||
|
* it as-is without mangling. */
|
||||||
|
if (meta_ui_window_is_widget (display->screen->ui, device_event->event))
|
||||||
|
break;
|
||||||
|
|
||||||
|
device_event->event = clutter_x11_get_stage_window (CLUTTER_STAGE (compositor->stage));
|
||||||
|
device_event->event_x = device_event->root_x;
|
||||||
|
device_event->event_y = device_event->root_y;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* meta_compositor_process_event: (skip)
|
* meta_compositor_process_event: (skip)
|
||||||
* @compositor:
|
* @compositor:
|
||||||
@@ -756,6 +901,20 @@ meta_compositor_process_event (MetaCompositor *compositor,
|
|||||||
XEvent *event,
|
XEvent *event,
|
||||||
MetaWindow *window)
|
MetaWindow *window)
|
||||||
{
|
{
|
||||||
|
MetaDisplay *display = compositor->display;
|
||||||
|
|
||||||
|
if (is_modal (display) && is_grabbed_event (display, event))
|
||||||
|
{
|
||||||
|
meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event);
|
||||||
|
|
||||||
|
/* We always consume events even if the plugin says it didn't handle them;
|
||||||
|
* exclusive is exclusive */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!meta_is_wayland_compositor ())
|
||||||
|
maybe_spoof_event_as_stage_event (compositor, window, event);
|
||||||
|
|
||||||
if (meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event))
|
if (meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
@@ -1356,13 +1515,3 @@ meta_compositor_hide_tile_preview (MetaCompositor *compositor)
|
|||||||
{
|
{
|
||||||
meta_plugin_manager_hide_tile_preview (compositor->plugin_mgr);
|
meta_plugin_manager_hide_tile_preview (compositor->plugin_mgr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
meta_compositor_show_window_menu (MetaCompositor *compositor,
|
|
||||||
MetaWindow *window,
|
|
||||||
MetaWindowMenuType menu,
|
|
||||||
int x,
|
|
||||||
int y)
|
|
||||||
{
|
|
||||||
meta_plugin_manager_show_window_menu (compositor->plugin_mgr, window, menu, x, y);
|
|
||||||
}
|
|
||||||
|
@@ -26,6 +26,8 @@
|
|||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <cogl/cogl-texture-pixmap-x11.h>
|
||||||
|
|
||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
|
|
||||||
#include "cogl-utils.h"
|
#include "cogl-utils.h"
|
||||||
@@ -753,6 +755,88 @@ set_filename (MetaBackground *self,
|
|||||||
priv->filename = g_strdup (filename);
|
priv->filename = g_strdup (filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Pixmap
|
||||||
|
get_still_frame_for_monitor (MetaScreen *screen,
|
||||||
|
int monitor)
|
||||||
|
{
|
||||||
|
MetaDisplay *display = meta_screen_get_display (screen);
|
||||||
|
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||||
|
Window xroot = meta_screen_get_xroot (screen);
|
||||||
|
Pixmap pixmap;
|
||||||
|
GC gc;
|
||||||
|
XGCValues values;
|
||||||
|
MetaRectangle geometry;
|
||||||
|
int depth;
|
||||||
|
|
||||||
|
meta_screen_get_monitor_geometry (screen, monitor, &geometry);
|
||||||
|
|
||||||
|
depth = DefaultDepth (xdisplay, meta_screen_get_screen_number (screen));
|
||||||
|
|
||||||
|
pixmap = XCreatePixmap (xdisplay,
|
||||||
|
xroot,
|
||||||
|
geometry.width, geometry.height, depth);
|
||||||
|
|
||||||
|
values.function = GXcopy;
|
||||||
|
values.plane_mask = AllPlanes;
|
||||||
|
values.fill_style = FillSolid;
|
||||||
|
values.subwindow_mode = IncludeInferiors;
|
||||||
|
|
||||||
|
gc = XCreateGC (xdisplay,
|
||||||
|
xroot,
|
||||||
|
GCFunction | GCPlaneMask | GCFillStyle | GCSubwindowMode,
|
||||||
|
&values);
|
||||||
|
|
||||||
|
XCopyArea (xdisplay,
|
||||||
|
xroot, pixmap, gc,
|
||||||
|
geometry.x, geometry.y,
|
||||||
|
geometry.width, geometry.height,
|
||||||
|
0, 0);
|
||||||
|
|
||||||
|
XFreeGC (xdisplay, gc);
|
||||||
|
|
||||||
|
return pixmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* meta_background_load_still_frame:
|
||||||
|
* @self: the #MetaBackground
|
||||||
|
*
|
||||||
|
* Takes a screenshot of the desktop and uses it as the background
|
||||||
|
* source.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
meta_background_load_still_frame (MetaBackground *self)
|
||||||
|
{
|
||||||
|
MetaBackgroundPrivate *priv = self->priv;
|
||||||
|
MetaDisplay *display = meta_screen_get_display (priv->screen);
|
||||||
|
Pixmap still_frame;
|
||||||
|
CoglTexture *texture;
|
||||||
|
CoglContext *context = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
ensure_pipeline (self);
|
||||||
|
|
||||||
|
unset_texture (self);
|
||||||
|
set_style (self, G_DESKTOP_BACKGROUND_STYLE_STRETCHED);
|
||||||
|
|
||||||
|
still_frame = get_still_frame_for_monitor (priv->screen, priv->monitor);
|
||||||
|
XSync (meta_display_get_xdisplay (display), False);
|
||||||
|
|
||||||
|
meta_error_trap_push (display);
|
||||||
|
texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (context, still_frame, FALSE, &error));
|
||||||
|
meta_error_trap_pop (display);
|
||||||
|
|
||||||
|
if (error != NULL)
|
||||||
|
{
|
||||||
|
g_warning ("Failed to create background texture from pixmap: %s",
|
||||||
|
error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_texture (self, texture);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* meta_background_load_gradient:
|
* meta_background_load_gradient:
|
||||||
* @self: the #MetaBackground
|
* @self: the #MetaBackground
|
||||||
|
@@ -356,21 +356,3 @@ meta_plugin_manager_hide_tile_preview (MetaPluginManager *plugin_mgr)
|
|||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
meta_plugin_manager_show_window_menu (MetaPluginManager *plugin_mgr,
|
|
||||||
MetaWindow *window,
|
|
||||||
MetaWindowMenuType menu,
|
|
||||||
int x,
|
|
||||||
int y)
|
|
||||||
{
|
|
||||||
MetaPlugin *plugin = plugin_mgr->plugin;
|
|
||||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
|
||||||
MetaDisplay *display = plugin_mgr->compositor->display;
|
|
||||||
|
|
||||||
if (display->display_opening)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (klass->show_window_menu)
|
|
||||||
klass->show_window_menu (plugin, window, menu, x, y);
|
|
||||||
}
|
|
||||||
|
@@ -80,12 +80,4 @@ gboolean meta_plugin_manager_show_tile_preview (MetaPluginManager *mgr,
|
|||||||
MetaRectangle *tile_rect,
|
MetaRectangle *tile_rect,
|
||||||
int tile_monitor_number);
|
int tile_monitor_number);
|
||||||
gboolean meta_plugin_manager_hide_tile_preview (MetaPluginManager *mgr);
|
gboolean meta_plugin_manager_hide_tile_preview (MetaPluginManager *mgr);
|
||||||
|
|
||||||
void meta_plugin_manager_show_window_menu (MetaPluginManager *mgr,
|
|
||||||
MetaWindow *window,
|
|
||||||
MetaWindowMenuType menu,
|
|
||||||
int x,
|
|
||||||
int y);
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -81,8 +81,18 @@ _meta_plugin_xevent_filter (MetaPlugin *plugin,
|
|||||||
{
|
{
|
||||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||||
|
|
||||||
if (klass->xevent_filter)
|
/* When mutter is running as a wayland compositor, things like input
|
||||||
return klass->xevent_filter (plugin, xev);
|
* events just come directly from clutter so it won't have disabled
|
||||||
|
* clutter's event retrieval and won't need to forward it events (if
|
||||||
|
* it did it would lead to recursion). Also when running as a
|
||||||
|
* wayland compositor we shouldn't be assuming that we're running
|
||||||
|
* with the clutter x11 backend.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (klass->xevent_filter && klass->xevent_filter (plugin, xev))
|
||||||
|
return TRUE;
|
||||||
|
else if (!meta_is_wayland_compositor ())
|
||||||
|
return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE;
|
||||||
else
|
else
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@@ -1,176 +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-backend.h"
|
|
||||||
#include <meta/util.h>
|
|
||||||
|
|
||||||
struct _MetaStagePrivate {
|
|
||||||
CoglPipeline *pipeline;
|
|
||||||
gboolean should_paint_cursor;
|
|
||||||
|
|
||||||
MetaCursorReference *cursor;
|
|
||||||
|
|
||||||
MetaRectangle current_rect;
|
|
||||||
MetaRectangle previous_rect;
|
|
||||||
gboolean previous_is_valid;
|
|
||||||
};
|
|
||||||
typedef struct _MetaStagePrivate MetaStagePrivate;
|
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaStage, meta_stage, CLUTTER_TYPE_STAGE);
|
|
||||||
|
|
||||||
static void
|
|
||||||
update_pipeline (MetaStage *stage)
|
|
||||||
{
|
|
||||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
|
||||||
|
|
||||||
if (priv->cursor)
|
|
||||||
{
|
|
||||||
CoglTexture *texture = meta_cursor_reference_get_cogl_texture (priv->cursor, NULL, NULL);
|
|
||||||
cogl_pipeline_set_layer_texture (priv->pipeline, 0, texture);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
cogl_pipeline_set_layer_texture (priv->pipeline, 0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_stage_finalize (GObject *object)
|
|
||||||
{
|
|
||||||
MetaStage *stage = META_STAGE (object);
|
|
||||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
|
||||||
|
|
||||||
if (priv->pipeline)
|
|
||||||
cogl_object_unref (priv->pipeline);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
paint_cursor (MetaStage *stage)
|
|
||||||
{
|
|
||||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
|
||||||
|
|
||||||
g_assert (meta_is_wayland_compositor ());
|
|
||||||
|
|
||||||
if (!priv->cursor)
|
|
||||||
return;
|
|
||||||
|
|
||||||
cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (),
|
|
||||||
priv->pipeline,
|
|
||||||
priv->current_rect.x,
|
|
||||||
priv->current_rect.y,
|
|
||||||
priv->current_rect.x +
|
|
||||||
priv->current_rect.width,
|
|
||||||
priv->current_rect.y +
|
|
||||||
priv->current_rect.height);
|
|
||||||
|
|
||||||
priv->previous_rect = priv->current_rect;
|
|
||||||
priv->previous_is_valid = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_stage_paint (ClutterActor *actor)
|
|
||||||
{
|
|
||||||
MetaStage *stage = META_STAGE (actor);
|
|
||||||
|
|
||||||
CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor);
|
|
||||||
|
|
||||||
if (meta_is_wayland_compositor ())
|
|
||||||
paint_cursor (stage);
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
|
||||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
|
||||||
|
|
||||||
priv->pipeline = cogl_pipeline_new (ctx);
|
|
||||||
|
|
||||||
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 (MetaStage *stage)
|
|
||||||
{
|
|
||||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
|
||||||
cairo_rectangle_int_t clip;
|
|
||||||
|
|
||||||
/* Clear the location the cursor was at before, if we need to. */
|
|
||||||
if (priv->previous_is_valid)
|
|
||||||
{
|
|
||||||
clip.x = priv->previous_rect.x;
|
|
||||||
clip.y = priv->previous_rect.y;
|
|
||||||
clip.width = priv->previous_rect.width;
|
|
||||||
clip.height = priv->previous_rect.height;
|
|
||||||
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &clip);
|
|
||||||
priv->previous_is_valid = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* And queue a redraw for the current cursor location. */
|
|
||||||
if (priv->cursor)
|
|
||||||
{
|
|
||||||
clip.x = priv->current_rect.x;
|
|
||||||
clip.y = priv->current_rect.y;
|
|
||||||
clip.width = priv->current_rect.width;
|
|
||||||
clip.height = priv->current_rect.height;
|
|
||||||
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &clip);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
meta_stage_set_cursor (MetaStage *stage,
|
|
||||||
MetaCursorReference *cursor,
|
|
||||||
MetaRectangle *rect)
|
|
||||||
{
|
|
||||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
|
||||||
|
|
||||||
if (priv->cursor != cursor)
|
|
||||||
{
|
|
||||||
priv->cursor = cursor;
|
|
||||||
update_pipeline (stage);
|
|
||||||
}
|
|
||||||
|
|
||||||
priv->current_rect = *rect;
|
|
||||||
queue_redraw (stage);
|
|
||||||
}
|
|
@@ -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,
|
|
||||||
MetaCursorReference *cursor,
|
|
||||||
MetaRectangle *rect);
|
|
||||||
G_END_DECLS
|
|
||||||
|
|
||||||
#endif /* META_STAGE_H */
|
|
@@ -108,62 +108,6 @@ meta_surface_actor_wayland_is_unredirected (MetaSurfaceActor *actor)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
get_output_scale (int output_id)
|
|
||||||
{
|
|
||||||
MetaMonitorManager *monitor_manager = meta_monitor_manager_get ();
|
|
||||||
MetaOutput *outputs;
|
|
||||||
guint n_outputs, i;
|
|
||||||
int output_scale = 1;
|
|
||||||
|
|
||||||
outputs = meta_monitor_manager_get_outputs (monitor_manager, &n_outputs);
|
|
||||||
|
|
||||||
for (i = 0; i < n_outputs; i++)
|
|
||||||
{
|
|
||||||
if (outputs[i].output_id == output_id)
|
|
||||||
{
|
|
||||||
output_scale = outputs[i].scale;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return output_scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
double
|
|
||||||
meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *actor)
|
|
||||||
{
|
|
||||||
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (actor);
|
|
||||||
MetaWaylandSurface *surface = priv->surface;
|
|
||||||
MetaWindow *window = surface->window;
|
|
||||||
int output_scale = 1;
|
|
||||||
|
|
||||||
while (surface)
|
|
||||||
{
|
|
||||||
if (surface->window)
|
|
||||||
{
|
|
||||||
window = surface->window;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
surface = surface->sub.parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XXX: We do not handle x11 clients yet */
|
|
||||||
if (window && window->client_type != META_WINDOW_CLIENT_TYPE_X11)
|
|
||||||
output_scale = get_output_scale (window->monitor->output_id);
|
|
||||||
|
|
||||||
return (double)output_scale / (double)priv->surface->scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
meta_surface_actor_wayland_scale_texture (MetaSurfaceActorWayland *actor)
|
|
||||||
{
|
|
||||||
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (actor));
|
|
||||||
double output_scale = meta_surface_actor_wayland_get_scale (actor);
|
|
||||||
|
|
||||||
clutter_actor_set_scale (CLUTTER_ACTOR (stex), output_scale, output_scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
static MetaWindow *
|
static MetaWindow *
|
||||||
meta_surface_actor_wayland_get_window (MetaSurfaceActor *actor)
|
meta_surface_actor_wayland_get_window (MetaSurfaceActor *actor)
|
||||||
{
|
{
|
||||||
@@ -172,42 +116,6 @@ meta_surface_actor_wayland_get_window (MetaSurfaceActor *actor)
|
|||||||
return priv->surface->window;
|
return priv->surface->window;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
meta_surface_actor_wayland_get_preferred_width (ClutterActor *self,
|
|
||||||
gfloat for_height,
|
|
||||||
gfloat *min_width_p,
|
|
||||||
gfloat *natural_width_p)
|
|
||||||
{
|
|
||||||
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
|
|
||||||
double scale = meta_surface_actor_wayland_get_scale (META_SURFACE_ACTOR_WAYLAND (self));
|
|
||||||
|
|
||||||
clutter_actor_get_preferred_width (CLUTTER_ACTOR (stex), for_height, min_width_p, natural_width_p);
|
|
||||||
|
|
||||||
if (min_width_p)
|
|
||||||
*min_width_p *= scale;
|
|
||||||
|
|
||||||
if (natural_width_p)
|
|
||||||
*natural_width_p *= scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_surface_actor_wayland_get_preferred_height (ClutterActor *self,
|
|
||||||
gfloat for_width,
|
|
||||||
gfloat *min_height_p,
|
|
||||||
gfloat *natural_height_p)
|
|
||||||
{
|
|
||||||
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
|
|
||||||
double scale = meta_surface_actor_wayland_get_scale (META_SURFACE_ACTOR_WAYLAND (self));
|
|
||||||
|
|
||||||
clutter_actor_get_preferred_height (CLUTTER_ACTOR (stex), for_width, min_height_p, natural_height_p);
|
|
||||||
|
|
||||||
if (min_height_p)
|
|
||||||
*min_height_p *= scale;
|
|
||||||
|
|
||||||
if (natural_height_p)
|
|
||||||
*natural_height_p *= scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_surface_actor_wayland_dispose (GObject *object)
|
meta_surface_actor_wayland_dispose (GObject *object)
|
||||||
{
|
{
|
||||||
@@ -222,12 +130,8 @@ static void
|
|||||||
meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass)
|
meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass)
|
||||||
{
|
{
|
||||||
MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass);
|
MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass);
|
||||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
actor_class->get_preferred_width = meta_surface_actor_wayland_get_preferred_width;
|
|
||||||
actor_class->get_preferred_height = meta_surface_actor_wayland_get_preferred_height;
|
|
||||||
|
|
||||||
surface_actor_class->process_damage = meta_surface_actor_wayland_process_damage;
|
surface_actor_class->process_damage = meta_surface_actor_wayland_process_damage;
|
||||||
surface_actor_class->pre_paint = meta_surface_actor_wayland_pre_paint;
|
surface_actor_class->pre_paint = meta_surface_actor_wayland_pre_paint;
|
||||||
surface_actor_class->is_visible = meta_surface_actor_wayland_is_visible;
|
surface_actor_class->is_visible = meta_surface_actor_wayland_is_visible;
|
||||||
|
@@ -61,9 +61,6 @@ MetaWaylandSurface * meta_surface_actor_wayland_get_surface (MetaSurfaceActorWay
|
|||||||
void meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self,
|
void meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self,
|
||||||
MetaWaylandBuffer *buffer);
|
MetaWaylandBuffer *buffer);
|
||||||
|
|
||||||
double meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *actor);
|
|
||||||
|
|
||||||
void meta_surface_actor_wayland_scale_texture (MetaSurfaceActorWayland *actor);
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __META_SURFACE_ACTOR_WAYLAND_H__ */
|
#endif /* __META_SURFACE_ACTOR_WAYLAND_H__ */
|
||||||
|
@@ -60,7 +60,6 @@ struct _MetaTextureTower
|
|||||||
CoglTexture *textures[MAX_TEXTURE_LEVELS];
|
CoglTexture *textures[MAX_TEXTURE_LEVELS];
|
||||||
CoglOffscreen *fbos[MAX_TEXTURE_LEVELS];
|
CoglOffscreen *fbos[MAX_TEXTURE_LEVELS];
|
||||||
Box invalid[MAX_TEXTURE_LEVELS];
|
Box invalid[MAX_TEXTURE_LEVELS];
|
||||||
CoglPipeline *pipeline_template;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -92,9 +91,6 @@ meta_texture_tower_free (MetaTextureTower *tower)
|
|||||||
{
|
{
|
||||||
g_return_if_fail (tower != NULL);
|
g_return_if_fail (tower != NULL);
|
||||||
|
|
||||||
if (tower->pipeline_template != NULL)
|
|
||||||
cogl_object_unref (tower->pipeline_template);
|
|
||||||
|
|
||||||
meta_texture_tower_set_base_texture (tower, NULL);
|
meta_texture_tower_set_base_texture (tower, NULL);
|
||||||
|
|
||||||
g_slice_free (MetaTextureTower, tower);
|
g_slice_free (MetaTextureTower, tower);
|
||||||
@@ -377,7 +373,7 @@ texture_tower_create_texture (MetaTextureTower *tower,
|
|||||||
tower->invalid[level].y2 = height;
|
tower->invalid[level].y2 = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static gboolean
|
||||||
texture_tower_revalidate_fbo (MetaTextureTower *tower,
|
texture_tower_revalidate_fbo (MetaTextureTower *tower,
|
||||||
int level)
|
int level)
|
||||||
{
|
{
|
||||||
@@ -388,50 +384,174 @@ texture_tower_revalidate_fbo (MetaTextureTower *tower,
|
|||||||
int dest_texture_width = cogl_texture_get_width (dest_texture);
|
int dest_texture_width = cogl_texture_get_width (dest_texture);
|
||||||
int dest_texture_height = cogl_texture_get_height (dest_texture);
|
int dest_texture_height = cogl_texture_get_height (dest_texture);
|
||||||
Box *invalid = &tower->invalid[level];
|
Box *invalid = &tower->invalid[level];
|
||||||
CoglFramebuffer *fb;
|
CoglMatrix modelview;
|
||||||
CoglError *catch_error = NULL;
|
|
||||||
CoglPipeline *pipeline;
|
|
||||||
|
|
||||||
if (tower->fbos[level] == NULL)
|
if (tower->fbos[level] == NULL)
|
||||||
tower->fbos[level] = cogl_offscreen_new_with_texture (dest_texture);
|
tower->fbos[level] = cogl_offscreen_new_to_texture (dest_texture);
|
||||||
|
|
||||||
fb = COGL_FRAMEBUFFER (tower->fbos[level]);
|
if (tower->fbos[level] == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (!cogl_framebuffer_allocate (fb, &catch_error))
|
cogl_push_framebuffer (COGL_FRAMEBUFFER (tower->fbos[level]));
|
||||||
|
|
||||||
|
cogl_ortho (0, dest_texture_width, dest_texture_height, 0, -1., 1.);
|
||||||
|
|
||||||
|
cogl_matrix_init_identity (&modelview);
|
||||||
|
cogl_set_modelview_matrix (&modelview);
|
||||||
|
|
||||||
|
cogl_set_source_texture (tower->textures[level - 1]);
|
||||||
|
cogl_rectangle_with_texture_coords (invalid->x1, invalid->y1,
|
||||||
|
invalid->x2, invalid->y2,
|
||||||
|
(2. * invalid->x1) / source_texture_width,
|
||||||
|
(2. * invalid->y1) / source_texture_height,
|
||||||
|
(2. * invalid->x2) / source_texture_width,
|
||||||
|
(2. * invalid->y2) / source_texture_height);
|
||||||
|
|
||||||
|
cogl_pop_framebuffer ();
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fill_copy (guchar *buf,
|
||||||
|
const guchar *source,
|
||||||
|
int width)
|
||||||
|
{
|
||||||
|
memcpy (buf, source, width * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fill_scale_down (guchar *buf,
|
||||||
|
const guchar *source,
|
||||||
|
int width)
|
||||||
|
{
|
||||||
|
while (width > 1)
|
||||||
{
|
{
|
||||||
cogl_error_free (catch_error);
|
buf[0] = (source[0] + source[4]) / 2;
|
||||||
return;
|
buf[1] = (source[1] + source[5]) / 2;
|
||||||
|
buf[2] = (source[2] + source[6]) / 2;
|
||||||
|
buf[3] = (source[3] + source[7]) / 2;
|
||||||
|
|
||||||
|
buf += 4;
|
||||||
|
source += 8;
|
||||||
|
width -= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
cogl_framebuffer_orthographic (fb, 0, 0, dest_texture_width, dest_texture_height, -1., 1.);
|
if (width > 0)
|
||||||
|
|
||||||
if (!tower->pipeline_template)
|
|
||||||
{
|
{
|
||||||
CoglContext *ctx =
|
buf[0] = source[0] / 2;
|
||||||
clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
buf[1] = source[1] / 2;
|
||||||
tower->pipeline_template = cogl_pipeline_new (ctx);
|
buf[2] = source[2] / 2;
|
||||||
cogl_pipeline_set_blend (tower->pipeline_template, "RGBA = ADD (SRC_COLOR, 0)", NULL);
|
buf[3] = source[3] / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
texture_tower_revalidate_client (MetaTextureTower *tower,
|
||||||
|
int level)
|
||||||
|
{
|
||||||
|
CoglTexture *source_texture = tower->textures[level - 1];
|
||||||
|
int source_texture_width = cogl_texture_get_width (source_texture);
|
||||||
|
int source_texture_height = cogl_texture_get_height (source_texture);
|
||||||
|
guint source_rowstride;
|
||||||
|
guchar *source_data;
|
||||||
|
CoglTexture *dest_texture = tower->textures[level];
|
||||||
|
int dest_texture_width = cogl_texture_get_width (dest_texture);
|
||||||
|
int dest_texture_height = cogl_texture_get_height (dest_texture);
|
||||||
|
int dest_x = tower->invalid[level].x1;
|
||||||
|
int dest_y = tower->invalid[level].y1;
|
||||||
|
int dest_width = tower->invalid[level].x2 - tower->invalid[level].x1;
|
||||||
|
int dest_height = tower->invalid[level].y2 - tower->invalid[level].y1;
|
||||||
|
guchar *dest_data;
|
||||||
|
guchar *source_tmp1 = NULL, *source_tmp2 = NULL;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
source_rowstride = source_texture_width * 4;
|
||||||
|
|
||||||
|
source_data = g_malloc (source_texture_height * source_rowstride);
|
||||||
|
cogl_texture_get_data (source_texture, TEXTURE_FORMAT, source_rowstride,
|
||||||
|
source_data);
|
||||||
|
|
||||||
|
dest_data = g_malloc (dest_height * dest_width * 4);
|
||||||
|
|
||||||
|
if (dest_texture_height < source_texture_height)
|
||||||
|
{
|
||||||
|
source_tmp1 = g_malloc (dest_width * 4);
|
||||||
|
source_tmp2 = g_malloc (dest_width * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
pipeline = cogl_pipeline_copy (tower->pipeline_template);
|
for (i = 0; i < dest_height; i++)
|
||||||
cogl_pipeline_set_layer_texture (pipeline, 0, tower->textures[level - 1]);
|
{
|
||||||
|
guchar *dest_row = dest_data + i * dest_width * 4;
|
||||||
|
if (dest_texture_height < source_texture_height)
|
||||||
|
{
|
||||||
|
guchar *source1, *source2;
|
||||||
|
guchar *dest;
|
||||||
|
|
||||||
cogl_framebuffer_draw_textured_rectangle (fb, pipeline,
|
if (dest_texture_width < source_texture_width)
|
||||||
invalid->x1, invalid->y1,
|
{
|
||||||
invalid->x2, invalid->y2,
|
fill_scale_down (source_tmp1,
|
||||||
(2. * invalid->x1) / source_texture_width,
|
source_data + ((i + dest_y) * 2) * source_rowstride + dest_x * 2 * 4,
|
||||||
(2. * invalid->y1) / source_texture_height,
|
dest_width * 2);
|
||||||
(2. * invalid->x2) / source_texture_width,
|
fill_scale_down (source_tmp2,
|
||||||
(2. * invalid->y2) / source_texture_height);
|
source_data + ((i + dest_y) * 2 + 1) * source_rowstride + dest_x * 2 * 4,
|
||||||
|
dest_width * 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fill_copy (source_tmp1,
|
||||||
|
source_data + ((i + dest_y) * 2) * source_rowstride + dest_x * 4,
|
||||||
|
dest_width);
|
||||||
|
fill_copy (source_tmp2,
|
||||||
|
source_data + ((i + dest_y) * 2 + 1) * source_rowstride + dest_x * 4,
|
||||||
|
dest_width);
|
||||||
|
}
|
||||||
|
|
||||||
cogl_object_unref (pipeline);
|
source1 = source_tmp1;
|
||||||
|
source2 = source_tmp2;
|
||||||
|
|
||||||
|
dest = dest_row;
|
||||||
|
for (j = 0; j < dest_width * 4; j++)
|
||||||
|
*(dest++) = (*(source1++) + *(source2++)) / 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (dest_texture_width < source_texture_width)
|
||||||
|
fill_scale_down (dest_row,
|
||||||
|
source_data + (i + dest_y) * source_rowstride + dest_x * 2 * 4,
|
||||||
|
dest_width * 2);
|
||||||
|
else
|
||||||
|
fill_copy (dest_row,
|
||||||
|
source_data + (i + dest_y) * source_rowstride,
|
||||||
|
dest_width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cogl_texture_set_region (dest_texture,
|
||||||
|
0, 0,
|
||||||
|
dest_x, dest_y,
|
||||||
|
dest_width, dest_height,
|
||||||
|
dest_width, dest_height,
|
||||||
|
TEXTURE_FORMAT,
|
||||||
|
4 * dest_width,
|
||||||
|
dest_data);
|
||||||
|
|
||||||
|
if (dest_texture_height < source_texture_height)
|
||||||
|
{
|
||||||
|
g_free (source_tmp1);
|
||||||
|
g_free (source_tmp2);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (source_data);
|
||||||
|
g_free (dest_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
texture_tower_revalidate (MetaTextureTower *tower,
|
texture_tower_revalidate (MetaTextureTower *tower,
|
||||||
int level)
|
int level)
|
||||||
{
|
{
|
||||||
texture_tower_revalidate_fbo (tower, level);
|
if (!texture_tower_revalidate_fbo (tower, level))
|
||||||
|
texture_tower_revalidate_client (tower, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -32,7 +32,6 @@
|
|||||||
|
|
||||||
#include "meta-surface-actor.h"
|
#include "meta-surface-actor.h"
|
||||||
#include "meta-surface-actor-x11.h"
|
#include "meta-surface-actor-x11.h"
|
||||||
#include "meta-surface-actor-wayland.h"
|
|
||||||
|
|
||||||
#include "wayland/meta-wayland-surface.h"
|
#include "wayland/meta-wayland-surface.h"
|
||||||
|
|
||||||
@@ -550,16 +549,6 @@ meta_window_actor_get_shape_bounds (MetaWindowActor *self,
|
|||||||
MetaWindowActorPrivate *priv = self->priv;
|
MetaWindowActorPrivate *priv = self->priv;
|
||||||
|
|
||||||
cairo_region_get_extents (priv->shape_region, bounds);
|
cairo_region_get_extents (priv->shape_region, bounds);
|
||||||
|
|
||||||
if (META_IS_SURFACE_ACTOR_WAYLAND (priv->surface))
|
|
||||||
{
|
|
||||||
double scale = priv->surface ?
|
|
||||||
meta_surface_actor_wayland_get_scale (META_SURFACE_ACTOR_WAYLAND (priv->surface)) : 1.;
|
|
||||||
bounds->x *= scale;
|
|
||||||
bounds->y *= scale;
|
|
||||||
bounds->width *= scale;
|
|
||||||
bounds->height *= scale;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -713,6 +702,7 @@ static gboolean
|
|||||||
meta_window_actor_has_shadow (MetaWindowActor *self)
|
meta_window_actor_has_shadow (MetaWindowActor *self)
|
||||||
{
|
{
|
||||||
MetaWindowActorPrivate *priv = self->priv;
|
MetaWindowActorPrivate *priv = self->priv;
|
||||||
|
MetaWindowType window_type = meta_window_get_window_type (priv->window);
|
||||||
|
|
||||||
if (priv->no_shadow)
|
if (priv->no_shadow)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@@ -751,6 +741,25 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
|
|||||||
if (priv->window->override_redirect)
|
if (priv->window->override_redirect)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't put shadow around DND icon windows
|
||||||
|
*/
|
||||||
|
if (window_type == META_WINDOW_DND ||
|
||||||
|
window_type == META_WINDOW_DESKTOP)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (window_type == META_WINDOW_MENU
|
||||||
|
#if 0
|
||||||
|
|| window_type == META_WINDOW_DROPDOWN_MENU
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (window_type == META_WINDOW_TOOLTIP)
|
||||||
|
return TRUE;
|
||||||
|
#endif
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -866,7 +875,6 @@ queue_send_frame_messages_timeout (MetaWindowActor *self)
|
|||||||
* to be drawn when the timer expires.
|
* to be drawn when the timer expires.
|
||||||
*/
|
*/
|
||||||
priv->send_frame_messages_timer = g_timeout_add_full (META_PRIORITY_REDRAW, offset, send_frame_messages_timeout, self, NULL);
|
priv->send_frame_messages_timer = g_timeout_add_full (META_PRIORITY_REDRAW, offset, send_frame_messages_timeout, self, NULL);
|
||||||
g_source_set_name_by_id (priv->send_frame_messages_timer, "[mutter] send_frame_messages_timeout");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
#define DESTROY_TIMEOUT 100
|
#define DESTROY_TIMEOUT 100
|
||||||
#define MINIMIZE_TIMEOUT 250
|
#define MINIMIZE_TIMEOUT 250
|
||||||
|
#define MAXIMIZE_TIMEOUT 250
|
||||||
#define MAP_TIMEOUT 250
|
#define MAP_TIMEOUT 250
|
||||||
#define SWITCH_TIMEOUT 500
|
#define SWITCH_TIMEOUT 500
|
||||||
|
|
||||||
@@ -76,6 +77,18 @@ static void map (MetaPlugin *plugin,
|
|||||||
MetaWindowActor *actor);
|
MetaWindowActor *actor);
|
||||||
static void destroy (MetaPlugin *plugin,
|
static void destroy (MetaPlugin *plugin,
|
||||||
MetaWindowActor *actor);
|
MetaWindowActor *actor);
|
||||||
|
static void maximize (MetaPlugin *plugin,
|
||||||
|
MetaWindowActor *actor,
|
||||||
|
gint x,
|
||||||
|
gint y,
|
||||||
|
gint width,
|
||||||
|
gint height);
|
||||||
|
static void unmaximize (MetaPlugin *plugin,
|
||||||
|
MetaWindowActor *actor,
|
||||||
|
gint x,
|
||||||
|
gint y,
|
||||||
|
gint width,
|
||||||
|
gint height);
|
||||||
|
|
||||||
static void switch_workspace (MetaPlugin *plugin,
|
static void switch_workspace (MetaPlugin *plugin,
|
||||||
gint from,
|
gint from,
|
||||||
@@ -122,8 +135,12 @@ typedef struct _ActorPrivate
|
|||||||
ClutterActor *orig_parent;
|
ClutterActor *orig_parent;
|
||||||
|
|
||||||
ClutterTimeline *tml_minimize;
|
ClutterTimeline *tml_minimize;
|
||||||
|
ClutterTimeline *tml_maximize;
|
||||||
ClutterTimeline *tml_destroy;
|
ClutterTimeline *tml_destroy;
|
||||||
ClutterTimeline *tml_map;
|
ClutterTimeline *tml_map;
|
||||||
|
|
||||||
|
gboolean is_minimized : 1;
|
||||||
|
gboolean is_maximized : 1;
|
||||||
} ActorPrivate;
|
} ActorPrivate;
|
||||||
|
|
||||||
/* callback data for when animations complete */
|
/* callback data for when animations complete */
|
||||||
@@ -199,6 +216,8 @@ meta_default_plugin_class_init (MetaDefaultPluginClass *klass)
|
|||||||
plugin_class->start = start;
|
plugin_class->start = start;
|
||||||
plugin_class->map = map;
|
plugin_class->map = map;
|
||||||
plugin_class->minimize = minimize;
|
plugin_class->minimize = minimize;
|
||||||
|
plugin_class->maximize = maximize;
|
||||||
|
plugin_class->unmaximize = unmaximize;
|
||||||
plugin_class->destroy = destroy;
|
plugin_class->destroy = destroy;
|
||||||
plugin_class->switch_workspace = switch_workspace;
|
plugin_class->switch_workspace = switch_workspace;
|
||||||
plugin_class->show_tile_preview = show_tile_preview;
|
plugin_class->show_tile_preview = show_tile_preview;
|
||||||
@@ -503,6 +522,8 @@ minimize (MetaPlugin *plugin, MetaWindowActor *window_actor)
|
|||||||
EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
|
EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
|
||||||
ActorPrivate *apriv = get_actor_private (window_actor);
|
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||||
|
|
||||||
|
apriv->is_minimized = TRUE;
|
||||||
|
|
||||||
animation = clutter_actor_animate (actor,
|
animation = clutter_actor_animate (actor,
|
||||||
CLUTTER_EASE_IN_SINE,
|
CLUTTER_EASE_IN_SINE,
|
||||||
MINIMIZE_TIMEOUT,
|
MINIMIZE_TIMEOUT,
|
||||||
@@ -523,6 +544,115 @@ minimize (MetaPlugin *plugin, MetaWindowActor *window_actor)
|
|||||||
meta_plugin_minimize_completed (plugin, window_actor);
|
meta_plugin_minimize_completed (plugin, window_actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Minimize effect completion callback; this function restores actor state, and
|
||||||
|
* calls the manager callback function.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
on_maximize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Must reverse the effect of the effect.
|
||||||
|
*/
|
||||||
|
MetaPlugin *plugin = data->plugin;
|
||||||
|
MetaWindowActor *window_actor = META_WINDOW_ACTOR (data->actor);
|
||||||
|
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||||
|
|
||||||
|
apriv->tml_maximize = NULL;
|
||||||
|
|
||||||
|
/* FIXME - don't assume the original scale was 1.0 */
|
||||||
|
clutter_actor_set_scale (data->actor, 1.0, 1.0);
|
||||||
|
|
||||||
|
/* Now notify the manager that we are done with this effect */
|
||||||
|
meta_plugin_maximize_completed (plugin, window_actor);
|
||||||
|
|
||||||
|
g_free (data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The Nature of Maximize operation is such that it is difficult to do a visual
|
||||||
|
* effect that would work well. Scaling, the obvious effect, does not work that
|
||||||
|
* well, because at the end of the effect we end up with window content bigger
|
||||||
|
* and differently laid out than in the real window; this is a proof concept.
|
||||||
|
*
|
||||||
|
* (Something like a sound would be more appropriate.)
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
maximize (MetaPlugin *plugin,
|
||||||
|
MetaWindowActor *window_actor,
|
||||||
|
gint end_x, gint end_y, gint end_width, gint end_height)
|
||||||
|
{
|
||||||
|
MetaWindowType type;
|
||||||
|
ClutterActor *actor = CLUTTER_ACTOR (window_actor);
|
||||||
|
MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
|
||||||
|
|
||||||
|
gdouble scale_x = 1.0;
|
||||||
|
gdouble scale_y = 1.0;
|
||||||
|
|
||||||
|
type = meta_window_get_window_type (meta_window);
|
||||||
|
|
||||||
|
if (type == META_WINDOW_NORMAL)
|
||||||
|
{
|
||||||
|
ClutterAnimation *animation;
|
||||||
|
EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
|
||||||
|
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||||
|
gfloat width, height;
|
||||||
|
gfloat x, y;
|
||||||
|
|
||||||
|
apriv->is_maximized = TRUE;
|
||||||
|
|
||||||
|
clutter_actor_get_size (actor, &width, &height);
|
||||||
|
clutter_actor_get_position (actor, &x, &y);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Work out the scale and anchor point so that the window is expanding
|
||||||
|
* smoothly into the target size.
|
||||||
|
*/
|
||||||
|
scale_x = (gdouble)end_width / (gdouble) width;
|
||||||
|
scale_y = (gdouble)end_height / (gdouble) height;
|
||||||
|
|
||||||
|
animation = clutter_actor_animate (actor,
|
||||||
|
CLUTTER_EASE_IN_SINE,
|
||||||
|
MAXIMIZE_TIMEOUT,
|
||||||
|
"scale-x", scale_x,
|
||||||
|
"scale-y", scale_y,
|
||||||
|
NULL);
|
||||||
|
apriv->tml_maximize = clutter_animation_get_timeline (animation);
|
||||||
|
data->plugin = plugin;
|
||||||
|
data->actor = actor;
|
||||||
|
g_signal_connect (apriv->tml_maximize, "completed",
|
||||||
|
G_CALLBACK (on_maximize_effect_complete),
|
||||||
|
data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
meta_plugin_maximize_completed (plugin, window_actor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See comments on the maximize() function.
|
||||||
|
*
|
||||||
|
* (Just a skeleton code.)
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
unmaximize (MetaPlugin *plugin,
|
||||||
|
MetaWindowActor *window_actor,
|
||||||
|
gint end_x, gint end_y, gint end_width, gint end_height)
|
||||||
|
{
|
||||||
|
MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
|
||||||
|
MetaWindowType type = meta_window_get_window_type (meta_window);
|
||||||
|
|
||||||
|
if (type == META_WINDOW_NORMAL)
|
||||||
|
{
|
||||||
|
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||||
|
|
||||||
|
apriv->is_maximized = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do this conditionally, if the effect requires completion callback. */
|
||||||
|
meta_plugin_unmaximize_completed (plugin, window_actor);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_map_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data)
|
on_map_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data)
|
||||||
{
|
{
|
||||||
@@ -578,6 +708,9 @@ map (MetaPlugin *plugin, MetaWindowActor *window_actor)
|
|||||||
g_signal_connect (apriv->tml_map, "completed",
|
g_signal_connect (apriv->tml_map, "completed",
|
||||||
G_CALLBACK (on_map_effect_complete),
|
G_CALLBACK (on_map_effect_complete),
|
||||||
data);
|
data);
|
||||||
|
|
||||||
|
apriv->is_minimized = FALSE;
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
meta_plugin_map_completed (plugin, window_actor);
|
meta_plugin_map_completed (plugin, window_actor);
|
||||||
@@ -738,6 +871,12 @@ kill_window_effects (MetaPlugin *plugin,
|
|||||||
g_signal_emit_by_name (apriv->tml_minimize, "completed", NULL);
|
g_signal_emit_by_name (apriv->tml_minimize, "completed", NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (apriv->tml_maximize)
|
||||||
|
{
|
||||||
|
clutter_timeline_stop (apriv->tml_maximize);
|
||||||
|
g_signal_emit_by_name (apriv->tml_maximize, "completed", NULL);
|
||||||
|
}
|
||||||
|
|
||||||
if (apriv->tml_map)
|
if (apriv->tml_map)
|
||||||
{
|
{
|
||||||
clutter_timeline_stop (apriv->tml_map);
|
clutter_timeline_stop (apriv->tml_map);
|
||||||
|
@@ -121,7 +121,7 @@ meta_region_builder_finish (MetaRegionBuilder *builder)
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* MetaRegionIterator */
|
/* MetaRegionIterator */
|
||||||
|
|
||||||
@@ -171,7 +171,7 @@ meta_region_iterator_next (MetaRegionIterator *iter)
|
|||||||
iter->line_end = TRUE;
|
iter->line_end = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_expanded_rect (MetaRegionBuilder *builder,
|
add_expanded_rect (MetaRegionBuilder *builder,
|
||||||
int x,
|
int x,
|
||||||
|
241
src/core/above-tab-keycode.c
Normal file
241
src/core/above-tab-keycode.c
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
|
||||||
|
/* Find the keycode for the key above the tab key */
|
||||||
|
/*
|
||||||
|
* Copyright 2010 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* The standard cycle-windows keybinding should be the key above the
|
||||||
|
* tab key. This will have a different keysym on different keyboards -
|
||||||
|
* it's the ` (grave) key on US keyboards but something else on many
|
||||||
|
* other national layouts. So we need to figure out the keycode for
|
||||||
|
* this key without reference to key symbol.
|
||||||
|
*
|
||||||
|
* The "correct" way to do this is to get the XKB geometry from the
|
||||||
|
* X server, find the Tab key, find the key above the Tab key in the
|
||||||
|
* same section and use the keycode for that key. This is what I
|
||||||
|
* implemented here, but unfortunately, fetching the geometry is rather
|
||||||
|
* slow (It could take 20ms or more.)
|
||||||
|
*
|
||||||
|
* If you looking for a way to optimize Mutter startup performance:
|
||||||
|
* On all Linux systems using evdev the key above TAB will have
|
||||||
|
* keycode 49. (KEY_GRAVE=41 + the 8 code point offset between
|
||||||
|
* evdev keysyms and X keysyms.) So a configure option
|
||||||
|
* --with-above-tab-keycode=49 could be added that bypassed this
|
||||||
|
* code. It wouldn't work right for displaying Mutter remotely
|
||||||
|
* to a non-Linux X server, but that is pretty rare.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "display-private.h"
|
||||||
|
|
||||||
|
#include <X11/keysym.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_XKB
|
||||||
|
#include <X11/XKBlib.h>
|
||||||
|
#include <X11/extensions/XKBgeom.h>
|
||||||
|
|
||||||
|
static guint
|
||||||
|
compute_above_tab_keycode (Display *xdisplay)
|
||||||
|
{
|
||||||
|
XkbDescPtr keyboard;
|
||||||
|
XkbGeometryPtr geometry;
|
||||||
|
int i, j, k;
|
||||||
|
int tab_keycode;
|
||||||
|
char *tab_name;
|
||||||
|
XkbSectionPtr tab_section;
|
||||||
|
XkbBoundsRec tab_bounds;
|
||||||
|
XkbKeyPtr best_key = NULL;
|
||||||
|
guint best_keycode = (guint)-1;
|
||||||
|
int best_x_dist = G_MAXINT;
|
||||||
|
int best_y_dist = G_MAXINT;
|
||||||
|
|
||||||
|
/* We need only the Names and the Geometry, but asking for these results
|
||||||
|
* in the Keyboard information retrieval failing for unknown reasons.
|
||||||
|
* (Testing with xorg-1.9.1.) So we ask for a part that we don't need
|
||||||
|
* as well.
|
||||||
|
*/
|
||||||
|
keyboard = XkbGetKeyboard (xdisplay,
|
||||||
|
XkbGBN_ClientSymbolsMask | XkbGBN_KeyNamesMask | XkbGBN_GeometryMask,
|
||||||
|
XkbUseCoreKbd);
|
||||||
|
if (!keyboard)
|
||||||
|
return best_keycode;
|
||||||
|
|
||||||
|
geometry = keyboard->geom;
|
||||||
|
|
||||||
|
/* There could potentially be multiple keys with the Tab keysym on the keyboard;
|
||||||
|
* but XKeysymToKeycode() returns us the one that the alt-Tab binding will
|
||||||
|
* use which is good enough
|
||||||
|
*/
|
||||||
|
tab_keycode = XKeysymToKeycode (xdisplay, XK_Tab);
|
||||||
|
if (tab_keycode == 0 || tab_keycode < keyboard->min_key_code || tab_keycode > keyboard->max_key_code)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* The keyboard geometry is stored by key "name" rather than keycode.
|
||||||
|
* (Key names are 4-character strings like like TAB or AE01.) We use the
|
||||||
|
* 'names' part of the keyboard description to map keycode to key name.
|
||||||
|
*
|
||||||
|
* XKB has a "key aliases" feature where a single keyboard key can have
|
||||||
|
* multiple names (with separate sets of aliases in the 'names' part and
|
||||||
|
* in the 'geometry' part), but I don't really understand it or how it is used,
|
||||||
|
* so I'm ignoring it here.
|
||||||
|
*/
|
||||||
|
|
||||||
|
tab_name = keyboard->names->keys[tab_keycode].name; /* Not NULL terminated! */
|
||||||
|
|
||||||
|
/* First, iterate through the keyboard geometry to find the tab key; the keyboard
|
||||||
|
* geometry has a three-level heirarchy of section > row > key
|
||||||
|
*/
|
||||||
|
for (i = 0; i < geometry->num_sections; i++)
|
||||||
|
{
|
||||||
|
XkbSectionPtr section = &geometry->sections[i];
|
||||||
|
for (j = 0; j < section->num_rows; j++)
|
||||||
|
{
|
||||||
|
int x = 0;
|
||||||
|
int y = 0;
|
||||||
|
|
||||||
|
XkbRowPtr row = §ion->rows[j];
|
||||||
|
for (k = 0; k < row->num_keys; k++)
|
||||||
|
{
|
||||||
|
XkbKeyPtr key = &row->keys[k];
|
||||||
|
XkbShapePtr shape = XkbKeyShape (geometry, key);
|
||||||
|
|
||||||
|
if (row->vertical)
|
||||||
|
y += key->gap;
|
||||||
|
else
|
||||||
|
x += key->gap;
|
||||||
|
|
||||||
|
if (strncmp (key->name.name, tab_name, XkbKeyNameLength) == 0)
|
||||||
|
{
|
||||||
|
tab_section = section;
|
||||||
|
tab_bounds = shape->bounds;
|
||||||
|
tab_bounds.x1 += row->left + x;
|
||||||
|
tab_bounds.x2 += row->left + x;
|
||||||
|
tab_bounds.y1 += row->top + y;
|
||||||
|
tab_bounds.y2 += row->top + y;
|
||||||
|
|
||||||
|
goto found_tab;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (row->vertical)
|
||||||
|
y += (shape->bounds.y2 - shape->bounds.y1);
|
||||||
|
else
|
||||||
|
x += (shape->bounds.x2 - shape->bounds.x1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No tab key found */
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
found_tab:
|
||||||
|
|
||||||
|
/* Now find the key that:
|
||||||
|
* - Is in the same section as the Tab key
|
||||||
|
* - Has a horizontal center in the Tab key's horizonal bounds
|
||||||
|
* - Is above the Tab key at a distance closer than any other key
|
||||||
|
* - In case of ties, has its horizontal center as close as possible
|
||||||
|
* to the Tab key's horizontal center
|
||||||
|
*/
|
||||||
|
for (j = 0; j < tab_section->num_rows; j++)
|
||||||
|
{
|
||||||
|
int x = 0;
|
||||||
|
int y = 0;
|
||||||
|
|
||||||
|
XkbRowPtr row = &tab_section->rows[j];
|
||||||
|
for (k = 0; k < row->num_keys; k++)
|
||||||
|
{
|
||||||
|
XkbKeyPtr key = &row->keys[k];
|
||||||
|
XkbShapePtr shape = XkbKeyShape(geometry, key);
|
||||||
|
XkbBoundsRec bounds = shape->bounds;
|
||||||
|
int x_center;
|
||||||
|
int x_dist, y_dist;
|
||||||
|
|
||||||
|
if (row->vertical)
|
||||||
|
y += key->gap;
|
||||||
|
else
|
||||||
|
x += key->gap;
|
||||||
|
|
||||||
|
bounds.x1 += row->left + x;
|
||||||
|
bounds.x2 += row->left + x;
|
||||||
|
bounds.y1 += row->top + y;
|
||||||
|
bounds.y2 += row->top + y;
|
||||||
|
|
||||||
|
y_dist = tab_bounds.y1 - bounds.y2;
|
||||||
|
if (y_dist < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
x_center = (bounds.x1 + bounds.x2) / 2;
|
||||||
|
if (x_center < tab_bounds.x1 || x_center > tab_bounds.x2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
x_dist = ABS (x_center - (tab_bounds.x1 + tab_bounds.x2) / 2);
|
||||||
|
|
||||||
|
if (y_dist < best_y_dist ||
|
||||||
|
(y_dist == best_y_dist && x_dist < best_x_dist))
|
||||||
|
{
|
||||||
|
best_key = key;
|
||||||
|
best_x_dist = x_dist;
|
||||||
|
best_y_dist = y_dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (row->vertical)
|
||||||
|
y += (shape->bounds.y2 - shape->bounds.y1);
|
||||||
|
else
|
||||||
|
x += (shape->bounds.x2 - shape->bounds.x1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (best_key == NULL)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* Now we need to resolve the name of the best key back to a keycode */
|
||||||
|
for (i = keyboard->min_key_code; i < keyboard->max_key_code; i++)
|
||||||
|
{
|
||||||
|
if (strncmp (best_key->name.name, keyboard->names->keys[i].name, XkbKeyNameLength) == 0)
|
||||||
|
{
|
||||||
|
best_keycode = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
XkbFreeKeyboard (keyboard, 0, True);
|
||||||
|
|
||||||
|
return best_keycode;
|
||||||
|
}
|
||||||
|
#else /* !HAVE_XKB */
|
||||||
|
static guint
|
||||||
|
compute_above_tab_keycode (Display *xdisplay)
|
||||||
|
{
|
||||||
|
return XKeysymToKeycode (xdisplay, XK_grave);
|
||||||
|
}
|
||||||
|
#endif /* HAVE_XKB */
|
||||||
|
|
||||||
|
guint
|
||||||
|
meta_display_get_above_tab_keycode (MetaDisplay *display)
|
||||||
|
{
|
||||||
|
if (display->above_tab_keycode == 0) /* not yet computed */
|
||||||
|
display->above_tab_keycode = compute_above_tab_keycode (display->xdisplay);
|
||||||
|
|
||||||
|
if (display->above_tab_keycode == (guint)-1) /* failed to compute */
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return display->above_tab_keycode;
|
||||||
|
}
|
@@ -120,7 +120,6 @@ bell_unflash_frame (gpointer data)
|
|||||||
static void
|
static void
|
||||||
bell_flash_window_frame (MetaWindow *window)
|
bell_flash_window_frame (MetaWindow *window)
|
||||||
{
|
{
|
||||||
guint id;
|
|
||||||
g_assert (window->frame != NULL);
|
g_assert (window->frame != NULL);
|
||||||
window->frame->is_flashing = 1;
|
window->frame->is_flashing = 1;
|
||||||
meta_frame_queue_draw (window->frame);
|
meta_frame_queue_draw (window->frame);
|
||||||
@@ -129,9 +128,8 @@ bell_flash_window_frame (MetaWindow *window)
|
|||||||
* we are guaranteed to get at least one frame drawn in the
|
* we are guaranteed to get at least one frame drawn in the
|
||||||
* flashed state, no matter how loaded we are.
|
* flashed state, no matter how loaded we are.
|
||||||
*/
|
*/
|
||||||
id = g_timeout_add_full (META_PRIORITY_REDRAW, 100,
|
g_timeout_add_full (META_PRIORITY_REDRAW, 100,
|
||||||
bell_unflash_frame, window->frame, NULL);
|
bell_unflash_frame, window->frame, NULL);
|
||||||
g_source_set_name_by_id (id, "[mutter] bell_unflash_frame");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -199,6 +199,14 @@ static void place_window_if_needed (MetaWindow *window,
|
|||||||
ConstraintInfo *info);
|
ConstraintInfo *info);
|
||||||
static void update_onscreen_requirements (MetaWindow *window,
|
static void update_onscreen_requirements (MetaWindow *window,
|
||||||
ConstraintInfo *info);
|
ConstraintInfo *info);
|
||||||
|
static void extend_by_frame (MetaWindow *window,
|
||||||
|
MetaRectangle *rect);
|
||||||
|
static void unextend_by_frame (MetaWindow *window,
|
||||||
|
MetaRectangle *rect);
|
||||||
|
static inline void get_size_limits (MetaWindow *window,
|
||||||
|
gboolean include_frame,
|
||||||
|
MetaRectangle *min_size,
|
||||||
|
MetaRectangle *max_size);
|
||||||
|
|
||||||
typedef gboolean (* ConstraintFunc) (MetaWindow *window,
|
typedef gboolean (* ConstraintFunc) (MetaWindow *window,
|
||||||
ConstraintInfo *info,
|
ConstraintInfo *info,
|
||||||
@@ -275,6 +283,11 @@ meta_window_constrain (MetaWindow *window,
|
|||||||
ConstraintPriority priority = PRIORITY_MINIMUM;
|
ConstraintPriority priority = PRIORITY_MINIMUM;
|
||||||
gboolean satisfied = FALSE;
|
gboolean satisfied = FALSE;
|
||||||
|
|
||||||
|
/* WARNING: orig and new specify positions and sizes of the inner window,
|
||||||
|
* not the outer. This is a common gotcha since half the constraints
|
||||||
|
* deal with inner window position/size and half deal with outer. See
|
||||||
|
* doc/how-constraints-works.txt for more information.
|
||||||
|
*/
|
||||||
meta_topic (META_DEBUG_GEOMETRY,
|
meta_topic (META_DEBUG_GEOMETRY,
|
||||||
"Constraining %s in move from %d,%d %dx%d to %d,%d %dx%d\n",
|
"Constraining %s in move from %d,%d %dx%d to %d,%d %dx%d\n",
|
||||||
window->desc,
|
window->desc,
|
||||||
@@ -487,6 +500,7 @@ place_window_if_needed(MetaWindow *window,
|
|||||||
meta_window_get_frame_rect (window, &placed_rect);
|
meta_window_get_frame_rect (window, &placed_rect);
|
||||||
|
|
||||||
orig_rect = info->orig;
|
orig_rect = info->orig;
|
||||||
|
extend_by_frame (window, &orig_rect);
|
||||||
|
|
||||||
meta_window_place (window, orig_rect.x, orig_rect.y,
|
meta_window_place (window, orig_rect.x, orig_rect.y,
|
||||||
&placed_rect.x, &placed_rect.y);
|
&placed_rect.x, &placed_rect.y);
|
||||||
@@ -506,6 +520,8 @@ place_window_if_needed(MetaWindow *window,
|
|||||||
meta_workspace_get_onmonitor_region (cur_workspace,
|
meta_workspace_get_onmonitor_region (cur_workspace,
|
||||||
monitor_info->number);
|
monitor_info->number);
|
||||||
|
|
||||||
|
meta_window_frame_rect_to_client_rect (window, &placed_rect, &placed_rect);
|
||||||
|
|
||||||
info->current.x = placed_rect.x;
|
info->current.x = placed_rect.x;
|
||||||
info->current.y = placed_rect.y;
|
info->current.y = placed_rect.y;
|
||||||
|
|
||||||
@@ -537,10 +553,10 @@ place_window_if_needed(MetaWindow *window,
|
|||||||
.083 * info->work_area_monitor.height;
|
.083 * info->work_area_monitor.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* idle_move_resize() uses the unconstrained_rect, so make sure it
|
/* idle_move_resize() uses the user_rect, so make sure it uses the
|
||||||
* uses the placed coordinates (bug #556696).
|
* placed coordinates (bug #556696).
|
||||||
*/
|
*/
|
||||||
window->unconstrained_rect = info->current;
|
window->user_rect = info->current;
|
||||||
|
|
||||||
if (window->maximize_horizontally_after_placement ||
|
if (window->maximize_horizontally_after_placement ||
|
||||||
window->maximize_vertically_after_placement)
|
window->maximize_vertically_after_placement)
|
||||||
@@ -606,6 +622,11 @@ update_onscreen_requirements (MetaWindow *window,
|
|||||||
* problematic case but this may need to be revisited.
|
* problematic case but this may need to be revisited.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* The require onscreen/on-single-monitor and titlebar_visible
|
||||||
|
* stuff is relative to the outer window, not the inner
|
||||||
|
*/
|
||||||
|
extend_by_frame (window, &info->current);
|
||||||
|
|
||||||
/* Update whether we want future constraint runs to require the
|
/* Update whether we want future constraint runs to require the
|
||||||
* window to be on fully onscreen.
|
* window to be on fully onscreen.
|
||||||
*/
|
*/
|
||||||
@@ -637,10 +658,13 @@ update_onscreen_requirements (MetaWindow *window,
|
|||||||
*/
|
*/
|
||||||
if (window->frame && window->decorated)
|
if (window->frame && window->decorated)
|
||||||
{
|
{
|
||||||
|
MetaFrameBorders borders;
|
||||||
MetaRectangle titlebar_rect;
|
MetaRectangle titlebar_rect;
|
||||||
|
|
||||||
meta_window_get_titlebar_rect (window, &titlebar_rect);
|
meta_frame_calc_borders (window->frame, &borders);
|
||||||
|
|
||||||
|
titlebar_rect = info->current;
|
||||||
|
titlebar_rect.height = borders.visible.top;
|
||||||
old = window->require_titlebar_visible;
|
old = window->require_titlebar_visible;
|
||||||
window->require_titlebar_visible =
|
window->require_titlebar_visible =
|
||||||
meta_rectangle_overlaps_with_region (info->usable_screen_region,
|
meta_rectangle_overlaps_with_region (info->usable_screen_region,
|
||||||
@@ -651,10 +675,28 @@ update_onscreen_requirements (MetaWindow *window,
|
|||||||
window->desc,
|
window->desc,
|
||||||
window->require_titlebar_visible ? "TRUE" : "FALSE");
|
window->require_titlebar_visible ? "TRUE" : "FALSE");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Don't forget to restore the position of the window */
|
||||||
|
unextend_by_frame (window, &info->current);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
extend_by_frame (MetaWindow *window,
|
||||||
|
MetaRectangle *rect)
|
||||||
|
{
|
||||||
|
meta_window_client_rect_to_frame_rect (window, rect, rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
unextend_by_frame (MetaWindow *window,
|
||||||
|
MetaRectangle *rect)
|
||||||
|
{
|
||||||
|
meta_window_frame_rect_to_client_rect (window, rect, rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
get_size_limits (MetaWindow *window,
|
get_size_limits (MetaWindow *window,
|
||||||
|
gboolean include_frame,
|
||||||
MetaRectangle *min_size,
|
MetaRectangle *min_size,
|
||||||
MetaRectangle *max_size)
|
MetaRectangle *max_size)
|
||||||
{
|
{
|
||||||
@@ -667,8 +709,11 @@ get_size_limits (MetaWindow *window,
|
|||||||
max_size->width = window->size_hints.max_width;
|
max_size->width = window->size_hints.max_width;
|
||||||
max_size->height = window->size_hints.max_height;
|
max_size->height = window->size_hints.max_height;
|
||||||
|
|
||||||
meta_window_client_rect_to_frame_rect (window, min_size, min_size);
|
if (include_frame)
|
||||||
meta_window_client_rect_to_frame_rect (window, max_size, max_size);
|
{
|
||||||
|
meta_window_client_rect_to_frame_rect (window, min_size, min_size);
|
||||||
|
meta_window_client_rect_to_frame_rect (window, max_size, max_size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@@ -692,11 +737,13 @@ constrain_modal_dialog (MetaWindow *window,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
child_rect = info->current;
|
child_rect = info->current;
|
||||||
|
extend_by_frame (window, &child_rect);
|
||||||
|
|
||||||
meta_window_get_frame_rect (parent, &parent_rect);
|
meta_window_get_frame_rect (parent, &parent_rect);
|
||||||
|
|
||||||
child_rect.x = parent_rect.x + (parent_rect.width / 2 - child_rect.width / 2);
|
child_rect.x = parent_rect.x + (parent_rect.width / 2 - child_rect.width / 2);
|
||||||
child_rect.y = parent_rect.y + (parent_rect.height / 2 - child_rect.height / 2);
|
child_rect.y = parent_rect.y + (parent_rect.height / 2 - child_rect.height / 2);
|
||||||
|
unextend_by_frame (window, &child_rect);
|
||||||
x = child_rect.x;
|
x = child_rect.x;
|
||||||
y = child_rect.y;
|
y = child_rect.y;
|
||||||
|
|
||||||
@@ -763,16 +810,19 @@ constrain_maximization (MetaWindow *window,
|
|||||||
active_workspace_struts = window->screen->active_workspace->all_struts;
|
active_workspace_struts = window->screen->active_workspace->all_struts;
|
||||||
|
|
||||||
target_size = info->current;
|
target_size = info->current;
|
||||||
|
extend_by_frame (window, &target_size);
|
||||||
meta_rectangle_expand_to_avoiding_struts (&target_size,
|
meta_rectangle_expand_to_avoiding_struts (&target_size,
|
||||||
&info->entire_monitor,
|
&info->entire_monitor,
|
||||||
direction,
|
direction,
|
||||||
active_workspace_struts);
|
active_workspace_struts);
|
||||||
}
|
}
|
||||||
|
/* Now make target_size = maximized size of client window */
|
||||||
|
unextend_by_frame (window, &target_size);
|
||||||
|
|
||||||
/* Check min size constraints; max size constraints are ignored for maximized
|
/* Check min size constraints; max size constraints are ignored for maximized
|
||||||
* windows, as per bug 327543.
|
* windows, as per bug 327543.
|
||||||
*/
|
*/
|
||||||
get_size_limits (window, &min_size, &max_size);
|
get_size_limits (window, FALSE, &min_size, &max_size);
|
||||||
hminbad = target_size.width < min_size.width && window->maximized_horizontally;
|
hminbad = target_size.width < min_size.width && window->maximized_horizontally;
|
||||||
vminbad = target_size.height < min_size.height && window->maximized_vertically;
|
vminbad = target_size.height < min_size.height && window->maximized_vertically;
|
||||||
if (hminbad || vminbad)
|
if (hminbad || vminbad)
|
||||||
@@ -826,11 +876,12 @@ constrain_tiling (MetaWindow *window,
|
|||||||
* use an external function for the actual calculation
|
* use an external function for the actual calculation
|
||||||
*/
|
*/
|
||||||
meta_window_get_current_tile_area (window, &target_size);
|
meta_window_get_current_tile_area (window, &target_size);
|
||||||
|
unextend_by_frame (window, &target_size);
|
||||||
|
|
||||||
/* Check min size constraints; max size constraints are ignored as for
|
/* Check min size constraints; max size constraints are ignored as for
|
||||||
* maximized windows.
|
* maximized windows.
|
||||||
*/
|
*/
|
||||||
get_size_limits (window, &min_size, &max_size);
|
get_size_limits (window, FALSE, &min_size, &max_size);
|
||||||
hminbad = target_size.width < min_size.width;
|
hminbad = target_size.width < min_size.width;
|
||||||
vminbad = target_size.height < min_size.height;
|
vminbad = target_size.height < min_size.height;
|
||||||
if (hminbad || vminbad)
|
if (hminbad || vminbad)
|
||||||
@@ -873,7 +924,7 @@ constrain_fullscreen (MetaWindow *window,
|
|||||||
|
|
||||||
monitor = info->entire_monitor;
|
monitor = info->entire_monitor;
|
||||||
|
|
||||||
get_size_limits (window, &min_size, &max_size);
|
get_size_limits (window, FALSE, &min_size, &max_size);
|
||||||
too_big = !meta_rectangle_could_fit_rect (&monitor, &min_size);
|
too_big = !meta_rectangle_could_fit_rect (&monitor, &min_size);
|
||||||
too_small = !meta_rectangle_could_fit_rect (&max_size, &monitor);
|
too_small = !meta_rectangle_could_fit_rect (&max_size, &monitor);
|
||||||
if (too_big || too_small)
|
if (too_big || too_small)
|
||||||
@@ -900,7 +951,6 @@ constrain_size_increments (MetaWindow *window,
|
|||||||
int new_width, new_height;
|
int new_width, new_height;
|
||||||
gboolean constraint_already_satisfied;
|
gboolean constraint_already_satisfied;
|
||||||
MetaRectangle *start_rect;
|
MetaRectangle *start_rect;
|
||||||
MetaRectangle client_rect;
|
|
||||||
|
|
||||||
if (priority > PRIORITY_SIZE_HINTS_INCREMENTS)
|
if (priority > PRIORITY_SIZE_HINTS_INCREMENTS)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@@ -911,15 +961,13 @@ constrain_size_increments (MetaWindow *window,
|
|||||||
info->action_type == ACTION_MOVE)
|
info->action_type == ACTION_MOVE)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
meta_window_frame_rect_to_client_rect (window, &info->current, &client_rect);
|
|
||||||
|
|
||||||
/* Determine whether constraint is already satisfied; exit if it is */
|
/* Determine whether constraint is already satisfied; exit if it is */
|
||||||
bh = window->size_hints.base_height;
|
bh = window->size_hints.base_height;
|
||||||
hi = window->size_hints.height_inc;
|
hi = window->size_hints.height_inc;
|
||||||
bw = window->size_hints.base_width;
|
bw = window->size_hints.base_width;
|
||||||
wi = window->size_hints.width_inc;
|
wi = window->size_hints.width_inc;
|
||||||
extra_height = (client_rect.height - bh) % hi;
|
extra_height = (info->current.height - bh) % hi;
|
||||||
extra_width = (client_rect.width - bw) % wi;
|
extra_width = (info->current.width - bw) % wi;
|
||||||
/* ignore size increments for maximized windows */
|
/* ignore size increments for maximized windows */
|
||||||
if (window->maximized_horizontally)
|
if (window->maximized_horizontally)
|
||||||
extra_width *= 0;
|
extra_width *= 0;
|
||||||
@@ -933,8 +981,8 @@ constrain_size_increments (MetaWindow *window,
|
|||||||
return constraint_already_satisfied;
|
return constraint_already_satisfied;
|
||||||
|
|
||||||
/*** Enforce constraint ***/
|
/*** Enforce constraint ***/
|
||||||
new_width = client_rect.width - extra_width;
|
new_width = info->current.width - extra_width;
|
||||||
new_height = client_rect.height - extra_height;
|
new_height = info->current.height - extra_height;
|
||||||
|
|
||||||
/* Adjusting down instead of up (as done in the above two lines) may
|
/* Adjusting down instead of up (as done in the above two lines) may
|
||||||
* violate minimum size constraints; fix the adjustment if this
|
* violate minimum size constraints; fix the adjustment if this
|
||||||
@@ -945,14 +993,6 @@ constrain_size_increments (MetaWindow *window,
|
|||||||
if (new_height < window->size_hints.min_height)
|
if (new_height < window->size_hints.min_height)
|
||||||
new_height += ((window->size_hints.min_height - new_height)/hi + 1)*hi;
|
new_height += ((window->size_hints.min_height - new_height)/hi + 1)*hi;
|
||||||
|
|
||||||
{
|
|
||||||
client_rect.width = new_width;
|
|
||||||
client_rect.height = new_height;
|
|
||||||
meta_window_client_rect_to_frame_rect (window, &client_rect, &client_rect);
|
|
||||||
new_width = client_rect.width;
|
|
||||||
new_height = client_rect.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Figure out what original rect to pass to meta_rectangle_resize_with_gravity
|
/* Figure out what original rect to pass to meta_rectangle_resize_with_gravity
|
||||||
* See bug 448183
|
* See bug 448183
|
||||||
*/
|
*/
|
||||||
@@ -993,7 +1033,7 @@ constrain_size_limits (MetaWindow *window,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* Determine whether constraint is already satisfied; exit if it is */
|
/* Determine whether constraint is already satisfied; exit if it is */
|
||||||
get_size_limits (window, &min_size, &max_size);
|
get_size_limits (window, FALSE, &min_size, &max_size);
|
||||||
/* We ignore max-size limits for maximized windows; see #327543 */
|
/* We ignore max-size limits for maximized windows; see #327543 */
|
||||||
if (window->maximized_horizontally)
|
if (window->maximized_horizontally)
|
||||||
max_size.width = MAX (max_size.width, info->current.width);
|
max_size.width = MAX (max_size.width, info->current.width);
|
||||||
@@ -1185,7 +1225,8 @@ do_screen_and_monitor_relative_constraints (
|
|||||||
|
|
||||||
/* Determine whether constraint applies; exit if it doesn't */
|
/* Determine whether constraint applies; exit if it doesn't */
|
||||||
how_far_it_can_be_smushed = info->current;
|
how_far_it_can_be_smushed = info->current;
|
||||||
get_size_limits (window, &min_size, &max_size);
|
get_size_limits (window, TRUE, &min_size, &max_size);
|
||||||
|
extend_by_frame (window, &info->current);
|
||||||
|
|
||||||
if (info->action_type != ACTION_MOVE)
|
if (info->action_type != ACTION_MOVE)
|
||||||
{
|
{
|
||||||
@@ -1204,7 +1245,10 @@ do_screen_and_monitor_relative_constraints (
|
|||||||
meta_rectangle_contained_in_region (region_spanning_rectangles,
|
meta_rectangle_contained_in_region (region_spanning_rectangles,
|
||||||
&info->current);
|
&info->current);
|
||||||
if (exit_early || constraint_satisfied || check_only)
|
if (exit_early || constraint_satisfied || check_only)
|
||||||
return constraint_satisfied;
|
{
|
||||||
|
unextend_by_frame (window, &info->current);
|
||||||
|
return constraint_satisfied;
|
||||||
|
}
|
||||||
|
|
||||||
/* Enforce constraint */
|
/* Enforce constraint */
|
||||||
|
|
||||||
@@ -1226,6 +1270,7 @@ do_screen_and_monitor_relative_constraints (
|
|||||||
info->fixed_directions,
|
info->fixed_directions,
|
||||||
&info->current);
|
&info->current);
|
||||||
|
|
||||||
|
unextend_by_frame (window, &info->current);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
347
src/core/core.c
347
src/core/core.c
@@ -86,56 +86,78 @@ meta_core_get (Display *xdisplay,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (request != META_CORE_WINDOW_HAS_FRAME &&
|
if (request != META_CORE_WINDOW_HAS_FRAME &&
|
||||||
(window == NULL || window->frame == NULL))
|
(window == NULL || window->frame == NULL)) {
|
||||||
{
|
meta_bug ("No such frame window 0x%lx!\n", xwindow);
|
||||||
meta_bug ("No such frame window 0x%lx!\n", xwindow);
|
goto out;
|
||||||
goto out;
|
}
|
||||||
|
|
||||||
|
while (request != META_CORE_GET_END) {
|
||||||
|
|
||||||
|
gpointer answer = va_arg (args, gpointer);
|
||||||
|
|
||||||
|
switch (request) {
|
||||||
|
case META_CORE_WINDOW_HAS_FRAME:
|
||||||
|
*((gboolean*)answer) = window != NULL && window->frame != NULL;
|
||||||
|
if (!*((gboolean*)answer)) goto out; /* see above */
|
||||||
|
break;
|
||||||
|
case META_CORE_GET_CLIENT_WIDTH:
|
||||||
|
*((gint*)answer) = window->rect.width;
|
||||||
|
break;
|
||||||
|
case META_CORE_GET_CLIENT_HEIGHT:
|
||||||
|
*((gint*)answer) = window->rect.height;
|
||||||
|
break;
|
||||||
|
case META_CORE_GET_CLIENT_XWINDOW:
|
||||||
|
*((Window*)answer) = window->xwindow;
|
||||||
|
break;
|
||||||
|
case META_CORE_GET_FRAME_FLAGS:
|
||||||
|
*((MetaFrameFlags*)answer) = meta_frame_get_flags (window->frame);
|
||||||
|
break;
|
||||||
|
case META_CORE_GET_FRAME_TYPE:
|
||||||
|
*((MetaFrameType*)answer) = meta_window_get_frame_type (window);
|
||||||
|
break;
|
||||||
|
case META_CORE_GET_MINI_ICON:
|
||||||
|
*((GdkPixbuf**)answer) = window->mini_icon;
|
||||||
|
break;
|
||||||
|
case META_CORE_GET_ICON:
|
||||||
|
*((GdkPixbuf**)answer) = window->icon;
|
||||||
|
break;
|
||||||
|
case META_CORE_GET_X:
|
||||||
|
meta_window_get_position (window, (int*)answer, NULL);
|
||||||
|
break;
|
||||||
|
case META_CORE_GET_Y:
|
||||||
|
meta_window_get_position (window, NULL, (int*)answer);
|
||||||
|
break;
|
||||||
|
case META_CORE_GET_FRAME_WORKSPACE:
|
||||||
|
*((gint*)answer) = meta_window_get_net_wm_desktop (window);
|
||||||
|
break;
|
||||||
|
case META_CORE_GET_FRAME_X:
|
||||||
|
*((gint*)answer) = window->frame->rect.x;
|
||||||
|
break;
|
||||||
|
case META_CORE_GET_FRAME_Y:
|
||||||
|
*((gint*)answer) = window->frame->rect.y;
|
||||||
|
break;
|
||||||
|
case META_CORE_GET_FRAME_WIDTH:
|
||||||
|
*((gint*)answer) = window->frame->rect.width;
|
||||||
|
break;
|
||||||
|
case META_CORE_GET_FRAME_HEIGHT:
|
||||||
|
*((gint*)answer) = window->frame->rect.height;
|
||||||
|
break;
|
||||||
|
case META_CORE_GET_THEME_VARIANT:
|
||||||
|
*((char**)answer) = window->gtk_theme_variant;
|
||||||
|
break;
|
||||||
|
case META_CORE_GET_SCREEN_WIDTH:
|
||||||
|
*((gint*)answer) = window->screen->rect.width;
|
||||||
|
break;
|
||||||
|
case META_CORE_GET_SCREEN_HEIGHT:
|
||||||
|
*((gint*)answer) = window->screen->rect.height;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
meta_warning("Unknown window information request: %d\n", request);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (request != META_CORE_GET_END)
|
request = va_arg (args, MetaCoreGetType);
|
||||||
{
|
}
|
||||||
gpointer answer = va_arg (args, gpointer);
|
|
||||||
|
|
||||||
switch (request)
|
|
||||||
{
|
|
||||||
case META_CORE_WINDOW_HAS_FRAME:
|
|
||||||
*((gboolean*)answer) = window != NULL && window->frame != NULL;
|
|
||||||
if (!*((gboolean*)answer)) goto out; /* see above */
|
|
||||||
break;
|
|
||||||
case META_CORE_GET_CLIENT_WIDTH:
|
|
||||||
*((gint*)answer) = window->rect.width;
|
|
||||||
break;
|
|
||||||
case META_CORE_GET_CLIENT_HEIGHT:
|
|
||||||
*((gint*)answer) = window->rect.height;
|
|
||||||
break;
|
|
||||||
case META_CORE_GET_FRAME_FLAGS:
|
|
||||||
*((MetaFrameFlags*)answer) = meta_frame_get_flags (window->frame);
|
|
||||||
break;
|
|
||||||
case META_CORE_GET_FRAME_TYPE:
|
|
||||||
*((MetaFrameType*)answer) = meta_window_get_frame_type (window);
|
|
||||||
break;
|
|
||||||
case META_CORE_GET_MINI_ICON:
|
|
||||||
*((GdkPixbuf**)answer) = window->mini_icon;
|
|
||||||
break;
|
|
||||||
case META_CORE_GET_ICON:
|
|
||||||
*((GdkPixbuf**)answer) = window->icon;
|
|
||||||
break;
|
|
||||||
case META_CORE_GET_FRAME_WIDTH:
|
|
||||||
*((gint*)answer) = window->frame->rect.width;
|
|
||||||
break;
|
|
||||||
case META_CORE_GET_FRAME_HEIGHT:
|
|
||||||
*((gint*)answer) = window->frame->rect.height;
|
|
||||||
break;
|
|
||||||
case META_CORE_GET_THEME_VARIANT:
|
|
||||||
*((char**)answer) = window->gtk_theme_variant;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
meta_warning("Unknown window information request: %d\n", request);
|
|
||||||
}
|
|
||||||
|
|
||||||
request = va_arg (args, MetaCoreGetType);
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
va_end (args);
|
va_end (args);
|
||||||
@@ -151,6 +173,38 @@ meta_core_queue_frame_resize (Display *xdisplay,
|
|||||||
meta_window_frame_size_changed (window);
|
meta_window_frame_size_changed (window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_core_user_move (Display *xdisplay,
|
||||||
|
Window frame_xwindow,
|
||||||
|
int x,
|
||||||
|
int y)
|
||||||
|
{
|
||||||
|
MetaWindow *window = get_window (xdisplay, frame_xwindow);
|
||||||
|
|
||||||
|
meta_window_move (window, TRUE, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_core_user_resize (Display *xdisplay,
|
||||||
|
Window frame_xwindow,
|
||||||
|
int gravity,
|
||||||
|
int width,
|
||||||
|
int height)
|
||||||
|
{
|
||||||
|
MetaWindow *window = get_window (xdisplay, frame_xwindow);
|
||||||
|
|
||||||
|
meta_window_resize_with_gravity (window, TRUE, width, height, gravity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_core_user_raise (Display *xdisplay,
|
||||||
|
Window frame_xwindow)
|
||||||
|
{
|
||||||
|
MetaWindow *window = get_window (xdisplay, frame_xwindow);
|
||||||
|
|
||||||
|
meta_window_raise (window);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
lower_window_and_transients (MetaWindow *window,
|
lower_window_and_transients (MetaWindow *window,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
@@ -207,6 +261,45 @@ meta_core_user_lower_and_unfocus (Display *xdisplay,
|
|||||||
timestamp);
|
timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_core_lower_beneath_grab_window (Display *xdisplay,
|
||||||
|
Window xwindow,
|
||||||
|
guint32 timestamp)
|
||||||
|
{
|
||||||
|
XWindowChanges changes;
|
||||||
|
MetaDisplay *display;
|
||||||
|
MetaScreen *screen;
|
||||||
|
MetaWindow *grab_window;
|
||||||
|
MetaStackWindow stack_window;
|
||||||
|
MetaStackWindow stack_sibling;
|
||||||
|
|
||||||
|
display = meta_display_for_x_display (xdisplay);
|
||||||
|
screen = display->screen;
|
||||||
|
grab_window = display->grab_window;
|
||||||
|
|
||||||
|
if (grab_window == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
changes.stack_mode = Below;
|
||||||
|
changes.sibling = meta_window_get_toplevel_xwindow (grab_window);
|
||||||
|
|
||||||
|
stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
|
||||||
|
stack_window.x11.xwindow = xwindow;
|
||||||
|
stack_sibling.any.type = META_WINDOW_CLIENT_TYPE_X11;
|
||||||
|
stack_sibling.x11.xwindow = changes.sibling;
|
||||||
|
meta_stack_tracker_record_lower_below (screen->stack_tracker,
|
||||||
|
&stack_window,
|
||||||
|
&stack_sibling,
|
||||||
|
XNextRequest (screen->display->xdisplay));
|
||||||
|
|
||||||
|
meta_error_trap_push (display);
|
||||||
|
XConfigureWindow (xdisplay,
|
||||||
|
xwindow,
|
||||||
|
CWSibling | CWStackMode,
|
||||||
|
&changes);
|
||||||
|
meta_error_trap_pop (display);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_core_user_focus (Display *xdisplay,
|
meta_core_user_focus (Display *xdisplay,
|
||||||
Window frame_xwindow,
|
Window frame_xwindow,
|
||||||
@@ -374,12 +467,12 @@ meta_core_change_workspace (Display *xdisplay,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_core_show_window_menu (Display *xdisplay,
|
meta_core_show_window_menu (Display *xdisplay,
|
||||||
Window frame_xwindow,
|
Window frame_xwindow,
|
||||||
MetaWindowMenuType menu,
|
int root_x,
|
||||||
int root_x,
|
int root_y,
|
||||||
int root_y,
|
int button,
|
||||||
guint32 timestamp)
|
guint32 timestamp)
|
||||||
{
|
{
|
||||||
MetaWindow *window = get_window (xdisplay, frame_xwindow);
|
MetaWindow *window = get_window (xdisplay, frame_xwindow);
|
||||||
|
|
||||||
@@ -387,7 +480,121 @@ meta_core_show_window_menu (Display *xdisplay,
|
|||||||
meta_window_raise (window);
|
meta_window_raise (window);
|
||||||
meta_window_focus (window, timestamp);
|
meta_window_focus (window, timestamp);
|
||||||
|
|
||||||
meta_window_show_menu (window, menu, root_x, root_y);
|
meta_window_show_menu (window, root_x, root_y, button, timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_core_get_menu_accelerator (MetaMenuOp menu_op,
|
||||||
|
int workspace,
|
||||||
|
unsigned int *keysym,
|
||||||
|
MetaVirtualModifier *modifiers)
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
name = NULL;
|
||||||
|
|
||||||
|
switch (menu_op)
|
||||||
|
{
|
||||||
|
case META_MENU_OP_NONE:
|
||||||
|
/* No keybinding for this one */
|
||||||
|
break;
|
||||||
|
case META_MENU_OP_DELETE:
|
||||||
|
name = "close";
|
||||||
|
break;
|
||||||
|
case META_MENU_OP_MINIMIZE:
|
||||||
|
name = "minimize";
|
||||||
|
break;
|
||||||
|
case META_MENU_OP_UNMAXIMIZE:
|
||||||
|
name = "unmaximize";
|
||||||
|
break;
|
||||||
|
case META_MENU_OP_MAXIMIZE:
|
||||||
|
name = "maximize";
|
||||||
|
break;
|
||||||
|
case META_MENU_OP_UNSHADE:
|
||||||
|
case META_MENU_OP_SHADE:
|
||||||
|
name = "toggle_shaded";
|
||||||
|
break;
|
||||||
|
case META_MENU_OP_UNSTICK:
|
||||||
|
case META_MENU_OP_STICK:
|
||||||
|
name = "toggle-on-all-workspaces";
|
||||||
|
break;
|
||||||
|
case META_MENU_OP_ABOVE:
|
||||||
|
case META_MENU_OP_UNABOVE:
|
||||||
|
name = "toggle-above";
|
||||||
|
break;
|
||||||
|
case META_MENU_OP_WORKSPACES:
|
||||||
|
switch (workspace)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
name = "move-to-workspace-1";
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
name = "move-to-workspace-2";
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
name = "move-to-workspace-3";
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
name = "move-to-workspace-4";
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
name = "move-to-workspace-5";
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
name = "move-to-workspace-6";
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
name = "move-to-workspace-7";
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
name = "move-to-workspace-8";
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
name = "move-to-workspace-9";
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
name = "move-to-workspace-10";
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
name = "move-to-workspace-11";
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
name = "move-to-workspace-12";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case META_MENU_OP_MOVE:
|
||||||
|
name = "begin-move";
|
||||||
|
break;
|
||||||
|
case META_MENU_OP_RESIZE:
|
||||||
|
name = "begin-resize";
|
||||||
|
break;
|
||||||
|
case META_MENU_OP_MOVE_LEFT:
|
||||||
|
name = "move-to-workspace-left";
|
||||||
|
break;
|
||||||
|
case META_MENU_OP_MOVE_RIGHT:
|
||||||
|
name = "move-to-workspace-right";
|
||||||
|
break;
|
||||||
|
case META_MENU_OP_MOVE_UP:
|
||||||
|
name = "move-to-workspace-up";
|
||||||
|
break;
|
||||||
|
case META_MENU_OP_MOVE_DOWN:
|
||||||
|
name = "move-to-workspace-down";
|
||||||
|
break;
|
||||||
|
case META_MENU_OP_RECOVER:
|
||||||
|
/* No keybinding for this one */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name)
|
||||||
|
{
|
||||||
|
meta_prefs_get_window_binding (name, keysym, modifiers);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*keysym = 0;
|
||||||
|
*modifiers = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
@@ -452,6 +659,36 @@ meta_core_get_grab_op (Display *xdisplay)
|
|||||||
return display->grab_op;
|
return display->grab_op;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Window
|
||||||
|
meta_core_get_grab_frame (Display *xdisplay)
|
||||||
|
{
|
||||||
|
MetaDisplay *display;
|
||||||
|
|
||||||
|
display = meta_display_for_x_display (xdisplay);
|
||||||
|
|
||||||
|
g_assert (display != NULL);
|
||||||
|
|
||||||
|
if (display->grab_op != META_GRAB_OP_NONE &&
|
||||||
|
display->grab_window &&
|
||||||
|
display->grab_window->frame)
|
||||||
|
return display->grab_window->frame->xwindow;
|
||||||
|
else
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
meta_core_get_grab_button (Display *xdisplay)
|
||||||
|
{
|
||||||
|
MetaDisplay *display;
|
||||||
|
|
||||||
|
display = meta_display_for_x_display (xdisplay);
|
||||||
|
|
||||||
|
if (display->grab_op == META_GRAB_OP_NONE)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return display->grab_button;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_core_grab_buttons (Display *xdisplay,
|
meta_core_grab_buttons (Display *xdisplay,
|
||||||
Window frame_xwindow)
|
Window frame_xwindow)
|
||||||
|
@@ -33,13 +33,21 @@ typedef enum
|
|||||||
META_CORE_WINDOW_HAS_FRAME,
|
META_CORE_WINDOW_HAS_FRAME,
|
||||||
META_CORE_GET_CLIENT_WIDTH,
|
META_CORE_GET_CLIENT_WIDTH,
|
||||||
META_CORE_GET_CLIENT_HEIGHT,
|
META_CORE_GET_CLIENT_HEIGHT,
|
||||||
|
META_CORE_GET_CLIENT_XWINDOW,
|
||||||
META_CORE_GET_FRAME_FLAGS,
|
META_CORE_GET_FRAME_FLAGS,
|
||||||
META_CORE_GET_FRAME_TYPE,
|
META_CORE_GET_FRAME_TYPE,
|
||||||
META_CORE_GET_MINI_ICON,
|
META_CORE_GET_MINI_ICON,
|
||||||
META_CORE_GET_ICON,
|
META_CORE_GET_ICON,
|
||||||
|
META_CORE_GET_X,
|
||||||
|
META_CORE_GET_Y,
|
||||||
|
META_CORE_GET_FRAME_WORKSPACE,
|
||||||
|
META_CORE_GET_FRAME_X,
|
||||||
|
META_CORE_GET_FRAME_Y,
|
||||||
META_CORE_GET_FRAME_WIDTH,
|
META_CORE_GET_FRAME_WIDTH,
|
||||||
META_CORE_GET_FRAME_HEIGHT,
|
META_CORE_GET_FRAME_HEIGHT,
|
||||||
META_CORE_GET_THEME_VARIANT,
|
META_CORE_GET_THEME_VARIANT,
|
||||||
|
META_CORE_GET_SCREEN_WIDTH,
|
||||||
|
META_CORE_GET_SCREEN_HEIGHT,
|
||||||
} MetaCoreGetType;
|
} MetaCoreGetType;
|
||||||
|
|
||||||
/* General information function about the given window. Pass in a sequence of
|
/* General information function about the given window. Pass in a sequence of
|
||||||
@@ -48,8 +56,8 @@ typedef enum
|
|||||||
* For example:
|
* For example:
|
||||||
*
|
*
|
||||||
* meta_core_get (my_display, my_window,
|
* meta_core_get (my_display, my_window,
|
||||||
* META_CORE_GET_FRAME_WIDTH, &width,
|
* META_CORE_GET_X, &x,
|
||||||
* META_CORE_GET_FRAME_HEIGHT, &height,
|
* META_CORE_GET_Y, &y,
|
||||||
* META_CORE_GET_END);
|
* META_CORE_GET_END);
|
||||||
*
|
*
|
||||||
* If the window doesn't have a frame, this will raise a meta_bug. To suppress
|
* If the window doesn't have a frame, this will raise a meta_bug. To suppress
|
||||||
@@ -85,6 +93,19 @@ void meta_core_get (Display *xdisplay,
|
|||||||
void meta_core_queue_frame_resize (Display *xdisplay,
|
void meta_core_queue_frame_resize (Display *xdisplay,
|
||||||
Window frame_xwindow);
|
Window frame_xwindow);
|
||||||
|
|
||||||
|
/* Move as a result of user operation */
|
||||||
|
void meta_core_user_move (Display *xdisplay,
|
||||||
|
Window frame_xwindow,
|
||||||
|
int x,
|
||||||
|
int y);
|
||||||
|
void meta_core_user_resize (Display *xdisplay,
|
||||||
|
Window frame_xwindow,
|
||||||
|
int gravity,
|
||||||
|
int width,
|
||||||
|
int height);
|
||||||
|
|
||||||
|
void meta_core_user_raise (Display *xdisplay,
|
||||||
|
Window frame_xwindow);
|
||||||
void meta_core_user_lower_and_unfocus (Display *xdisplay,
|
void meta_core_user_lower_and_unfocus (Display *xdisplay,
|
||||||
Window frame_xwindow,
|
Window frame_xwindow,
|
||||||
guint32 timestamp);
|
guint32 timestamp);
|
||||||
@@ -93,6 +114,10 @@ void meta_core_user_focus (Display *xdisplay,
|
|||||||
Window frame_xwindow,
|
Window frame_xwindow,
|
||||||
guint32 timestamp);
|
guint32 timestamp);
|
||||||
|
|
||||||
|
void meta_core_lower_beneath_grab_window (Display *xdisplay,
|
||||||
|
Window xwindow,
|
||||||
|
guint32 timestamp);
|
||||||
|
|
||||||
void meta_core_minimize (Display *xdisplay,
|
void meta_core_minimize (Display *xdisplay,
|
||||||
Window frame_xwindow);
|
Window frame_xwindow);
|
||||||
void meta_core_toggle_maximize (Display *xdisplay,
|
void meta_core_toggle_maximize (Display *xdisplay,
|
||||||
@@ -132,12 +157,17 @@ const char* meta_core_get_workspace_name_with_index (Display *xdisplay,
|
|||||||
Window xroot,
|
Window xroot,
|
||||||
int index);
|
int index);
|
||||||
|
|
||||||
void meta_core_show_window_menu (Display *xdisplay,
|
void meta_core_show_window_menu (Display *xdisplay,
|
||||||
Window frame_xwindow,
|
Window frame_xwindow,
|
||||||
MetaWindowMenuType menu,
|
int root_x,
|
||||||
int root_x,
|
int root_y,
|
||||||
int root_y,
|
int button,
|
||||||
guint32 timestamp);
|
guint32 timestamp);
|
||||||
|
|
||||||
|
void meta_core_get_menu_accelerator (MetaMenuOp menu_op,
|
||||||
|
int workspace,
|
||||||
|
unsigned int *keysym,
|
||||||
|
MetaVirtualModifier *modifiers);
|
||||||
|
|
||||||
gboolean meta_core_begin_grab_op (Display *xdisplay,
|
gboolean meta_core_begin_grab_op (Display *xdisplay,
|
||||||
Window frame_xwindow,
|
Window frame_xwindow,
|
||||||
@@ -152,6 +182,8 @@ gboolean meta_core_begin_grab_op (Display *xdisplay,
|
|||||||
void meta_core_end_grab_op (Display *xdisplay,
|
void meta_core_end_grab_op (Display *xdisplay,
|
||||||
guint32 timestamp);
|
guint32 timestamp);
|
||||||
MetaGrabOp meta_core_get_grab_op (Display *xdisplay);
|
MetaGrabOp meta_core_get_grab_op (Display *xdisplay);
|
||||||
|
Window meta_core_get_grab_frame (Display *xdisplay);
|
||||||
|
int meta_core_get_grab_button (Display *xdisplay);
|
||||||
|
|
||||||
|
|
||||||
void meta_core_grab_buttons (Display *xdisplay,
|
void meta_core_grab_buttons (Display *xdisplay,
|
||||||
|
@@ -39,58 +39,35 @@
|
|||||||
|
|
||||||
#include "wayland/meta-wayland-surface.h"
|
#include "wayland/meta-wayland-surface.h"
|
||||||
|
|
||||||
|
static void meta_window_present_delete_dialog (MetaWindow *window,
|
||||||
|
guint32 timestamp);
|
||||||
|
|
||||||
|
static void
|
||||||
|
delete_ping_reply_func (MetaWindow *window,
|
||||||
|
guint32 timestamp,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
meta_topic (META_DEBUG_PING, "Got reply to delete ping for %s\n", window->desc);
|
||||||
|
|
||||||
|
/* we do nothing */
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dialog_exited (GPid pid, int status, gpointer user_data)
|
dialog_exited (GPid pid, int status, gpointer user_data)
|
||||||
{
|
{
|
||||||
MetaWindow *window = user_data;
|
MetaWindow *ours = (MetaWindow*) user_data;
|
||||||
|
|
||||||
window->dialog_pid = -1;
|
ours->dialog_pid = -1;
|
||||||
|
|
||||||
/* exit status of 1 means the user pressed "Force Quit" */
|
/* exit status of 1 means the user pressed "Force Quit" */
|
||||||
if (WIFEXITED (status) && WEXITSTATUS (status) == 1)
|
if (WIFEXITED (status) && WEXITSTATUS (status) == 1)
|
||||||
meta_window_kill (window);
|
meta_window_kill (ours);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
present_existing_delete_dialog (MetaWindow *window,
|
delete_ping_timeout_func (MetaWindow *window,
|
||||||
guint32 timestamp)
|
guint32 timestamp,
|
||||||
{
|
void *user_data)
|
||||||
meta_topic (META_DEBUG_PING,
|
|
||||||
"Presenting existing ping dialog for %s\n",
|
|
||||||
window->desc);
|
|
||||||
|
|
||||||
if (window->dialog_pid >= 0)
|
|
||||||
{
|
|
||||||
GSList *windows;
|
|
||||||
GSList *tmp;
|
|
||||||
|
|
||||||
/* Activate transient for window that belongs to
|
|
||||||
* mutter-dialog
|
|
||||||
*/
|
|
||||||
|
|
||||||
windows = meta_display_list_windows (window->display, META_LIST_DEFAULT);
|
|
||||||
tmp = windows;
|
|
||||||
while (tmp != NULL)
|
|
||||||
{
|
|
||||||
MetaWindow *w = tmp->data;
|
|
||||||
|
|
||||||
if (w->transient_for == window && w->res_class &&
|
|
||||||
g_ascii_strcasecmp (w->res_class, "mutter-dialog") == 0)
|
|
||||||
{
|
|
||||||
meta_window_activate (w, timestamp);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp = tmp->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_slist_free (windows);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
show_delete_dialog (MetaWindow *window,
|
|
||||||
guint32 timestamp)
|
|
||||||
{
|
{
|
||||||
char *window_title;
|
char *window_title;
|
||||||
gchar *window_content, *tmp;
|
gchar *window_content, *tmp;
|
||||||
@@ -102,7 +79,7 @@ show_delete_dialog (MetaWindow *window,
|
|||||||
|
|
||||||
if (window->dialog_pid >= 0)
|
if (window->dialog_pid >= 0)
|
||||||
{
|
{
|
||||||
present_existing_delete_dialog (window, timestamp);
|
meta_window_present_delete_dialog (window, timestamp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,33 +128,15 @@ show_delete_dialog (MetaWindow *window,
|
|||||||
g_child_watch_add (dialog_pid, dialog_exited, window);
|
g_child_watch_add (dialog_pid, dialog_exited, window);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
kill_delete_dialog (MetaWindow *window)
|
|
||||||
{
|
|
||||||
if (window->dialog_pid > -1)
|
|
||||||
kill (window->dialog_pid, SIGTERM);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
meta_window_set_alive (MetaWindow *window,
|
|
||||||
gboolean is_alive)
|
|
||||||
{
|
|
||||||
if (window->is_alive == is_alive)
|
|
||||||
return;
|
|
||||||
|
|
||||||
window->is_alive = is_alive;
|
|
||||||
|
|
||||||
if (window->is_alive)
|
|
||||||
kill_delete_dialog (window);
|
|
||||||
else
|
|
||||||
show_delete_dialog (window, CurrentTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_window_check_alive (MetaWindow *window,
|
meta_window_check_alive (MetaWindow *window,
|
||||||
guint32 timestamp)
|
guint32 timestamp)
|
||||||
{
|
{
|
||||||
meta_display_ping_window (window, timestamp);
|
meta_display_ping_window (window,
|
||||||
|
timestamp,
|
||||||
|
delete_ping_reply_func,
|
||||||
|
delete_ping_timeout_func,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -232,3 +191,39 @@ meta_window_free_delete_dialog (MetaWindow *window)
|
|||||||
window->dialog_pid = -1;
|
window->dialog_pid = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_window_present_delete_dialog (MetaWindow *window, guint32 timestamp)
|
||||||
|
{
|
||||||
|
meta_topic (META_DEBUG_PING,
|
||||||
|
"Presenting existing ping dialog for %s\n",
|
||||||
|
window->desc);
|
||||||
|
|
||||||
|
if (window->dialog_pid >= 0)
|
||||||
|
{
|
||||||
|
GSList *windows;
|
||||||
|
GSList *tmp;
|
||||||
|
|
||||||
|
/* Activate transient for window that belongs to
|
||||||
|
* mutter-dialog
|
||||||
|
*/
|
||||||
|
|
||||||
|
windows = meta_display_list_windows (window->display, META_LIST_DEFAULT);
|
||||||
|
tmp = windows;
|
||||||
|
while (tmp != NULL)
|
||||||
|
{
|
||||||
|
MetaWindow *w = tmp->data;
|
||||||
|
|
||||||
|
if (w->transient_for == window && w->res_class &&
|
||||||
|
g_ascii_strcasecmp (w->res_class, "mutter-dialog") == 0)
|
||||||
|
{
|
||||||
|
meta_window_activate (w, timestamp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = tmp->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_slist_free (windows);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -43,7 +43,9 @@
|
|||||||
#include <libsn/sn.h>
|
#include <libsn/sn.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_XSYNC
|
||||||
#include <X11/extensions/sync.h>
|
#include <X11/extensions/sync.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct _MetaStack MetaStack;
|
typedef struct _MetaStack MetaStack;
|
||||||
typedef struct _MetaUISlave MetaUISlave;
|
typedef struct _MetaUISlave MetaUISlave;
|
||||||
@@ -53,6 +55,10 @@ typedef struct _MetaWindowPropHooks MetaWindowPropHooks;
|
|||||||
|
|
||||||
typedef struct MetaEdgeResistanceData MetaEdgeResistanceData;
|
typedef struct MetaEdgeResistanceData MetaEdgeResistanceData;
|
||||||
|
|
||||||
|
typedef void (* MetaWindowPingFunc) (MetaWindow *window,
|
||||||
|
guint32 timestamp,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
META_LIST_DEFAULT = 0, /* normal windows */
|
META_LIST_DEFAULT = 0, /* normal windows */
|
||||||
META_LIST_INCLUDE_OVERRIDE_REDIRECT = 1 << 0, /* normal and O-R */
|
META_LIST_INCLUDE_OVERRIDE_REDIRECT = 1 << 0, /* normal and O-R */
|
||||||
@@ -141,10 +147,13 @@ struct _MetaDisplay
|
|||||||
guint focused_by_us : 1;
|
guint focused_by_us : 1;
|
||||||
|
|
||||||
/*< private-ish >*/
|
/*< private-ish >*/
|
||||||
|
guint error_trap_synced_at_last_pop : 1;
|
||||||
MetaScreen *screen;
|
MetaScreen *screen;
|
||||||
GHashTable *xids;
|
GHashTable *xids;
|
||||||
GHashTable *wayland_windows;
|
GHashTable *wayland_windows;
|
||||||
|
int error_traps;
|
||||||
|
int (* error_trap_handler) (Display *display,
|
||||||
|
XErrorEvent *error);
|
||||||
int server_grab_count;
|
int server_grab_count;
|
||||||
|
|
||||||
/* serials of leave/unmap events that may
|
/* serials of leave/unmap events that may
|
||||||
@@ -190,6 +199,7 @@ struct _MetaDisplay
|
|||||||
int grab_tile_monitor_number;
|
int grab_tile_monitor_number;
|
||||||
int grab_latest_motion_x;
|
int grab_latest_motion_x;
|
||||||
int grab_latest_motion_y;
|
int grab_latest_motion_y;
|
||||||
|
gulong grab_mask;
|
||||||
guint grab_have_pointer : 1;
|
guint grab_have_pointer : 1;
|
||||||
guint grab_have_keyboard : 1;
|
guint grab_have_keyboard : 1;
|
||||||
guint grab_frame_action : 1;
|
guint grab_frame_action : 1;
|
||||||
@@ -199,7 +209,9 @@ struct _MetaDisplay
|
|||||||
MetaRectangle grab_initial_window_pos;
|
MetaRectangle grab_initial_window_pos;
|
||||||
int grab_initial_x, grab_initial_y; /* These are only relevant for */
|
int grab_initial_x, grab_initial_y; /* These are only relevant for */
|
||||||
gboolean grab_threshold_movement_reached; /* raise_on_click == FALSE. */
|
gboolean grab_threshold_movement_reached; /* raise_on_click == FALSE. */
|
||||||
|
MetaResizePopup *grab_resize_popup;
|
||||||
GTimeVal grab_last_moveresize_time;
|
GTimeVal grab_last_moveresize_time;
|
||||||
|
GList* grab_old_window_stacking;
|
||||||
MetaEdgeResistanceData *grab_edge_resistance_data;
|
MetaEdgeResistanceData *grab_edge_resistance_data;
|
||||||
unsigned int grab_last_user_action_was_snap;
|
unsigned int grab_last_user_action_was_snap;
|
||||||
guint32 grab_timestamp;
|
guint32 grab_timestamp;
|
||||||
@@ -222,7 +234,11 @@ struct _MetaDisplay
|
|||||||
int max_keycode;
|
int max_keycode;
|
||||||
KeySym *keymap;
|
KeySym *keymap;
|
||||||
int keysyms_per_keycode;
|
int keysyms_per_keycode;
|
||||||
|
XModifierKeymap *modmap;
|
||||||
|
unsigned int above_tab_keycode;
|
||||||
unsigned int ignored_modifier_mask;
|
unsigned int ignored_modifier_mask;
|
||||||
|
unsigned int num_lock_mask;
|
||||||
|
unsigned int scroll_lock_mask;
|
||||||
unsigned int hyper_mask;
|
unsigned int hyper_mask;
|
||||||
unsigned int super_mask;
|
unsigned int super_mask;
|
||||||
unsigned int meta_mask;
|
unsigned int meta_mask;
|
||||||
@@ -243,6 +259,10 @@ struct _MetaDisplay
|
|||||||
/* Managed by group.c */
|
/* Managed by group.c */
|
||||||
GHashTable *groups_by_leader;
|
GHashTable *groups_by_leader;
|
||||||
|
|
||||||
|
/* currently-active window menu if any */
|
||||||
|
MetaWindowMenu *window_menu;
|
||||||
|
MetaWindow *window_with_menu;
|
||||||
|
|
||||||
/* Managed by window-props.c */
|
/* Managed by window-props.c */
|
||||||
MetaWindowPropHooks *prop_hooks_table;
|
MetaWindowPropHooks *prop_hooks_table;
|
||||||
GHashTable *prop_hooks;
|
GHashTable *prop_hooks;
|
||||||
@@ -254,6 +274,9 @@ struct _MetaDisplay
|
|||||||
/* Managed by compositor.c */
|
/* Managed by compositor.c */
|
||||||
MetaCompositor *compositor;
|
MetaCompositor *compositor;
|
||||||
|
|
||||||
|
int render_event_base;
|
||||||
|
int render_error_base;
|
||||||
|
|
||||||
int composite_event_base;
|
int composite_event_base;
|
||||||
int composite_error_base;
|
int composite_error_base;
|
||||||
int composite_major_version;
|
int composite_major_version;
|
||||||
@@ -269,14 +292,28 @@ struct _MetaDisplay
|
|||||||
#ifdef HAVE_STARTUP_NOTIFICATION
|
#ifdef HAVE_STARTUP_NOTIFICATION
|
||||||
SnDisplay *sn_display;
|
SnDisplay *sn_display;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_XSYNC
|
||||||
int xsync_event_base;
|
int xsync_event_base;
|
||||||
int xsync_error_base;
|
int xsync_error_base;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SHAPE
|
||||||
int shape_event_base;
|
int shape_event_base;
|
||||||
int shape_error_base;
|
int shape_error_base;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_XSYNC
|
||||||
unsigned int have_xsync : 1;
|
unsigned int have_xsync : 1;
|
||||||
#define META_DISPLAY_HAS_XSYNC(display) ((display)->have_xsync)
|
#define META_DISPLAY_HAS_XSYNC(display) ((display)->have_xsync)
|
||||||
|
#else
|
||||||
|
#define META_DISPLAY_HAS_XSYNC(display) FALSE
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SHAPE
|
||||||
unsigned int have_shape : 1;
|
unsigned int have_shape : 1;
|
||||||
#define META_DISPLAY_HAS_SHAPE(display) ((display)->have_shape)
|
#define META_DISPLAY_HAS_SHAPE(display) ((display)->have_shape)
|
||||||
|
#else
|
||||||
|
#define META_DISPLAY_HAS_SHAPE(display) FALSE
|
||||||
|
#endif
|
||||||
|
unsigned int have_render : 1;
|
||||||
|
#define META_DISPLAY_HAS_RENDER(display) ((display)->have_render)
|
||||||
unsigned int have_composite : 1;
|
unsigned int have_composite : 1;
|
||||||
unsigned int have_damage : 1;
|
unsigned int have_damage : 1;
|
||||||
#define META_DISPLAY_HAS_COMPOSITE(display) ((display)->have_composite)
|
#define META_DISPLAY_HAS_COMPOSITE(display) ((display)->have_composite)
|
||||||
@@ -339,6 +376,7 @@ void meta_display_register_wayland_window (MetaDisplay *display,
|
|||||||
void meta_display_unregister_wayland_window (MetaDisplay *display,
|
void meta_display_unregister_wayland_window (MetaDisplay *display,
|
||||||
MetaWindow *window);
|
MetaWindow *window);
|
||||||
|
|
||||||
|
#ifdef HAVE_XSYNC
|
||||||
MetaWindow* meta_display_lookup_sync_alarm (MetaDisplay *display,
|
MetaWindow* meta_display_lookup_sync_alarm (MetaDisplay *display,
|
||||||
XSyncAlarm alarm);
|
XSyncAlarm alarm);
|
||||||
void meta_display_register_sync_alarm (MetaDisplay *display,
|
void meta_display_register_sync_alarm (MetaDisplay *display,
|
||||||
@@ -346,6 +384,7 @@ void meta_display_register_sync_alarm (MetaDisplay *display,
|
|||||||
MetaWindow *window);
|
MetaWindow *window);
|
||||||
void meta_display_unregister_sync_alarm (MetaDisplay *display,
|
void meta_display_unregister_sync_alarm (MetaDisplay *display,
|
||||||
XSyncAlarm alarm);
|
XSyncAlarm alarm);
|
||||||
|
#endif /* HAVE_XSYNC */
|
||||||
|
|
||||||
void meta_display_notify_window_created (MetaDisplay *display,
|
void meta_display_notify_window_created (MetaDisplay *display,
|
||||||
MetaWindow *window);
|
MetaWindow *window);
|
||||||
@@ -359,7 +398,11 @@ MetaDisplay* meta_get_display (void);
|
|||||||
Cursor meta_display_create_x_cursor (MetaDisplay *display,
|
Cursor meta_display_create_x_cursor (MetaDisplay *display,
|
||||||
MetaCursor cursor);
|
MetaCursor cursor);
|
||||||
|
|
||||||
void meta_display_update_cursor (MetaDisplay *display);
|
void meta_display_set_grab_op_cursor (MetaDisplay *display,
|
||||||
|
MetaScreen *screen,
|
||||||
|
MetaGrabOp op,
|
||||||
|
Window grab_xwindow,
|
||||||
|
guint32 timestamp);
|
||||||
|
|
||||||
void meta_display_check_threshold_reached (MetaDisplay *display,
|
void meta_display_check_threshold_reached (MetaDisplay *display,
|
||||||
int x,
|
int x,
|
||||||
@@ -389,19 +432,25 @@ const char* meta_event_detail_to_string (int d);
|
|||||||
void meta_display_queue_retheme_all_windows (MetaDisplay *display);
|
void meta_display_queue_retheme_all_windows (MetaDisplay *display);
|
||||||
void meta_display_retheme_all (void);
|
void meta_display_retheme_all (void);
|
||||||
|
|
||||||
void meta_display_ping_window (MetaWindow *window,
|
void meta_display_set_cursor_theme (const char *theme,
|
||||||
guint32 serial);
|
int size);
|
||||||
void meta_display_pong_for_serial (MetaDisplay *display,
|
|
||||||
guint32 serial);
|
void meta_display_ping_window (MetaWindow *window,
|
||||||
|
guint32 timestamp,
|
||||||
|
MetaWindowPingFunc ping_reply_func,
|
||||||
|
MetaWindowPingFunc ping_timeout_func,
|
||||||
|
void *user_data);
|
||||||
|
void meta_display_pong_for_serial (MetaDisplay *display,
|
||||||
|
guint32 serial);
|
||||||
|
|
||||||
int meta_resize_gravity_from_grab_op (MetaGrabOp op);
|
int meta_resize_gravity_from_grab_op (MetaGrabOp op);
|
||||||
|
|
||||||
gboolean meta_grab_op_is_moving (MetaGrabOp op);
|
gboolean meta_grab_op_is_moving (MetaGrabOp op);
|
||||||
gboolean meta_grab_op_is_resizing (MetaGrabOp op);
|
gboolean meta_grab_op_is_resizing (MetaGrabOp op);
|
||||||
gboolean meta_grab_op_is_moving_or_resizing (MetaGrabOp op);
|
|
||||||
gboolean meta_grab_op_is_mouse (MetaGrabOp op);
|
gboolean meta_grab_op_is_mouse (MetaGrabOp op);
|
||||||
|
gboolean meta_grab_op_is_clicking (MetaGrabOp op);
|
||||||
|
gboolean meta_grab_op_is_wayland (MetaGrabOp op);
|
||||||
gboolean meta_grab_op_is_keyboard (MetaGrabOp op);
|
gboolean meta_grab_op_is_keyboard (MetaGrabOp op);
|
||||||
gboolean meta_grab_op_should_block_wayland (MetaGrabOp op);
|
|
||||||
|
|
||||||
void meta_display_devirtualize_modifiers (MetaDisplay *display,
|
void meta_display_devirtualize_modifiers (MetaDisplay *display,
|
||||||
MetaVirtualModifier modifiers,
|
MetaVirtualModifier modifiers,
|
||||||
@@ -421,6 +470,9 @@ void meta_display_accelerator_activate (MetaDisplay *display,
|
|||||||
ClutterKeyEvent *event);
|
ClutterKeyEvent *event);
|
||||||
gboolean meta_display_modifiers_accelerator_activate (MetaDisplay *display);
|
gboolean meta_display_modifiers_accelerator_activate (MetaDisplay *display);
|
||||||
|
|
||||||
|
/* In above-tab-keycode.c */
|
||||||
|
guint meta_display_get_above_tab_keycode (MetaDisplay *display);
|
||||||
|
|
||||||
#ifdef HAVE_XI23
|
#ifdef HAVE_XI23
|
||||||
gboolean meta_display_process_barrier_event (MetaDisplay *display,
|
gboolean meta_display_process_barrier_event (MetaDisplay *display,
|
||||||
XIEvent *event);
|
XIEvent *event);
|
||||||
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user