Compare commits
81 Commits
wip/waylan
...
wip/waylan
Author | SHA1 | Date | |
---|---|---|---|
![]() |
10fbaf7695 | ||
![]() |
ef73402654 | ||
![]() |
22cdf2d650 | ||
![]() |
284b497b4c | ||
![]() |
7d9141c56f | ||
![]() |
519a06b93d | ||
![]() |
0cceddab75 | ||
![]() |
c9830c13b4 | ||
![]() |
9a4783e364 | ||
![]() |
aa15c09d54 | ||
![]() |
62d908be42 | ||
![]() |
6526e9882b | ||
![]() |
ab72352c47 | ||
![]() |
f09b9573f0 | ||
![]() |
3d3ae40f79 | ||
![]() |
ea3d2b4759 | ||
![]() |
542a0886cf | ||
![]() |
bd3d5df9ce | ||
![]() |
91cdfab495 | ||
![]() |
1617323dca | ||
![]() |
bbf9358eba | ||
![]() |
9682a2aea4 | ||
![]() |
c9fbb51775 | ||
![]() |
aa6d887214 | ||
![]() |
13312527de | ||
![]() |
9bd366f2a6 | ||
![]() |
5de346bfef | ||
![]() |
2af20b77b6 | ||
![]() |
9affbf10a6 | ||
![]() |
c0acf3ae6d | ||
![]() |
2c1b20e15f | ||
![]() |
77290b6736 | ||
![]() |
876f81db12 | ||
![]() |
75f3ae14b5 | ||
![]() |
d26f248b0f | ||
![]() |
eeb3dfc991 | ||
![]() |
e66db2eab3 | ||
![]() |
2ae7454f36 | ||
![]() |
4fd3c63da9 | ||
![]() |
909a6607c5 | ||
![]() |
1bde397edf | ||
![]() |
015c05fbf6 | ||
![]() |
8ad5ccd2f8 | ||
![]() |
115cc870c7 | ||
![]() |
3112794d83 | ||
![]() |
3528b067d0 | ||
![]() |
0986b660be | ||
![]() |
3bb5086173 | ||
![]() |
69467842ab | ||
![]() |
57077435ed | ||
![]() |
46de0ed462 | ||
![]() |
5086626805 | ||
![]() |
bbbcd8c631 | ||
![]() |
3b61b85f2c | ||
![]() |
cd20f1bc0b | ||
![]() |
8b52782ed4 | ||
![]() |
849050be95 | ||
![]() |
5c27a91684 | ||
![]() |
764c472edb | ||
![]() |
d0529b7482 | ||
![]() |
8f4621240a | ||
![]() |
e039add240 | ||
![]() |
dbd8d4d598 | ||
![]() |
522542c486 | ||
![]() |
fc67c707e4 | ||
![]() |
c354e7e81b | ||
![]() |
bf40409d97 | ||
![]() |
57d083730e | ||
![]() |
dc242e46c2 | ||
![]() |
7e1d1003c9 | ||
![]() |
3bb33d384f | ||
![]() |
214f31257b | ||
![]() |
bfc87d13cb | ||
![]() |
506ddc3d6c | ||
![]() |
24564c77d6 | ||
![]() |
18a21b67c2 | ||
![]() |
3803fd9511 | ||
![]() |
152d896f75 | ||
![]() |
2f3a5f2001 | ||
![]() |
c3e8646af3 | ||
![]() |
8c17b670fb |
10
.gitignore
vendored
10
.gitignore
vendored
@@ -23,7 +23,7 @@ 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-wm.desktop
|
src/mutter-wm.desktop
|
||||||
src/mutter.desktop
|
src/mutter-wayland.desktop
|
||||||
*.o
|
*.o
|
||||||
*.a
|
*.a
|
||||||
*.lo
|
*.lo
|
||||||
@@ -46,10 +46,10 @@ 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-theme-viewer
|
mutter-theme-viewer
|
||||||
mutter.desktop
|
mutter-wayland.desktop
|
||||||
org.gnome.mutter.gschema.valid
|
org.gnome.mutter.gschema.valid
|
||||||
org.gnome.mutter.gschema.xml
|
org.gnome.mutter.gschema.xml
|
||||||
testasyncgetprop
|
testasyncgetprop
|
||||||
@@ -74,6 +74,8 @@ src/mutter-enum-types.[ch]
|
|||||||
src/stamp-mutter-enum-types.h
|
src/stamp-mutter-enum-types.h
|
||||||
src/mutter-marshal.[ch]
|
src/mutter-marshal.[ch]
|
||||||
src/stamp-mutter-marshal.h
|
src/stamp-mutter-marshal.h
|
||||||
|
src/meta-dbus-xrandr.[ch]
|
||||||
|
src/meta-dbus-idle-monitor.[ch]
|
||||||
src/mutter-plugins.pc
|
src/mutter-plugins.pc
|
||||||
doc/reference/*.args
|
doc/reference/*.args
|
||||||
doc/reference/*.bak
|
doc/reference/*.bak
|
||||||
|
26
NEWS
26
NEWS
@@ -1,3 +1,29 @@
|
|||||||
|
3.9.90
|
||||||
|
======
|
||||||
|
* First release from the wayland branch, includes basic support for running
|
||||||
|
as a wayland compositor [Robert, Neil, Giovanni]
|
||||||
|
* Add support for _GTK_FRAME_EXTENTS [Jasper; #705766]
|
||||||
|
* Fix quick consecutive <super> presses breaking keyboard input [Alban; #666101]
|
||||||
|
* Work towards running as wayland compositor [Giovanni]
|
||||||
|
- Add DBus API for display configuration
|
||||||
|
[#705670, #706231, #706233, #706322, #706382]
|
||||||
|
- Add abstraction layer for cursor tracking [#705911]
|
||||||
|
- Add support for plugin modality under wayland [#705917]
|
||||||
|
* Disable GTK+ scaling [Alexander; #706388]
|
||||||
|
* Disable blending while updating tower [Robert]
|
||||||
|
* Misc bug fixes and cleanups [Adel, Jasper, Giovanni, Colin, Rico, Florian;
|
||||||
|
#703332, #704437, #706207]
|
||||||
|
|
||||||
|
Contributors:
|
||||||
|
Robert Bragg, Giovanni Campagna, Alban Crequy, Adel Gadllah,
|
||||||
|
Alexander Larsson, Florian Müllner, Jasper St. Pierre, Neil Roberts,
|
||||||
|
Rico Tzschichholz, Colin Walters
|
||||||
|
|
||||||
|
Translations:
|
||||||
|
Jiro Matsuzawa [ja], Kjartan Maraas [nb], Matej Urbančič [sl],
|
||||||
|
Marek Černocký [cs], Daniel Mustieles [es], Rafael Ferreira [pt_BR],
|
||||||
|
Yaron Shahrabani [he], Ján Kyselica [sk]
|
||||||
|
|
||||||
3.9.5
|
3.9.5
|
||||||
=====
|
=====
|
||||||
* Don't select for touch events on the stage [Jasper; #697192]
|
* Don't select for touch events on the stage [Jasper; #697192]
|
||||||
|
51
configure.ac
51
configure.ac
@@ -2,7 +2,7 @@ AC_PREREQ(2.50)
|
|||||||
|
|
||||||
m4_define([mutter_major_version], [3])
|
m4_define([mutter_major_version], [3])
|
||||||
m4_define([mutter_minor_version], [9])
|
m4_define([mutter_minor_version], [9])
|
||||||
m4_define([mutter_micro_version], [5])
|
m4_define([mutter_micro_version], [90])
|
||||||
|
|
||||||
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])
|
||||||
@@ -19,6 +19,10 @@ AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz tar-ustar])
|
|||||||
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
|
||||||
@@ -34,7 +38,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])
|
||||||
|
|
||||||
@@ -76,6 +80,7 @@ MUTTER_PC_MODULES="
|
|||||||
$CLUTTER_PACKAGE >= 1.14.3
|
$CLUTTER_PACKAGE >= 1.14.3
|
||||||
cogl-1.0 >= 1.13.3
|
cogl-1.0 >= 1.13.3
|
||||||
upower-glib > 0.9.11
|
upower-glib > 0.9.11
|
||||||
|
gnome-desktop-3.0
|
||||||
"
|
"
|
||||||
|
|
||||||
GLIB_GSETTINGS
|
GLIB_GSETTINGS
|
||||||
@@ -114,11 +119,6 @@ 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)
|
||||||
|
|
||||||
AC_ARG_ENABLE(wayland,
|
|
||||||
AC_HELP_STRING([--enable-wayland],
|
|
||||||
[Enable support for running as a hybrid X and Wayland compositor]),,
|
|
||||||
enable_wayland=no)
|
|
||||||
|
|
||||||
## Wayland support requires the xserver.xml protocol extension found in the weston
|
## Wayland support requires the xserver.xml protocol extension found in the weston
|
||||||
## repository but since there aren't currently established conventions for
|
## repository but since there aren't currently established conventions for
|
||||||
## installing and discovering these we simply require a location to be given
|
## installing and discovering these we simply require a location to be given
|
||||||
@@ -139,7 +139,6 @@ 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"
|
||||||
@@ -218,29 +217,16 @@ if test x$have_xcursor = xyes; then
|
|||||||
AC_DEFINE(HAVE_XCURSOR, , [Building with Xcursor support])
|
AC_DEFINE(HAVE_XCURSOR, , [Building with Xcursor support])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
have_wayland=no
|
# We always build with wayland enabled
|
||||||
if test x$enable_wayland = "xyes"; then
|
AC_DEFINE(HAVE_WAYLAND, , [Building with Wayland support])
|
||||||
WAYLAND_VERSION=0.1
|
|
||||||
AC_MSG_CHECKING([Wayland >= $WAYLAND_VERSION])
|
|
||||||
if ! $PKG_CONFIG --atleast-version $WAYLAND_VERSION wayland-server; then
|
|
||||||
AC_MSG_ERROR([wayland support enabled but no suitable wayland-server package found])
|
|
||||||
fi
|
|
||||||
AC_MSG_RESULT(yes)
|
|
||||||
|
|
||||||
AC_PATH_PROG([WAYLAND_SCANNER],[wayland-scanner],[no])
|
AC_PATH_PROG([WAYLAND_SCANNER],[wayland-scanner],[no])
|
||||||
AS_IF([test "x$WAYLAND_SCANNER" = "xno"],
|
AS_IF([test "x$WAYLAND_SCANNER" = "xno"],
|
||||||
AC_MSG_ERROR([Could not find wayland-scanner in your PATH, required for parsing wayland extension protocols]))
|
AC_MSG_ERROR([Could not find wayland-scanner in your PATH, required for parsing wayland extension protocols]))
|
||||||
AC_SUBST([WAYLAND_SCANNER])
|
AC_SUBST([WAYLAND_SCANNER])
|
||||||
|
AC_SUBST(XWAYLAND_PATH)
|
||||||
AC_SUBST(XWAYLAND_PATH)
|
|
||||||
|
|
||||||
MUTTER_PC_MODULES="$MUTTER_PC_MODULES wayland-server libdrm"
|
|
||||||
AC_DEFINE(HAVE_WAYLAND, , [Building with Wayland support])
|
|
||||||
have_wayland=yes
|
|
||||||
fi
|
|
||||||
|
|
||||||
AM_CONDITIONAL(HAVE_WAYLAND, test x$have_wayland = "xyes")
|
|
||||||
|
|
||||||
|
MUTTER_PC_MODULES="$MUTTER_PC_MODULES wayland-server"
|
||||||
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],
|
||||||
@@ -478,8 +464,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/mutter-plugins.pc
|
|
||||||
src/compositor/plugins/Makefile
|
src/compositor/plugins/Makefile
|
||||||
protocol/Makefile
|
protocol/Makefile
|
||||||
data/Makefile
|
data/Makefile
|
||||||
@@ -498,14 +483,12 @@ fi
|
|||||||
|
|
||||||
dnl ==========================================================================
|
dnl ==========================================================================
|
||||||
echo "
|
echo "
|
||||||
mutter-$VERSION
|
mutter-wayland-$VERSION
|
||||||
|
|
||||||
prefix: ${prefix}
|
prefix: ${prefix}
|
||||||
source code location: ${srcdir}
|
source code location: ${srcdir}
|
||||||
compiler: ${CC}
|
compiler: ${CC}
|
||||||
|
|
||||||
Wayland: ${have_wayland}
|
|
||||||
|
|
||||||
Startup notification: ${have_startup_notification}
|
Startup notification: ${have_startup_notification}
|
||||||
libcanberra: ${have_libcanberra}
|
libcanberra: ${have_libcanberra}
|
||||||
Introspection: ${found_introspection}
|
Introspection: ${found_introspection}
|
||||||
|
@@ -1,7 +1,3 @@
|
|||||||
defaultcursordir = $(datadir)/mutter/cursors
|
defaultcursordir = $(pkgdatadir)/cursors
|
||||||
|
|
||||||
dist_defaultcursor_DATA =
|
dist_defaultcursor_DATA = left_ptr.png
|
||||||
|
|
||||||
if HAVE_WAYLAND
|
|
||||||
dist_defaultcursor_DATA += left_ptr.png
|
|
||||||
endif
|
|
||||||
|
@@ -140,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
|
||||||
|
@@ -12,6 +12,7 @@ src/core/display.c
|
|||||||
src/core/errors.c
|
src/core/errors.c
|
||||||
src/core/keybindings.c
|
src/core/keybindings.c
|
||||||
src/core/main.c
|
src/core/main.c
|
||||||
|
src/core/monitor.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
|
||||||
@@ -23,12 +24,9 @@ src/core/xprops.c
|
|||||||
src/mutter.desktop.in
|
src/mutter.desktop.in
|
||||||
src/mutter-wm.desktop.in
|
src/mutter-wm.desktop.in
|
||||||
src/org.gnome.mutter.gschema.xml.in
|
src/org.gnome.mutter.gschema.xml.in
|
||||||
src/tools/mutter-message.c
|
|
||||||
src/ui/frames.c
|
src/ui/frames.c
|
||||||
src/ui/menu.c
|
src/ui/menu.c
|
||||||
src/ui/metaaccellabel.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/ui/theme-viewer.c
|
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
|
||||||
@@ -10,6 +10,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)/core \
|
-I$(srcdir)/core \
|
||||||
-I$(srcdir)/ui \
|
-I$(srcdir)/ui \
|
||||||
@@ -29,26 +30,21 @@ INCLUDES= \
|
|||||||
-DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\" \
|
-DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\" \
|
||||||
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\"
|
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\"
|
||||||
|
|
||||||
if HAVE_WAYLAND
|
|
||||||
INCLUDES += \
|
INCLUDES += \
|
||||||
-I$(srcdir)/wayland \
|
-I$(srcdir)/wayland \
|
||||||
|
-I$(builddir)/wayland \
|
||||||
-DXWAYLAND_PATH='"@XWAYLAND_PATH@"'
|
-DXWAYLAND_PATH='"@XWAYLAND_PATH@"'
|
||||||
endif
|
|
||||||
|
|
||||||
mutter_built_sources = \
|
mutter_built_sources = \
|
||||||
$(dbus_xrandr_built_sources) \
|
$(dbus_idle_built_sources) \
|
||||||
$(dbus_idle_built_sources) \
|
$(dbus_xrandr_built_sources) \
|
||||||
mutter-enum-types.h \
|
mutter-enum-types.h \
|
||||||
mutter-enum-types.c
|
mutter-enum-types.c \
|
||||||
|
|
||||||
if HAVE_WAYLAND
|
|
||||||
mutter_built_sources += \
|
|
||||||
wayland/xserver-protocol.c \
|
wayland/xserver-protocol.c \
|
||||||
wayland/xserver-server-protocol.h \
|
wayland/xserver-server-protocol.h \
|
||||||
wayland/xserver-client-protocol.h
|
wayland/xserver-client-protocol.h
|
||||||
endif
|
|
||||||
|
|
||||||
libmutter_la_SOURCES = \
|
libmutter_wayland_la_SOURCES = \
|
||||||
core/async-getprop.c \
|
core/async-getprop.c \
|
||||||
core/async-getprop.h \
|
core/async-getprop.h \
|
||||||
core/barrier.c \
|
core/barrier.c \
|
||||||
@@ -77,6 +73,7 @@ libmutter_la_SOURCES = \
|
|||||||
compositor/meta-shadow-factory.c \
|
compositor/meta-shadow-factory.c \
|
||||||
compositor/meta-shadow-factory-private.h \
|
compositor/meta-shadow-factory-private.h \
|
||||||
compositor/meta-shaped-texture.c \
|
compositor/meta-shaped-texture.c \
|
||||||
|
compositor/meta-shaped-texture-private.h \
|
||||||
compositor/meta-texture-rectangle.c \
|
compositor/meta-texture-rectangle.c \
|
||||||
compositor/meta-texture-rectangle.h \
|
compositor/meta-texture-rectangle.h \
|
||||||
compositor/meta-texture-tower.c \
|
compositor/meta-texture-tower.c \
|
||||||
@@ -109,6 +106,8 @@ libmutter_la_SOURCES = \
|
|||||||
ui/draw-workspace.h \
|
ui/draw-workspace.h \
|
||||||
core/edge-resistance.c \
|
core/edge-resistance.c \
|
||||||
core/edge-resistance.h \
|
core/edge-resistance.h \
|
||||||
|
core/edid-parse.c \
|
||||||
|
core/edid.h \
|
||||||
core/errors.c \
|
core/errors.c \
|
||||||
meta/errors.h \
|
meta/errors.h \
|
||||||
core/frame.c \
|
core/frame.c \
|
||||||
@@ -132,7 +131,6 @@ libmutter_la_SOURCES = \
|
|||||||
core/meta-xrandr-shared.h \
|
core/meta-xrandr-shared.h \
|
||||||
core/monitor.c \
|
core/monitor.c \
|
||||||
core/monitor-config.c \
|
core/monitor-config.c \
|
||||||
core/monitor-kms.c \
|
|
||||||
core/monitor-private.h \
|
core/monitor-private.h \
|
||||||
core/monitor-xrandr.c \
|
core/monitor-xrandr.c \
|
||||||
core/mutter-Xatomtype.h \
|
core/mutter-Xatomtype.h \
|
||||||
@@ -183,10 +181,7 @@ libmutter_la_SOURCES = \
|
|||||||
ui/ui.c \
|
ui/ui.c \
|
||||||
$(mutter_built_sources)
|
$(mutter_built_sources)
|
||||||
|
|
||||||
if HAVE_WAYLAND
|
libmutter_wayland_la_SOURCES += \
|
||||||
libmutter_la_SOURCES += \
|
|
||||||
wayland/meta-tty.c \
|
|
||||||
wayland/meta-tty.h \
|
|
||||||
wayland/meta-wayland.c \
|
wayland/meta-wayland.c \
|
||||||
wayland/meta-wayland-private.h \
|
wayland/meta-wayland-private.h \
|
||||||
wayland/meta-xwayland-private.h \
|
wayland/meta-xwayland-private.h \
|
||||||
@@ -200,13 +195,10 @@ libmutter_la_SOURCES += \
|
|||||||
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.h \
|
||||||
wayland/meta-wayland-stage.c \
|
wayland/meta-wayland-stage.c
|
||||||
wayland/meta-weston-launch.c \
|
|
||||||
wayland/meta-weston-launch.h
|
|
||||||
endif
|
|
||||||
|
|
||||||
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
|
||||||
@@ -244,29 +236,16 @@ 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
|
||||||
|
|
||||||
if HAVE_WAYLAND
|
|
||||||
bin_PROGRAMS+=mutter-launch
|
|
||||||
|
|
||||||
mutter_launch_SOURCES = wayland/weston-launch.c wayland/weston-launch.h
|
|
||||||
|
|
||||||
mutter_launch_CFLAGS = $(MUTTER_LAUNCH_CFLAGS)
|
|
||||||
mutter_launch_LDFLAGS = $(MUTTER_LAUNCH_LIBS) -lpam
|
|
||||||
|
|
||||||
install-exec-hook:
|
|
||||||
-chown root $(DESTDIR)$(bindir)/mutter-launch
|
|
||||||
-chmod u+s $(DESTDIR)$(bindir)/mutter-launch
|
|
||||||
endif
|
|
||||||
|
|
||||||
if HAVE_INTROSPECTION
|
if HAVE_INTROSPECTION
|
||||||
include $(INTROSPECTION_MAKEFILE)
|
include $(INTROSPECTION_MAKEFILE)
|
||||||
@@ -288,15 +267,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))
|
$(filter %.c,$(libmutter_wayland_la_SOURCES))
|
||||||
@META_GIR@_SCANNERFLAGS = --warn-all --warn-error
|
@META_GIR@_SCANNERFLAGS = --warn-all --warn-error
|
||||||
|
|
||||||
endif
|
endif
|
||||||
@@ -307,22 +286,17 @@ testasyncgetprop_SOURCES = core/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)
|
||||||
|
|
||||||
wmpropertiesdir=$(datadir)/gnome/wm-properties
|
|
||||||
wmproperties_in_files=mutter-wm.desktop.in
|
|
||||||
wmproperties_files=$(wmproperties_in_files:.desktop.in=.desktop)
|
|
||||||
wmproperties_DATA = $(wmproperties_files)
|
|
||||||
|
|
||||||
xmldir = @GNOME_KEYBINDINGS_KEYSDIR@
|
xmldir = @GNOME_KEYBINDINGS_KEYSDIR@
|
||||||
xml_in_files = \
|
xml_in_files = \
|
||||||
50-mutter-navigation.xml.in \
|
50-mutter-navigation.xml.in \
|
||||||
@@ -330,6 +304,8 @@ xml_in_files = \
|
|||||||
50-mutter-windows.xml.in
|
50-mutter-windows.xml.in
|
||||||
xml_DATA = $(xml_in_files:.xml.in=.xml)
|
xml_DATA = $(xml_in_files:.xml.in=.xml)
|
||||||
|
|
||||||
|
dbus_idle_built_sources = meta-dbus-idle-monitor.c meta-dbus-idle-monitor.h
|
||||||
|
|
||||||
gsettings_SCHEMAS = org.gnome.mutter.gschema.xml
|
gsettings_SCHEMAS = org.gnome.mutter.gschema.xml
|
||||||
@INTLTOOL_XML_NOMERGE_RULE@
|
@INTLTOOL_XML_NOMERGE_RULE@
|
||||||
@GSETTINGS_RULES@
|
@GSETTINGS_RULES@
|
||||||
@@ -338,7 +314,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 \
|
||||||
$(xml_DATA) \
|
$(xml_DATA) \
|
||||||
@@ -348,7 +324,7 @@ CLEANFILES = \
|
|||||||
|
|
||||||
pkgconfigdir = $(libdir)/pkgconfig
|
pkgconfigdir = $(libdir)/pkgconfig
|
||||||
|
|
||||||
pkgconfig_DATA = libmutter.pc mutter-plugins.pc
|
pkgconfig_DATA = libmutter-wayland.pc
|
||||||
|
|
||||||
EXTRA_DIST=$(desktopfiles_files) \
|
EXTRA_DIST=$(desktopfiles_files) \
|
||||||
$(wmproperties_files) \
|
$(wmproperties_files) \
|
||||||
@@ -358,8 +334,7 @@ EXTRA_DIST=$(desktopfiles_files) \
|
|||||||
$(xml_in_files) \
|
$(xml_in_files) \
|
||||||
org.gnome.mutter.gschema.xml.in \
|
org.gnome.mutter.gschema.xml.in \
|
||||||
mutter-schemas.convert \
|
mutter-schemas.convert \
|
||||||
libmutter.pc.in \
|
libmutter-wayland.pc.in \
|
||||||
mutter-plugins.pc.in \
|
|
||||||
mutter-enum-types.h.in \
|
mutter-enum-types.h.in \
|
||||||
mutter-enum-types.c.in
|
mutter-enum-types.c.in
|
||||||
|
|
||||||
@@ -393,7 +368,7 @@ $(dbus_xrandr_built_sources) : Makefile.am xrandr.xml
|
|||||||
--interface-prefix org.gnome.Mutter \
|
--interface-prefix org.gnome.Mutter \
|
||||||
--c-namespace MetaDBus \
|
--c-namespace MetaDBus \
|
||||||
--generate-c-code meta-dbus-xrandr \
|
--generate-c-code meta-dbus-xrandr \
|
||||||
xrandr.xml
|
$(srcdir)/xrandr.xml
|
||||||
|
|
||||||
dbus_idle_built_sources = meta-dbus-idle-monitor.c meta-dbus-idle-monitor.h
|
dbus_idle_built_sources = meta-dbus-idle-monitor.c meta-dbus-idle-monitor.h
|
||||||
|
|
||||||
@@ -403,13 +378,14 @@ $(dbus_idle_built_sources) : Makefile.am idle-monitor.xml
|
|||||||
--c-namespace MetaDBus \
|
--c-namespace MetaDBus \
|
||||||
--generate-c-code meta-dbus-idle-monitor \
|
--generate-c-code meta-dbus-idle-monitor \
|
||||||
--c-generate-object-manager \
|
--c-generate-object-manager \
|
||||||
idle-monitor.xml
|
$(srcdir)/idle-monitor.xml
|
||||||
|
|
||||||
if HAVE_WAYLAND
|
|
||||||
wayland/%-protocol.c : $(top_builddir)/protocol/%.xml
|
wayland/%-protocol.c : $(top_builddir)/protocol/%.xml
|
||||||
|
mkdir -p wayland
|
||||||
$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
|
$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
|
||||||
wayland/%-server-protocol.h : $(top_builddir)/protocol/%.xml
|
wayland/%-server-protocol.h : $(top_builddir)/protocol/%.xml
|
||||||
|
mkdir -p wayland
|
||||||
$(AM_V_GEN)$(WAYLAND_SCANNER) server-header < $< > $@
|
$(AM_V_GEN)$(WAYLAND_SCANNER) server-header < $< > $@
|
||||||
wayland/%-client-protocol.h : $(top_builddir)/protocol/%.xml
|
wayland/%-client-protocol.h : $(top_builddir)/protocol/%.xml
|
||||||
|
mkdir -p wayland
|
||||||
$(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@
|
$(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@
|
||||||
endif
|
|
||||||
|
@@ -84,11 +84,7 @@
|
|||||||
#include "meta-window-group.h"
|
#include "meta-window-group.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() */
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
#include "meta-wayland-private.h"
|
#include "meta-wayland-private.h"
|
||||||
#include "meta-wayland-pointer.h"
|
|
||||||
#include "meta-wayland-keyboard.h"
|
|
||||||
#endif
|
|
||||||
#include <X11/extensions/shape.h>
|
#include <X11/extensions/shape.h>
|
||||||
#include <X11/extensions/Xcomposite.h>
|
#include <X11/extensions/Xcomposite.h>
|
||||||
|
|
||||||
@@ -428,20 +424,34 @@ meta_stage_is_focused (MetaScreen *screen)
|
|||||||
return (screen->display->focus_type == META_FOCUS_STAGE);
|
return (screen->display->focus_type == META_FOCUS_STAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
gboolean
|
||||||
begin_modal_x11 (MetaScreen *screen,
|
meta_begin_modal_for_plugin (MetaScreen *screen,
|
||||||
MetaPlugin *plugin,
|
MetaPlugin *plugin,
|
||||||
MetaModalOptions options,
|
MetaModalOptions options,
|
||||||
guint32 timestamp)
|
guint32 timestamp)
|
||||||
{
|
{
|
||||||
MetaDisplay *display = meta_screen_get_display (screen);
|
/* To some extent this duplicates code in meta_display_begin_grab_op(), but there
|
||||||
Display *xdpy = meta_display_get_xdisplay (display);
|
* are significant differences in how we handle grabs that make it difficult to
|
||||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
* merge the two.
|
||||||
Window grab_window = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
|
*/
|
||||||
Cursor cursor = None;
|
MetaDisplay *display = meta_screen_get_display (screen);
|
||||||
int result;
|
Display *xdpy = meta_display_get_xdisplay (display);
|
||||||
gboolean pointer_grabbed = FALSE;
|
MetaCompositor *compositor = display->compositor;
|
||||||
gboolean keyboard_grabbed = FALSE;
|
ClutterStage *stage;
|
||||||
|
Window grab_window;
|
||||||
|
Cursor cursor = None;
|
||||||
|
gboolean pointer_grabbed = FALSE;
|
||||||
|
gboolean keyboard_grabbed = FALSE;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
stage = CLUTTER_STAGE (meta_get_stage_for_screen (screen));
|
||||||
|
if (!stage)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
grab_window = clutter_x11_get_stage_window (stage);
|
||||||
|
|
||||||
|
if (compositor->modal_plugin != NULL || display->grab_op != META_GRAB_OP_NONE)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if ((options & META_MODAL_POINTER_ALREADY_GRABBED) == 0)
|
if ((options & META_MODAL_POINTER_ALREADY_GRABBED) == 0)
|
||||||
{
|
{
|
||||||
@@ -491,79 +501,6 @@ begin_modal_x11 (MetaScreen *screen,
|
|||||||
keyboard_grabbed = TRUE;
|
keyboard_grabbed = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
if (pointer_grabbed)
|
|
||||||
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_POINTER_ID, timestamp);
|
|
||||||
if (keyboard_grabbed)
|
|
||||||
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
begin_modal_wayland (MetaScreen *screen,
|
|
||||||
MetaPlugin *plugin,
|
|
||||||
MetaModalOptions options,
|
|
||||||
guint32 timestamp)
|
|
||||||
{
|
|
||||||
MetaWaylandCompositor *compositor;
|
|
||||||
gboolean pointer_grabbed = FALSE;
|
|
||||||
gboolean keyboard_grabbed = FALSE;
|
|
||||||
|
|
||||||
compositor = meta_wayland_compositor_get_default ();
|
|
||||||
|
|
||||||
if ((options & META_MODAL_POINTER_ALREADY_GRABBED) == 0)
|
|
||||||
{
|
|
||||||
if (!meta_wayland_pointer_begin_modal (&compositor->seat->pointer))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
pointer_grabbed = TRUE;
|
|
||||||
}
|
|
||||||
if ((options & META_MODAL_KEYBOARD_ALREADY_GRABBED) == 0)
|
|
||||||
{
|
|
||||||
if (!meta_wayland_keyboard_begin_modal (&compositor->seat->keyboard))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
keyboard_grabbed = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
if (pointer_grabbed)
|
|
||||||
meta_wayland_pointer_end_modal (&compositor->seat->pointer);
|
|
||||||
if (keyboard_grabbed)
|
|
||||||
meta_wayland_keyboard_end_modal (&compositor->seat->keyboard);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
gboolean
|
|
||||||
meta_begin_modal_for_plugin (MetaScreen *screen,
|
|
||||||
MetaPlugin *plugin,
|
|
||||||
MetaModalOptions options,
|
|
||||||
guint32 timestamp)
|
|
||||||
{
|
|
||||||
/* To some extent this duplicates code in meta_display_begin_grab_op(), but there
|
|
||||||
* are significant differences in how we handle grabs that make it difficult to
|
|
||||||
* merge the two.
|
|
||||||
*/
|
|
||||||
MetaDisplay *display = meta_screen_get_display (screen);
|
|
||||||
MetaCompositor *compositor = display->compositor;
|
|
||||||
gboolean ok;
|
|
||||||
|
|
||||||
if (compositor->modal_plugin != NULL || display->grab_op != META_GRAB_OP_NONE)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if (meta_is_wayland_compositor ())
|
|
||||||
ok = begin_modal_wayland (screen, plugin, options, timestamp);
|
|
||||||
else
|
|
||||||
ok = begin_modal_x11 (screen, plugin, options, timestamp);
|
|
||||||
if (!ok)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
display->grab_op = META_GRAB_OP_COMPOSITOR;
|
display->grab_op = META_GRAB_OP_COMPOSITOR;
|
||||||
display->grab_window = NULL;
|
display->grab_window = NULL;
|
||||||
display->grab_screen = screen;
|
display->grab_screen = screen;
|
||||||
@@ -573,6 +510,14 @@ meta_begin_modal_for_plugin (MetaScreen *screen,
|
|||||||
compositor->modal_plugin = plugin;
|
compositor->modal_plugin = plugin;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (pointer_grabbed)
|
||||||
|
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_POINTER_ID, timestamp);
|
||||||
|
if (keyboard_grabbed)
|
||||||
|
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -586,18 +531,8 @@ meta_end_modal_for_plugin (MetaScreen *screen,
|
|||||||
|
|
||||||
g_return_if_fail (compositor->modal_plugin == plugin);
|
g_return_if_fail (compositor->modal_plugin == plugin);
|
||||||
|
|
||||||
if (meta_is_wayland_compositor ())
|
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_POINTER_ID, timestamp);
|
||||||
{
|
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
|
||||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
|
||||||
|
|
||||||
meta_wayland_pointer_end_modal (&compositor->seat->pointer);
|
|
||||||
meta_wayland_keyboard_end_modal (&compositor->seat->keyboard);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_POINTER_ID, timestamp);
|
|
||||||
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
display->grab_op = META_GRAB_OP_NONE;
|
display->grab_op = META_GRAB_OP_NONE;
|
||||||
display->grab_window = NULL;
|
display->grab_window = NULL;
|
||||||
@@ -694,11 +629,9 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
|
|||||||
MetaCompScreen *info;
|
MetaCompScreen *info;
|
||||||
MetaDisplay *display = meta_screen_get_display (screen);
|
MetaDisplay *display = meta_screen_get_display (screen);
|
||||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||||
Window xwin = None;
|
Window xwin;
|
||||||
gint width, height;
|
gint width, height;
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
MetaWaylandCompositor *wayland_compositor;
|
MetaWaylandCompositor *wayland_compositor;
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Check if the screen is already managed */
|
/* Check if the screen is already managed */
|
||||||
if (meta_screen_get_compositor_data (screen))
|
if (meta_screen_get_compositor_data (screen))
|
||||||
@@ -731,7 +664,6 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
|
|||||||
|
|
||||||
/* We will have already created a stage if running as a wayland
|
/* We will have already created a stage if running as a wayland
|
||||||
* compositor... */
|
* compositor... */
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
if (meta_is_wayland_compositor ())
|
if (meta_is_wayland_compositor ())
|
||||||
{
|
{
|
||||||
wayland_compositor = meta_wayland_compositor_get_default ();
|
wayland_compositor = meta_wayland_compositor_get_default ();
|
||||||
@@ -741,7 +673,6 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
|
|||||||
clutter_actor_set_size (info->stage, width, height);
|
clutter_actor_set_size (info->stage, width, height);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif /* HAVE_WAYLAND */
|
|
||||||
{
|
{
|
||||||
info->stage = clutter_stage_new ();
|
info->stage = clutter_stage_new ();
|
||||||
|
|
||||||
@@ -840,8 +771,6 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
|
|||||||
|
|
||||||
redirect_windows (compositor, screen);
|
redirect_windows (compositor, screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
clutter_actor_show (info->stage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1001,8 +930,8 @@ is_grabbed_event (MetaDisplay *display,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_compositor_window_x11_shape_changed (MetaCompositor *compositor,
|
meta_compositor_window_shape_changed (MetaCompositor *compositor,
|
||||||
MetaWindow *window)
|
MetaWindow *window)
|
||||||
{
|
{
|
||||||
MetaWindowActor *window_actor;
|
MetaWindowActor *window_actor;
|
||||||
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||||
@@ -1490,6 +1419,7 @@ meta_compositor_sync_screen_size (MetaCompositor *compositor,
|
|||||||
guint width,
|
guint width,
|
||||||
guint height)
|
guint height)
|
||||||
{
|
{
|
||||||
|
MetaDisplay *display = meta_screen_get_display (screen);
|
||||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||||
|
|
||||||
if (meta_is_wayland_compositor ())
|
if (meta_is_wayland_compositor ())
|
||||||
@@ -1508,7 +1438,6 @@ meta_compositor_sync_screen_size (MetaCompositor *compositor,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MetaDisplay *display = meta_screen_get_display (screen);
|
|
||||||
Display *xdisplay;
|
Display *xdisplay;
|
||||||
Window xwin;
|
Window xwin;
|
||||||
|
|
||||||
|
@@ -1031,7 +1031,6 @@ meta_background_load_file_finish (MetaBackground *self,
|
|||||||
GAsyncResult *result,
|
GAsyncResult *result,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
static CoglUserDataKey key;
|
|
||||||
GTask *task;
|
GTask *task;
|
||||||
LoadFileTaskData *task_data;
|
LoadFileTaskData *task_data;
|
||||||
CoglTexture *texture;
|
CoglTexture *texture;
|
||||||
@@ -1077,12 +1076,6 @@ meta_background_load_file_finish (MetaBackground *self,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
cogl_object_set_user_data (COGL_OBJECT (texture),
|
|
||||||
&key,
|
|
||||||
g_object_ref (pixbuf),
|
|
||||||
(CoglUserDataDestroyCallback)
|
|
||||||
g_object_unref);
|
|
||||||
|
|
||||||
ensure_pipeline (self);
|
ensure_pipeline (self);
|
||||||
unset_texture (self);
|
unset_texture (self);
|
||||||
set_style (self, task_data->style);
|
set_style (self, task_data->style);
|
||||||
|
44
src/compositor/meta-shaped-texture-private.h
Normal file
44
src/compositor/meta-shaped-texture-private.h
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* shaped texture
|
||||||
|
*
|
||||||
|
* An actor to draw a texture clipped to a list of rectangles
|
||||||
|
*
|
||||||
|
* Authored By Neil Roberts <neil@linux.intel.com>
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Intel Corporation
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __META_SHAPED_TEXTURE_PRIVATE_H__
|
||||||
|
#define __META_SHAPED_TEXTURE_PRIVATE_H__
|
||||||
|
|
||||||
|
#include <meta/meta-shaped-texture.h>
|
||||||
|
#include "meta-wayland-private.h"
|
||||||
|
|
||||||
|
ClutterActor *meta_shaped_texture_new_with_xwindow (Window xwindow);
|
||||||
|
ClutterActor *meta_shaped_texture_new_with_wayland_surface (MetaWaylandSurface *surface);
|
||||||
|
void meta_shaped_texture_set_wayland_surface (MetaShapedTexture *stex,
|
||||||
|
MetaWaylandSurface *surface);
|
||||||
|
MetaWaylandSurface *meta_shaped_texture_get_wayland_surface (MetaShapedTexture *stex);
|
||||||
|
|
||||||
|
void meta_shaped_texture_set_pixmap (MetaShapedTexture *stex,
|
||||||
|
Pixmap pixmap);
|
||||||
|
void meta_shaped_texture_attach_wayland_buffer (MetaShapedTexture *stex,
|
||||||
|
MetaWaylandBuffer *buffer);
|
||||||
|
|
||||||
|
#endif
|
@@ -33,10 +33,9 @@
|
|||||||
#include <meta/util.h>
|
#include <meta/util.h>
|
||||||
#include "meta-texture-tower.h"
|
#include "meta-texture-tower.h"
|
||||||
|
|
||||||
#ifdef HAVE_WAYLAND
|
#include "meta-shaped-texture-private.h"
|
||||||
#include "meta-wayland-private.h"
|
#include "meta-wayland-private.h"
|
||||||
#include <cogl/cogl-wayland-server.h>
|
#include <cogl/cogl-wayland-server.h>
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
#include <cogl/cogl.h>
|
#include <cogl/cogl.h>
|
||||||
@@ -64,9 +63,7 @@ static gboolean meta_shaped_texture_get_paint_volume (ClutterActor *self, Clutte
|
|||||||
typedef enum _MetaShapedTextureType
|
typedef enum _MetaShapedTextureType
|
||||||
{
|
{
|
||||||
META_SHAPED_TEXTURE_TYPE_X11_PIXMAP,
|
META_SHAPED_TEXTURE_TYPE_X11_PIXMAP,
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
META_SHAPED_TEXTURE_TYPE_WAYLAND_SURFACE,
|
META_SHAPED_TEXTURE_TYPE_WAYLAND_SURFACE,
|
||||||
#endif
|
|
||||||
} MetaShapedTextureType;
|
} MetaShapedTextureType;
|
||||||
|
|
||||||
|
|
||||||
@@ -86,21 +83,18 @@ struct _MetaShapedTexturePrivate
|
|||||||
struct {
|
struct {
|
||||||
Pixmap pixmap;
|
Pixmap pixmap;
|
||||||
} x11;
|
} x11;
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
struct {
|
struct {
|
||||||
MetaWaylandSurface *surface;
|
MetaWaylandSurface *surface;
|
||||||
} wayland;
|
} wayland;
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
CoglTexture *texture;
|
CoglTexture *texture;
|
||||||
|
|
||||||
CoglTexture *mask_texture;
|
CoglTexture *mask_texture;
|
||||||
CoglPipeline *pipeline;
|
|
||||||
CoglPipeline *pipeline_unshaped;
|
|
||||||
|
|
||||||
cairo_region_t *clip_region;
|
cairo_region_t *clip_region;
|
||||||
cairo_region_t *input_shape_region;
|
cairo_region_t *input_shape_region;
|
||||||
|
cairo_region_t *opaque_region;
|
||||||
|
|
||||||
guint tex_width, tex_height;
|
guint tex_width, tex_height;
|
||||||
|
|
||||||
@@ -150,8 +144,6 @@ meta_shaped_texture_dispose (GObject *object)
|
|||||||
meta_texture_tower_free (priv->paint_tower);
|
meta_texture_tower_free (priv->paint_tower);
|
||||||
priv->paint_tower = NULL;
|
priv->paint_tower = NULL;
|
||||||
|
|
||||||
g_clear_pointer (&priv->pipeline, cogl_object_unref);
|
|
||||||
g_clear_pointer (&priv->pipeline_unshaped, cogl_object_unref);
|
|
||||||
g_clear_pointer (&priv->texture, cogl_object_unref);
|
g_clear_pointer (&priv->texture, cogl_object_unref);
|
||||||
|
|
||||||
meta_shaped_texture_set_mask_texture (self, NULL);
|
meta_shaped_texture_set_mask_texture (self, NULL);
|
||||||
@@ -160,6 +152,76 @@ meta_shaped_texture_dispose (GObject *object)
|
|||||||
G_OBJECT_CLASS (meta_shaped_texture_parent_class)->dispose (object);
|
G_OBJECT_CLASS (meta_shaped_texture_parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static CoglPipeline *
|
||||||
|
get_unmasked_pipeline (CoglContext *ctx)
|
||||||
|
{
|
||||||
|
return cogl_pipeline_new (ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static CoglPipeline *
|
||||||
|
get_masked_pipeline (CoglContext *ctx)
|
||||||
|
{
|
||||||
|
static CoglPipeline *template = NULL;
|
||||||
|
if (G_UNLIKELY (template == NULL))
|
||||||
|
{
|
||||||
|
template = cogl_pipeline_new (ctx);
|
||||||
|
cogl_pipeline_set_layer_combine (template, 1,
|
||||||
|
"RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cogl_pipeline_copy (template);
|
||||||
|
}
|
||||||
|
|
||||||
|
static CoglPipeline *
|
||||||
|
get_unblended_pipeline (CoglContext *ctx)
|
||||||
|
{
|
||||||
|
static CoglPipeline *template = NULL;
|
||||||
|
if (G_UNLIKELY (template == NULL))
|
||||||
|
{
|
||||||
|
CoglColor color;
|
||||||
|
template = cogl_pipeline_new (ctx);
|
||||||
|
cogl_color_init_from_4ub (&color, 255, 255, 255, 255);
|
||||||
|
cogl_pipeline_set_blend (template,
|
||||||
|
"RGBA = ADD (SRC_COLOR, 0)",
|
||||||
|
NULL);
|
||||||
|
cogl_pipeline_set_color (template, &color);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cogl_pipeline_copy (template);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
paint_clipped_rectangle (CoglFramebuffer *fb,
|
||||||
|
CoglPipeline *pipeline,
|
||||||
|
cairo_rectangle_int_t *rect,
|
||||||
|
ClutterActorBox *alloc)
|
||||||
|
{
|
||||||
|
float coords[8];
|
||||||
|
float x1, y1, x2, y2;
|
||||||
|
|
||||||
|
x1 = rect->x;
|
||||||
|
y1 = rect->y;
|
||||||
|
x2 = rect->x + rect->width;
|
||||||
|
y2 = rect->y + rect->height;
|
||||||
|
|
||||||
|
coords[0] = rect->x / (alloc->x2 - alloc->x1);
|
||||||
|
coords[1] = rect->y / (alloc->y2 - alloc->y1);
|
||||||
|
coords[2] = (rect->x + rect->width) / (alloc->x2 - alloc->x1);
|
||||||
|
coords[3] = (rect->y + rect->height) / (alloc->y2 - alloc->y1);
|
||||||
|
|
||||||
|
coords[4] = coords[0];
|
||||||
|
coords[5] = coords[1];
|
||||||
|
coords[6] = coords[2];
|
||||||
|
coords[7] = coords[3];
|
||||||
|
|
||||||
|
cogl_framebuffer_draw_multitextured_rectangle (fb, pipeline,
|
||||||
|
x1, y1, x2, y2,
|
||||||
|
&coords[0], 8);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_cogl_texture (MetaShapedTexture *stex,
|
set_cogl_texture (MetaShapedTexture *stex,
|
||||||
CoglTexture *cogl_tex)
|
CoglTexture *cogl_tex)
|
||||||
@@ -176,12 +238,6 @@ set_cogl_texture (MetaShapedTexture *stex,
|
|||||||
|
|
||||||
priv->texture = cogl_tex;
|
priv->texture = cogl_tex;
|
||||||
|
|
||||||
if (priv->pipeline != NULL)
|
|
||||||
cogl_pipeline_set_layer_texture (priv->pipeline, 0, COGL_TEXTURE (cogl_tex));
|
|
||||||
|
|
||||||
if (priv->pipeline_unshaped != NULL)
|
|
||||||
cogl_pipeline_set_layer_texture (priv->pipeline_unshaped, 0, COGL_TEXTURE (cogl_tex));
|
|
||||||
|
|
||||||
if (cogl_tex != NULL)
|
if (cogl_tex != NULL)
|
||||||
{
|
{
|
||||||
width = cogl_texture_get_width (COGL_TEXTURE (cogl_tex));
|
width = cogl_texture_get_width (COGL_TEXTURE (cogl_tex));
|
||||||
@@ -215,14 +271,14 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
|||||||
{
|
{
|
||||||
MetaShapedTexture *stex = (MetaShapedTexture *) actor;
|
MetaShapedTexture *stex = (MetaShapedTexture *) actor;
|
||||||
MetaShapedTexturePrivate *priv = stex->priv;
|
MetaShapedTexturePrivate *priv = stex->priv;
|
||||||
CoglTexture *paint_tex;
|
|
||||||
guint tex_width, tex_height;
|
guint tex_width, tex_height;
|
||||||
|
guchar opacity;
|
||||||
|
CoglContext *ctx;
|
||||||
|
CoglFramebuffer *fb;
|
||||||
|
CoglPipeline *pipeline = NULL;
|
||||||
|
CoglTexture *paint_tex;
|
||||||
ClutterActorBox alloc;
|
ClutterActorBox alloc;
|
||||||
|
cairo_region_t *blended_region = NULL;
|
||||||
static CoglPipeline *pipeline_template = NULL;
|
|
||||||
static CoglPipeline *pipeline_unshaped_template = NULL;
|
|
||||||
|
|
||||||
CoglPipeline *pipeline;
|
|
||||||
|
|
||||||
if (priv->clip_region && cairo_region_is_empty (priv->clip_region))
|
if (priv->clip_region && cairo_region_is_empty (priv->clip_region))
|
||||||
return;
|
return;
|
||||||
@@ -259,38 +315,67 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
|||||||
if (tex_width == 0 || tex_height == 0) /* no contents yet */
|
if (tex_width == 0 || tex_height == 0) /* no contents yet */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||||
|
fb = cogl_get_draw_framebuffer ();
|
||||||
|
|
||||||
|
opacity = clutter_actor_get_paint_opacity (actor);
|
||||||
|
clutter_actor_get_allocation_box (actor, &alloc);
|
||||||
|
|
||||||
|
if (priv->opaque_region != NULL && opacity == 255)
|
||||||
|
{
|
||||||
|
CoglPipeline *opaque_pipeline;
|
||||||
|
cairo_region_t *region;
|
||||||
|
int n_rects;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
region = cairo_region_copy (priv->clip_region);
|
||||||
|
cairo_region_intersect (region, priv->opaque_region);
|
||||||
|
|
||||||
|
if (cairo_region_is_empty (region))
|
||||||
|
goto paint_blended;
|
||||||
|
|
||||||
|
opaque_pipeline = get_unblended_pipeline (ctx);
|
||||||
|
cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex);
|
||||||
|
|
||||||
|
n_rects = cairo_region_num_rectangles (region);
|
||||||
|
for (i = 0; i < n_rects; i++)
|
||||||
|
{
|
||||||
|
cairo_rectangle_int_t rect;
|
||||||
|
cairo_region_get_rectangle (region, i, &rect);
|
||||||
|
paint_clipped_rectangle (fb, opaque_pipeline, &rect, &alloc);
|
||||||
|
}
|
||||||
|
|
||||||
|
cogl_object_unref (opaque_pipeline);
|
||||||
|
|
||||||
|
if (priv->clip_region != NULL)
|
||||||
|
{
|
||||||
|
blended_region = cairo_region_copy (priv->clip_region);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cairo_rectangle_int_t rect = { 0, 0, tex_width, tex_height };
|
||||||
|
blended_region = cairo_region_create_rectangle (&rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_region_subtract (blended_region, priv->opaque_region);
|
||||||
|
|
||||||
|
paint_blended:
|
||||||
|
cairo_region_destroy (region);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (blended_region == NULL && priv->clip_region != NULL)
|
||||||
|
blended_region = cairo_region_reference (priv->clip_region);
|
||||||
|
|
||||||
|
if (blended_region != NULL && cairo_region_is_empty (blended_region))
|
||||||
|
goto out;
|
||||||
|
|
||||||
if (priv->mask_texture == NULL)
|
if (priv->mask_texture == NULL)
|
||||||
{
|
{
|
||||||
/* Use a single-layer texture if we don't have a mask. */
|
pipeline = get_unmasked_pipeline (ctx);
|
||||||
|
|
||||||
if (priv->pipeline_unshaped == NULL)
|
|
||||||
{
|
|
||||||
if (G_UNLIKELY (pipeline_unshaped_template == NULL))
|
|
||||||
{
|
|
||||||
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
|
||||||
pipeline_unshaped_template = cogl_pipeline_new (ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
priv->pipeline_unshaped = cogl_pipeline_copy (pipeline_unshaped_template);
|
|
||||||
}
|
|
||||||
pipeline = priv->pipeline_unshaped;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (priv->pipeline == NULL)
|
pipeline = get_masked_pipeline (ctx);
|
||||||
{
|
|
||||||
if (G_UNLIKELY (pipeline_template == NULL))
|
|
||||||
{
|
|
||||||
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
|
||||||
pipeline_template = cogl_pipeline_new (ctx);
|
|
||||||
cogl_pipeline_set_layer_combine (pipeline_template, 1,
|
|
||||||
"RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
priv->pipeline = cogl_pipeline_copy (pipeline_template);
|
|
||||||
}
|
|
||||||
pipeline = priv->pipeline;
|
|
||||||
|
|
||||||
cogl_pipeline_set_layer_texture (pipeline, 1, priv->mask_texture);
|
cogl_pipeline_set_layer_texture (pipeline, 1, priv->mask_texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,20 +383,13 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
|||||||
|
|
||||||
{
|
{
|
||||||
CoglColor color;
|
CoglColor color;
|
||||||
guchar opacity = clutter_actor_get_paint_opacity (actor);
|
cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity);
|
||||||
cogl_color_set_from_4ub (&color, opacity, opacity, opacity, opacity);
|
|
||||||
cogl_pipeline_set_color (pipeline, &color);
|
cogl_pipeline_set_color (pipeline, &color);
|
||||||
}
|
}
|
||||||
|
|
||||||
cogl_set_source (pipeline);
|
if (blended_region != NULL)
|
||||||
|
|
||||||
clutter_actor_get_allocation_box (actor, &alloc);
|
|
||||||
|
|
||||||
if (priv->clip_region)
|
|
||||||
{
|
{
|
||||||
int n_rects;
|
int n_rects;
|
||||||
int i;
|
|
||||||
cairo_rectangle_int_t tex_rect = { 0, 0, tex_width, tex_height };
|
|
||||||
|
|
||||||
/* Limit to how many separate rectangles we'll draw; beyond this just
|
/* Limit to how many separate rectangles we'll draw; beyond this just
|
||||||
* fall back and draw the whole thing */
|
* fall back and draw the whole thing */
|
||||||
@@ -320,8 +398,8 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
|||||||
n_rects = cairo_region_num_rectangles (priv->clip_region);
|
n_rects = cairo_region_num_rectangles (priv->clip_region);
|
||||||
if (n_rects <= MAX_RECTS)
|
if (n_rects <= MAX_RECTS)
|
||||||
{
|
{
|
||||||
float coords[8];
|
int i;
|
||||||
float x1, y1, x2, y2;
|
cairo_rectangle_int_t tex_rect = { 0, 0, tex_width, tex_height };
|
||||||
|
|
||||||
for (i = 0; i < n_rects; i++)
|
for (i = 0; i < n_rects; i++)
|
||||||
{
|
{
|
||||||
@@ -332,32 +410,23 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
|||||||
if (!gdk_rectangle_intersect (&tex_rect, &rect, &rect))
|
if (!gdk_rectangle_intersect (&tex_rect, &rect, &rect))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
x1 = rect.x;
|
paint_clipped_rectangle (fb, pipeline, &rect, &alloc);
|
||||||
y1 = rect.y;
|
|
||||||
x2 = rect.x + rect.width;
|
|
||||||
y2 = rect.y + rect.height;
|
|
||||||
|
|
||||||
coords[0] = rect.x / (alloc.x2 - alloc.x1);
|
|
||||||
coords[1] = rect.y / (alloc.y2 - alloc.y1);
|
|
||||||
coords[2] = (rect.x + rect.width) / (alloc.x2 - alloc.x1);
|
|
||||||
coords[3] = (rect.y + rect.height) / (alloc.y2 - alloc.y1);
|
|
||||||
|
|
||||||
coords[4] = coords[0];
|
|
||||||
coords[5] = coords[1];
|
|
||||||
coords[6] = coords[2];
|
|
||||||
coords[7] = coords[3];
|
|
||||||
|
|
||||||
cogl_rectangle_with_multitexture_coords (x1, y1, x2, y2,
|
|
||||||
&coords[0], 8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cogl_rectangle (0, 0,
|
cogl_framebuffer_draw_rectangle (fb, pipeline,
|
||||||
alloc.x2 - alloc.x1,
|
0, 0,
|
||||||
alloc.y2 - alloc.y1);
|
alloc.x2 - alloc.x1,
|
||||||
|
alloc.y2 - alloc.y1);
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (pipeline != NULL)
|
||||||
|
cogl_object_unref (pipeline);
|
||||||
|
if (blended_region != NULL)
|
||||||
|
cairo_region_destroy (blended_region);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -373,13 +442,17 @@ meta_shaped_texture_pick (ClutterActor *actor,
|
|||||||
|
|
||||||
/* If there is no region then use the regular pick */
|
/* If there is no region then use the regular pick */
|
||||||
if (priv->input_shape_region == NULL)
|
if (priv->input_shape_region == NULL)
|
||||||
CLUTTER_ACTOR_CLASS (meta_shaped_texture_parent_class)
|
CLUTTER_ACTOR_CLASS (meta_shaped_texture_parent_class)->pick (actor, color);
|
||||||
->pick (actor, color);
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int n_rects;
|
int n_rects;
|
||||||
float *rectangles;
|
float *rectangles;
|
||||||
int i;
|
int i;
|
||||||
|
ClutterActorBox alloc;
|
||||||
|
CoglPipeline *pipeline;
|
||||||
|
CoglContext *ctx;
|
||||||
|
CoglFramebuffer *fb;
|
||||||
|
CoglColor cogl_color;
|
||||||
|
|
||||||
/* Note: We don't bother trying to intersect the pick and clip regions
|
/* Note: We don't bother trying to intersect the pick and clip regions
|
||||||
* since needing to copy the region, do the intersection, and probably
|
* since needing to copy the region, do the intersection, and probably
|
||||||
@@ -408,12 +481,17 @@ meta_shaped_texture_pick (ClutterActor *actor,
|
|||||||
rectangles[pos + 3] = rect.y + rect.height;
|
rectangles[pos + 3] = rect.y + rect.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
cogl_set_source_color4ub (color->red,
|
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||||
color->green,
|
fb = cogl_get_draw_framebuffer ();
|
||||||
color->blue,
|
|
||||||
color->alpha);
|
|
||||||
|
|
||||||
cogl_rectangles (rectangles, n_rects);
|
cogl_color_init_from_4ub (&cogl_color, color->red, color->green, color->blue, color->alpha);
|
||||||
|
|
||||||
|
pipeline = cogl_pipeline_new (ctx);
|
||||||
|
cogl_pipeline_set_color (pipeline, &cogl_color);
|
||||||
|
|
||||||
|
cogl_framebuffer_draw_rectangles (fb, pipeline,
|
||||||
|
rectangles, n_rects);
|
||||||
|
cogl_object_unref (pipeline);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -462,7 +540,6 @@ meta_shaped_texture_get_paint_volume (ClutterActor *self,
|
|||||||
return clutter_paint_volume_set_from_allocation (volume, self);
|
return clutter_paint_volume_set_from_allocation (volume, self);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
ClutterActor *
|
ClutterActor *
|
||||||
meta_shaped_texture_new_with_wayland_surface (MetaWaylandSurface *surface)
|
meta_shaped_texture_new_with_wayland_surface (MetaWaylandSurface *surface)
|
||||||
{
|
{
|
||||||
@@ -498,7 +575,6 @@ meta_shaped_texture_get_wayland_surface (MetaShapedTexture *stex)
|
|||||||
MetaShapedTexturePrivate *priv = stex->priv;
|
MetaShapedTexturePrivate *priv = stex->priv;
|
||||||
return priv->wayland.surface;
|
return priv->wayland.surface;
|
||||||
}
|
}
|
||||||
#endif /* HAVE_WAYLAND */
|
|
||||||
|
|
||||||
ClutterActor *
|
ClutterActor *
|
||||||
meta_shaped_texture_new_with_xwindow (Window xwindow)
|
meta_shaped_texture_new_with_xwindow (Window xwindow)
|
||||||
@@ -548,7 +624,6 @@ meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex,
|
|||||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
|
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
static void
|
static void
|
||||||
wayland_surface_update_area (MetaShapedTexture *stex,
|
wayland_surface_update_area (MetaShapedTexture *stex,
|
||||||
int x,
|
int x,
|
||||||
@@ -608,7 +683,6 @@ wayland_surface_update_area (MetaShapedTexture *stex,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* HAVE_WAYLAND */
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
queue_damage_redraw_with_clip (MetaShapedTexture *stex,
|
queue_damage_redraw_with_clip (MetaShapedTexture *stex,
|
||||||
@@ -678,11 +752,9 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
|
|||||||
cogl_texture_pixmap_x11_update_area (COGL_TEXTURE_PIXMAP_X11 (priv->texture),
|
cogl_texture_pixmap_x11_update_area (COGL_TEXTURE_PIXMAP_X11 (priv->texture),
|
||||||
x, y, width, height);
|
x, y, width, height);
|
||||||
break;
|
break;
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
case META_SHAPED_TEXTURE_TYPE_WAYLAND_SURFACE:
|
case META_SHAPED_TEXTURE_TYPE_WAYLAND_SURFACE:
|
||||||
wayland_surface_update_area (stex, x, y, width, height);
|
wayland_surface_update_area (stex, x, y, width, height);
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
meta_texture_tower_update_area (priv->paint_tower, x, y, width, height);
|
meta_texture_tower_update_area (priv->paint_tower, x, y, width, height);
|
||||||
@@ -726,7 +798,6 @@ meta_shaped_texture_set_pixmap (MetaShapedTexture *stex,
|
|||||||
COGL_TEXTURE (priv->texture));
|
COGL_TEXTURE (priv->texture));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
void
|
void
|
||||||
meta_shaped_texture_attach_wayland_buffer (MetaShapedTexture *stex,
|
meta_shaped_texture_attach_wayland_buffer (MetaShapedTexture *stex,
|
||||||
MetaWaylandBuffer *buffer)
|
MetaWaylandBuffer *buffer)
|
||||||
@@ -772,7 +843,6 @@ meta_shaped_texture_attach_wayland_buffer (MetaShapedTexture *stex,
|
|||||||
meta_texture_tower_set_base_texture (priv->paint_tower,
|
meta_texture_tower_set_base_texture (priv->paint_tower,
|
||||||
COGL_TEXTURE (priv->texture));
|
COGL_TEXTURE (priv->texture));
|
||||||
}
|
}
|
||||||
#endif /* HAVE_WAYLAND */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* meta_shaped_texture_get_texture:
|
* meta_shaped_texture_get_texture:
|
||||||
@@ -858,6 +928,36 @@ meta_shaped_texture_set_clip_region (MetaShapedTexture *stex,
|
|||||||
priv->clip_region = NULL;
|
priv->clip_region = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* meta_shaped_texture_set_opaque_region:
|
||||||
|
* @stex: a #MetaShapedTexture
|
||||||
|
* @opaque_region: (transfer full): the region of the texture that
|
||||||
|
* can have blending turned off.
|
||||||
|
*
|
||||||
|
* As most windows have a large portion that does not require blending,
|
||||||
|
* we can easily turn off blending if we know the areas that do not
|
||||||
|
* require blending. This sets the region where we will not blend for
|
||||||
|
* optimization purposes.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
meta_shaped_texture_set_opaque_region (MetaShapedTexture *stex,
|
||||||
|
cairo_region_t *opaque_region)
|
||||||
|
{
|
||||||
|
MetaShapedTexturePrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||||
|
|
||||||
|
priv = stex->priv;
|
||||||
|
|
||||||
|
if (priv->opaque_region)
|
||||||
|
cairo_region_destroy (priv->opaque_region);
|
||||||
|
|
||||||
|
if (opaque_region)
|
||||||
|
priv->opaque_region = cairo_region_reference (opaque_region);
|
||||||
|
else
|
||||||
|
priv->opaque_region = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* meta_shaped_texture_get_image:
|
* meta_shaped_texture_get_image:
|
||||||
* @stex: A #MetaShapedTexture
|
* @stex: A #MetaShapedTexture
|
||||||
|
@@ -5,10 +5,8 @@
|
|||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
#include <wayland-server.h>
|
#include <wayland-server.h>
|
||||||
#include <meta-wayland-private.h>
|
#include <meta-wayland-private.h>
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <X11/extensions/Xdamage.h>
|
#include <X11/extensions/Xdamage.h>
|
||||||
#include <meta/compositor-mutter.h>
|
#include <meta/compositor-mutter.h>
|
||||||
@@ -32,7 +30,6 @@ void meta_window_actor_unmaximize (MetaWindowActor *self,
|
|||||||
void meta_window_actor_process_x11_damage (MetaWindowActor *self,
|
void meta_window_actor_process_x11_damage (MetaWindowActor *self,
|
||||||
XDamageNotifyEvent *event);
|
XDamageNotifyEvent *event);
|
||||||
|
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
void meta_window_actor_process_wayland_damage (MetaWindowActor *self,
|
void meta_window_actor_process_wayland_damage (MetaWindowActor *self,
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
@@ -42,7 +39,6 @@ void meta_window_actor_set_wayland_surface (MetaWindowActor *self,
|
|||||||
MetaWaylandSurface *surface);
|
MetaWaylandSurface *surface);
|
||||||
void meta_window_actor_attach_wayland_buffer (MetaWindowActor *self,
|
void meta_window_actor_attach_wayland_buffer (MetaWindowActor *self,
|
||||||
MetaWaylandBuffer *buffer);
|
MetaWaylandBuffer *buffer);
|
||||||
#endif
|
|
||||||
|
|
||||||
void meta_window_actor_pre_paint (MetaWindowActor *self);
|
void meta_window_actor_pre_paint (MetaWindowActor *self);
|
||||||
void meta_window_actor_post_paint (MetaWindowActor *self);
|
void meta_window_actor_post_paint (MetaWindowActor *self);
|
||||||
|
@@ -10,7 +10,6 @@
|
|||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include <X11/extensions/shape.h>
|
|
||||||
#include <X11/extensions/Xcomposite.h>
|
#include <X11/extensions/Xcomposite.h>
|
||||||
#include <X11/extensions/Xdamage.h>
|
#include <X11/extensions/Xdamage.h>
|
||||||
#include <X11/extensions/Xrender.h>
|
#include <X11/extensions/Xrender.h>
|
||||||
@@ -28,13 +27,12 @@
|
|||||||
#include "xprops.h"
|
#include "xprops.h"
|
||||||
|
|
||||||
#include "compositor-private.h"
|
#include "compositor-private.h"
|
||||||
|
#include "meta-shaped-texture-private.h"
|
||||||
#include "meta-shadow-factory-private.h"
|
#include "meta-shadow-factory-private.h"
|
||||||
#include "meta-window-actor-private.h"
|
#include "meta-window-actor-private.h"
|
||||||
#include "meta-texture-rectangle.h"
|
#include "meta-texture-rectangle.h"
|
||||||
#include "region-utils.h"
|
#include "region-utils.h"
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
#include "meta-wayland-private.h"
|
#include "meta-wayland-private.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
POSITION_CHANGED,
|
POSITION_CHANGED,
|
||||||
@@ -72,7 +70,7 @@ struct _MetaWindowActorPrivate
|
|||||||
/* A region that matches the shape of the window, including frame bounds */
|
/* A region that matches the shape of the window, including frame bounds */
|
||||||
cairo_region_t *shape_region;
|
cairo_region_t *shape_region;
|
||||||
/* If the window has an input shape, a region that matches the shape */
|
/* If the window has an input shape, a region that matches the shape */
|
||||||
cairo_region_t *input_shape_region;
|
cairo_region_t *input_region;
|
||||||
/* The opaque region, from _NET_WM_OPAQUE_REGION, intersected with
|
/* The opaque region, from _NET_WM_OPAQUE_REGION, intersected with
|
||||||
* the shape region. */
|
* the shape region. */
|
||||||
cairo_region_t *opaque_region;
|
cairo_region_t *opaque_region;
|
||||||
@@ -371,11 +369,9 @@ meta_window_actor_constructed (GObject *object)
|
|||||||
|
|
||||||
if (!priv->actor)
|
if (!priv->actor)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
if (meta_is_wayland_compositor ())
|
if (meta_is_wayland_compositor ())
|
||||||
priv->actor = meta_shaped_texture_new_with_wayland_surface (window->surface);
|
priv->actor = meta_shaped_texture_new_with_wayland_surface (window->surface);
|
||||||
else
|
else
|
||||||
#endif
|
|
||||||
priv->actor = meta_shaped_texture_new_with_xwindow (xwindow);
|
priv->actor = meta_shaped_texture_new_with_xwindow (xwindow);
|
||||||
|
|
||||||
clutter_actor_add_child (CLUTTER_ACTOR (self), priv->actor);
|
clutter_actor_add_child (CLUTTER_ACTOR (self), priv->actor);
|
||||||
@@ -392,10 +388,10 @@ meta_window_actor_constructed (GObject *object)
|
|||||||
*/
|
*/
|
||||||
g_object_ref (priv->actor);
|
g_object_ref (priv->actor);
|
||||||
|
|
||||||
g_signal_connect (window, "notify::decorated",
|
g_signal_connect_object (window, "notify::decorated",
|
||||||
G_CALLBACK (window_decorated_notify), self);
|
G_CALLBACK (window_decorated_notify), self, 0);
|
||||||
g_signal_connect (window, "notify::appears-focused",
|
g_signal_connect_object (window, "notify::appears-focused",
|
||||||
G_CALLBACK (window_appears_focused_notify), self);
|
G_CALLBACK (window_appears_focused_notify), self, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -410,8 +406,8 @@ meta_window_actor_constructed (GObject *object)
|
|||||||
|
|
||||||
/* Start off with empty regions to maintain the invariant that
|
/* Start off with empty regions to maintain the invariant that
|
||||||
these regions are always set */
|
these regions are always set */
|
||||||
priv->shape_region = cairo_region_create();
|
priv->shape_region = cairo_region_create ();
|
||||||
priv->input_shape_region = cairo_region_create();
|
priv->input_region = cairo_region_create ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -441,7 +437,7 @@ meta_window_actor_dispose (GObject *object)
|
|||||||
}
|
}
|
||||||
|
|
||||||
g_clear_pointer (&priv->shape_region, cairo_region_destroy);
|
g_clear_pointer (&priv->shape_region, cairo_region_destroy);
|
||||||
g_clear_pointer (&priv->input_shape_region, cairo_region_destroy);
|
g_clear_pointer (&priv->input_region, cairo_region_destroy);
|
||||||
g_clear_pointer (&priv->opaque_region, cairo_region_destroy);
|
g_clear_pointer (&priv->opaque_region, cairo_region_destroy);
|
||||||
g_clear_pointer (&priv->shadow_clip, cairo_region_destroy);
|
g_clear_pointer (&priv->shadow_clip, cairo_region_destroy);
|
||||||
|
|
||||||
@@ -1263,7 +1259,7 @@ meta_window_actor_should_unredirect (MetaWindowActor *self)
|
|||||||
if (priv->opacity != 0xff)
|
if (priv->opacity != 0xff)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (metaWindow->has_shape)
|
if (metaWindow->shape_region != NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (priv->argb32 && !meta_window_requested_bypass_compositor (metaWindow))
|
if (priv->argb32 && !meta_window_requested_bypass_compositor (metaWindow))
|
||||||
@@ -1320,10 +1316,8 @@ meta_window_actor_destroy (MetaWindowActor *self)
|
|||||||
|
|
||||||
priv = self->priv;
|
priv = self->priv;
|
||||||
|
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
if (meta_is_wayland_compositor ())
|
if (meta_is_wayland_compositor ())
|
||||||
meta_shaped_texture_set_wayland_surface (META_SHAPED_TEXTURE (priv->actor), NULL);
|
meta_shaped_texture_set_wayland_surface (META_SHAPED_TEXTURE (priv->actor), NULL);
|
||||||
#endif
|
|
||||||
|
|
||||||
window = priv->window;
|
window = priv->window;
|
||||||
window_type = meta_window_get_window_type (window);
|
window_type = meta_window_get_window_type (window);
|
||||||
@@ -1567,14 +1561,12 @@ meta_window_actor_new (MetaWindow *window)
|
|||||||
|
|
||||||
meta_verbose ("add window: Meta %p, xwin 0x%x\n", window, (guint)top_window);
|
meta_verbose ("add window: Meta %p, xwin 0x%x\n", window, (guint)top_window);
|
||||||
}
|
}
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
meta_verbose ("add window: Meta %p, wayland surface %p\n",
|
meta_verbose ("add window: Meta %p, wayland surface %p\n",
|
||||||
window, window->surface);
|
window, window->surface);
|
||||||
top_window = None;
|
top_window = None;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
self = g_object_new (META_TYPE_WINDOW_ACTOR,
|
self = g_object_new (META_TYPE_WINDOW_ACTOR,
|
||||||
"meta-window", window,
|
"meta-window", window,
|
||||||
@@ -1583,13 +1575,13 @@ meta_window_actor_new (MetaWindow *window)
|
|||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
priv = self->priv;
|
priv = self->priv;
|
||||||
|
priv->mapped = meta_window_toplevel_is_mapped (priv->window);
|
||||||
|
|
||||||
if (!meta_is_wayland_compositor ())
|
if (!meta_is_wayland_compositor ())
|
||||||
{
|
{
|
||||||
priv->last_width = -1;
|
priv->last_width = -1;
|
||||||
priv->last_height = -1;
|
priv->last_height = -1;
|
||||||
|
|
||||||
priv->mapped = meta_window_toplevel_is_mapped (priv->window);
|
|
||||||
if (priv->mapped)
|
if (priv->mapped)
|
||||||
meta_window_actor_queue_create_x11_pixmap (self);
|
meta_window_actor_queue_create_x11_pixmap (self);
|
||||||
|
|
||||||
@@ -2022,7 +2014,6 @@ meta_window_actor_process_x11_damage (MetaWindowActor *self,
|
|||||||
priv->repaint_scheduled = TRUE;
|
priv->repaint_scheduled = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
void
|
void
|
||||||
meta_window_actor_process_wayland_damage (MetaWindowActor *self,
|
meta_window_actor_process_wayland_damage (MetaWindowActor *self,
|
||||||
int x,
|
int x,
|
||||||
@@ -2039,7 +2030,6 @@ meta_window_actor_process_wayland_damage (MetaWindowActor *self,
|
|||||||
x, y, width, height);
|
x, y, width, height);
|
||||||
priv->repaint_scheduled = TRUE;
|
priv->repaint_scheduled = TRUE;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_window_actor_sync_visibility (MetaWindowActor *self)
|
meta_window_actor_sync_visibility (MetaWindowActor *self)
|
||||||
@@ -2180,85 +2170,21 @@ build_and_scan_frame_mask (MetaWindowActor *self,
|
|||||||
g_free (mask_data);
|
g_free (mask_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static cairo_region_t *
|
|
||||||
region_create_from_x_rectangles (const XRectangle *rects,
|
|
||||||
int n_rects,
|
|
||||||
int dx,
|
|
||||||
int dy)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
cairo_rectangle_int_t *cairo_rects = g_newa (cairo_rectangle_int_t, n_rects);
|
|
||||||
|
|
||||||
for (i = 0; i < n_rects; i ++)
|
|
||||||
{
|
|
||||||
cairo_rects[i].x = rects[i].x + dx;
|
|
||||||
cairo_rects[i].y = rects[i].y + dy;
|
|
||||||
cairo_rects[i].width = rects[i].width;
|
|
||||||
cairo_rects[i].height = rects[i].height;
|
|
||||||
}
|
|
||||||
|
|
||||||
return cairo_region_create_rectangles (cairo_rects, n_rects);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_window_actor_update_x11_shape_region (MetaWindowActor *self,
|
meta_window_actor_update_shape_region (MetaWindowActor *self,
|
||||||
cairo_rectangle_int_t *client_area)
|
cairo_rectangle_int_t *client_area)
|
||||||
{
|
{
|
||||||
MetaWindowActorPrivate *priv = self->priv;
|
MetaWindowActorPrivate *priv = self->priv;
|
||||||
cairo_region_t *region = NULL;
|
cairo_region_t *region = NULL;
|
||||||
gboolean needs_mask;
|
|
||||||
|
|
||||||
if (priv->shadow_shape != NULL)
|
if (priv->window->frame != NULL && priv->window->shape_region != NULL)
|
||||||
{
|
{
|
||||||
meta_window_shape_unref (priv->shadow_shape);
|
region = cairo_region_copy (priv->window->shape_region);
|
||||||
priv->shadow_shape = NULL;
|
cairo_region_translate (region, client_area->x, client_area->y);
|
||||||
}
|
}
|
||||||
|
else if (priv->window->shape_region != NULL)
|
||||||
meta_shaped_texture_set_mask_texture (META_SHAPED_TEXTURE (priv->actor), NULL);
|
|
||||||
g_clear_pointer (&priv->shape_region, cairo_region_destroy);
|
|
||||||
g_clear_pointer (&priv->opaque_region, cairo_region_destroy);
|
|
||||||
|
|
||||||
#ifdef HAVE_SHAPE
|
|
||||||
if (priv->window->has_shape)
|
|
||||||
{
|
{
|
||||||
/* Translate the set of XShape rectangles that we
|
region = cairo_region_reference (priv->window->shape_region);
|
||||||
* get from the X server to a cairo_region. */
|
|
||||||
MetaScreen *screen = priv->screen;
|
|
||||||
MetaDisplay *display = meta_screen_get_display (screen);
|
|
||||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
|
||||||
XRectangle *rects;
|
|
||||||
int n_rects, ordering;
|
|
||||||
|
|
||||||
meta_error_trap_push (display);
|
|
||||||
rects = XShapeGetRectangles (xdisplay,
|
|
||||||
priv->window->xwindow,
|
|
||||||
ShapeBounding,
|
|
||||||
&n_rects,
|
|
||||||
&ordering);
|
|
||||||
meta_error_trap_pop (display);
|
|
||||||
|
|
||||||
if (rects)
|
|
||||||
{
|
|
||||||
region = region_create_from_x_rectangles (rects, n_rects,
|
|
||||||
client_area->x,
|
|
||||||
client_area->y);
|
|
||||||
XFree (rects);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
needs_mask = (region != NULL) || (priv->window->frame != NULL);
|
|
||||||
|
|
||||||
if (region != NULL)
|
|
||||||
{
|
|
||||||
/* The shape we get back from the client may have coordinates
|
|
||||||
* outside of the frame. The X SHAPE Extension requires that
|
|
||||||
* the overall shape the client provides never exceeds the
|
|
||||||
* "bounding rectangle" of the window -- the shape that the
|
|
||||||
* window would have gotten if it was unshaped. In our case,
|
|
||||||
* this is simply the client area.
|
|
||||||
*/
|
|
||||||
cairo_region_intersect_rectangle (region, client_area);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -2268,11 +2194,70 @@ meta_window_actor_update_x11_shape_region (MetaWindowActor *self,
|
|||||||
region = cairo_region_create_rectangle (client_area);
|
region = cairo_region_create_rectangle (client_area);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The region at this point should be constrained to the
|
meta_shaped_texture_set_mask_texture (META_SHAPED_TEXTURE (priv->actor), NULL);
|
||||||
* bounds of the client rectangle. */
|
if ((priv->window->shape_region != NULL) || (priv->window->frame != NULL))
|
||||||
|
build_and_scan_frame_mask (self, client_area, region);
|
||||||
|
|
||||||
|
g_clear_pointer (&priv->shape_region, cairo_region_destroy);
|
||||||
|
priv->shape_region = region;
|
||||||
|
|
||||||
|
if (priv->shadow_shape != NULL)
|
||||||
|
{
|
||||||
|
meta_window_shape_unref (priv->shadow_shape);
|
||||||
|
priv->shadow_shape = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
meta_window_actor_invalidate_shadow (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_window_actor_update_input_region (MetaWindowActor *self,
|
||||||
|
cairo_rectangle_int_t *client_area)
|
||||||
|
{
|
||||||
|
MetaWindowActorPrivate *priv = self->priv;
|
||||||
|
MetaShapedTexture *stex = META_SHAPED_TEXTURE (priv->actor);
|
||||||
|
cairo_region_t *region = NULL;
|
||||||
|
|
||||||
|
if (priv->window->frame != NULL && priv->window->shape_region != NULL)
|
||||||
|
{
|
||||||
|
cairo_region_t *client_region = cairo_region_copy (priv->window->input_region);
|
||||||
|
|
||||||
|
region = meta_frame_get_frame_bounds (priv->window->frame);
|
||||||
|
|
||||||
|
cairo_region_subtract_rectangle (region, client_area);
|
||||||
|
cairo_region_translate (client_region, client_area->x, client_area->y);
|
||||||
|
cairo_region_union (region, client_region);
|
||||||
|
cairo_region_destroy (client_region);
|
||||||
|
}
|
||||||
|
else if (priv->window->shape_region != NULL)
|
||||||
|
{
|
||||||
|
region = cairo_region_reference (priv->window->input_region);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* If we don't have a shape on the server, that means that
|
||||||
|
* we have an implicit shape of one rectangle covering the
|
||||||
|
* entire window. */
|
||||||
|
region = cairo_region_create_rectangle (client_area);
|
||||||
|
}
|
||||||
|
|
||||||
|
meta_shaped_texture_set_input_shape_region (stex, region);
|
||||||
|
cairo_region_destroy (region);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_window_actor_update_opaque_region (MetaWindowActor *self)
|
||||||
|
{
|
||||||
|
MetaWindowActorPrivate *priv = self->priv;
|
||||||
|
|
||||||
|
g_clear_pointer (&priv->opaque_region, cairo_region_destroy);
|
||||||
|
|
||||||
if (priv->argb32 && priv->window->opaque_region != NULL)
|
if (priv->argb32 && priv->window->opaque_region != NULL)
|
||||||
{
|
{
|
||||||
|
MetaFrameBorders borders;
|
||||||
|
|
||||||
|
meta_frame_calc_borders (priv->window->frame, &borders);
|
||||||
|
|
||||||
/* The opaque region is defined to be a part of the
|
/* The opaque region is defined to be a part of the
|
||||||
* window which ARGB32 will always paint with opaque
|
* window which ARGB32 will always paint with opaque
|
||||||
* pixels. For these regions, we want to avoid painting
|
* pixels. For these regions, we want to avoid painting
|
||||||
@@ -2284,91 +2269,16 @@ meta_window_actor_update_x11_shape_region (MetaWindowActor *self,
|
|||||||
* case, graphical glitches will occur.
|
* case, graphical glitches will occur.
|
||||||
*/
|
*/
|
||||||
priv->opaque_region = cairo_region_copy (priv->window->opaque_region);
|
priv->opaque_region = cairo_region_copy (priv->window->opaque_region);
|
||||||
cairo_region_translate (priv->opaque_region, client_area->x, client_area->y);
|
cairo_region_translate (priv->opaque_region, borders.total.left, borders.total.top);
|
||||||
cairo_region_intersect (priv->opaque_region, region);
|
cairo_region_intersect (priv->opaque_region, priv->shape_region);
|
||||||
}
|
}
|
||||||
else if (priv->argb32)
|
else if (priv->argb32)
|
||||||
priv->opaque_region = NULL;
|
priv->opaque_region = NULL;
|
||||||
else
|
else
|
||||||
priv->opaque_region = cairo_region_reference (region);
|
priv->opaque_region = cairo_region_reference (priv->shape_region);
|
||||||
|
|
||||||
if (needs_mask)
|
meta_shaped_texture_set_opaque_region (META_SHAPED_TEXTURE (priv->actor),
|
||||||
{
|
priv->opaque_region);
|
||||||
/* This takes the region, generates a mask using GTK+
|
|
||||||
* and scans the mask looking for all opaque pixels,
|
|
||||||
* adding it to region.
|
|
||||||
*/
|
|
||||||
build_and_scan_frame_mask (self, client_area, region);
|
|
||||||
}
|
|
||||||
|
|
||||||
priv->shape_region = region;
|
|
||||||
|
|
||||||
meta_window_actor_invalidate_shadow (self);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_window_actor_update_x11_input_shape_region (MetaWindowActor *self,
|
|
||||||
cairo_rectangle_int_t *client_area)
|
|
||||||
{
|
|
||||||
MetaWindowActorPrivate *priv = self->priv;
|
|
||||||
cairo_region_t *region = NULL;
|
|
||||||
|
|
||||||
g_clear_pointer (&priv->input_shape_region, cairo_region_destroy);
|
|
||||||
|
|
||||||
#ifdef HAVE_SHAPE
|
|
||||||
/* Note: we currently assume that mutter never sets an input region
|
|
||||||
* when there is a frame. */
|
|
||||||
if (priv->window->frame == NULL && priv->window->has_input_shape)
|
|
||||||
{
|
|
||||||
MetaScreen *screen = priv->screen;
|
|
||||||
MetaDisplay *display = meta_screen_get_display (screen);
|
|
||||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
|
||||||
XRectangle *rects;
|
|
||||||
int n_rects, ordering;
|
|
||||||
|
|
||||||
/* Note we only actually query the ShapeInput shape of a window
|
|
||||||
* when we don't have a frame because we assume currently that
|
|
||||||
* mutter never sets an ShapeInput shape on a frame. */
|
|
||||||
meta_error_trap_push (display);
|
|
||||||
rects = XShapeGetRectangles (xdisplay,
|
|
||||||
priv->window->xwindow,
|
|
||||||
ShapeInput,
|
|
||||||
&n_rects,
|
|
||||||
&ordering);
|
|
||||||
meta_error_trap_pop (display);
|
|
||||||
if (rects)
|
|
||||||
{
|
|
||||||
region = region_create_from_x_rectangles (rects, n_rects,
|
|
||||||
client_area->x,
|
|
||||||
client_area->y);
|
|
||||||
XFree (rects);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* HAVE_SHAPE */
|
|
||||||
|
|
||||||
if (region != NULL)
|
|
||||||
{
|
|
||||||
/* The X shape extension requires us to intersect the input
|
|
||||||
* region with the effective bounding shape to determine the
|
|
||||||
* effective input region.
|
|
||||||
*/
|
|
||||||
if (priv->shape_region)
|
|
||||||
cairo_region_intersect (region, priv->shape_region);
|
|
||||||
else
|
|
||||||
cairo_region_intersect_rectangle (region, client_area);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* If we don't have a shape on the server, that means that we
|
|
||||||
* have an implicit shape of one rectangle covering the entire
|
|
||||||
* window. */
|
|
||||||
region = cairo_region_create_rectangle (client_area);
|
|
||||||
}
|
|
||||||
|
|
||||||
priv->input_shape_region = region;
|
|
||||||
|
|
||||||
meta_shaped_texture_set_input_shape_region (META_SHAPED_TEXTURE (priv->actor),
|
|
||||||
priv->input_shape_region);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -2394,24 +2304,9 @@ check_needs_reshape (MetaWindowActor *self)
|
|||||||
else
|
else
|
||||||
client_area.height = priv->window->rect.height;
|
client_area.height = priv->window->rect.height;
|
||||||
|
|
||||||
if (priv->window->client_type == META_WINDOW_CLIENT_TYPE_X11)
|
meta_window_actor_update_shape_region (self, &client_area);
|
||||||
{
|
meta_window_actor_update_input_region (self, &client_area);
|
||||||
meta_window_actor_update_x11_shape_region (self, &client_area);
|
meta_window_actor_update_opaque_region (self);
|
||||||
meta_window_actor_update_x11_input_shape_region (self, &client_area);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* TODO: properly support setting an input region as specified
|
|
||||||
* via the wayland protocol */
|
|
||||||
|
|
||||||
g_clear_pointer (&priv->shape_region, cairo_region_destroy);
|
|
||||||
g_clear_pointer (&priv->opaque_region, cairo_region_destroy);
|
|
||||||
g_clear_pointer (&priv->input_shape_region, cairo_region_destroy);
|
|
||||||
|
|
||||||
priv->shape_region = cairo_region_create_rectangle (&client_area);
|
|
||||||
priv->opaque_region = cairo_region_reference (priv->shape_region);
|
|
||||||
priv->input_shape_region = cairo_region_reference (priv->shape_region);
|
|
||||||
}
|
|
||||||
|
|
||||||
priv->needs_reshape = FALSE;
|
priv->needs_reshape = FALSE;
|
||||||
}
|
}
|
||||||
@@ -2429,7 +2324,6 @@ meta_window_actor_update_shape (MetaWindowActor *self)
|
|||||||
clutter_actor_queue_redraw (priv->actor);
|
clutter_actor_queue_redraw (priv->actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
static void
|
static void
|
||||||
maybe_emit_size_changed (MetaWindowActor *self,
|
maybe_emit_size_changed (MetaWindowActor *self,
|
||||||
MetaWaylandBuffer *new_buffer)
|
MetaWaylandBuffer *new_buffer)
|
||||||
@@ -2473,6 +2367,8 @@ meta_window_actor_set_wayland_surface (MetaWindowActor *self,
|
|||||||
surface);
|
surface);
|
||||||
if (surface && surface->buffer_ref.buffer)
|
if (surface && surface->buffer_ref.buffer)
|
||||||
maybe_emit_size_changed (self, surface->buffer_ref.buffer);
|
maybe_emit_size_changed (self, surface->buffer_ref.buffer);
|
||||||
|
|
||||||
|
meta_window_actor_invalidate_shadow (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -2490,7 +2386,6 @@ meta_window_actor_attach_wayland_buffer (MetaWindowActor *self,
|
|||||||
|
|
||||||
maybe_emit_size_changed (self, buffer);
|
maybe_emit_size_changed (self, buffer);
|
||||||
}
|
}
|
||||||
#endif /* HAVE_WAYLAND */
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_window_actor_handle_updates (MetaWindowActor *self)
|
meta_window_actor_handle_updates (MetaWindowActor *self)
|
||||||
|
@@ -186,8 +186,7 @@ meta_window_group_paint (ClutterActor *actor)
|
|||||||
|
|
||||||
if (META_IS_WINDOW_ACTOR (child))
|
if (META_IS_WINDOW_ACTOR (child))
|
||||||
{
|
{
|
||||||
MetaWindow *meta_window;
|
MetaWindowActor *window_actor = META_WINDOW_ACTOR (child);
|
||||||
MetaWindowActor *window_actor = child;
|
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
if (!meta_actor_is_untransformed (CLUTTER_ACTOR (window_actor), &x, &y))
|
if (!meta_actor_is_untransformed (CLUTTER_ACTOR (window_actor), &x, &y))
|
||||||
@@ -201,14 +200,7 @@ meta_window_group_paint (ClutterActor *actor)
|
|||||||
|
|
||||||
meta_window_actor_set_visible_region (window_actor, visible_region);
|
meta_window_actor_set_visible_region (window_actor, visible_region);
|
||||||
|
|
||||||
/* TODO: Track the opaque regions of wayland clients.
|
if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (window_actor)) == 0xff)
|
||||||
* Although wayland clients can report opaque window
|
|
||||||
* regions, for now we assume that all wayland clients are
|
|
||||||
* transparent... */
|
|
||||||
meta_window = meta_window_actor_get_meta_window (window_actor);
|
|
||||||
|
|
||||||
if (meta_window->client_type != META_WINDOW_CLIENT_TYPE_WAYLAND &&
|
|
||||||
clutter_actor_get_paint_opacity (CLUTTER_ACTOR (window_actor)) == 0xff)
|
|
||||||
{
|
{
|
||||||
cairo_region_t *obscured_region = meta_window_actor_get_obscured_region (window_actor);
|
cairo_region_t *obscured_region = meta_window_actor_get_obscured_region (window_actor);
|
||||||
if (obscured_region)
|
if (obscured_region)
|
||||||
|
@@ -27,7 +27,6 @@
|
|||||||
#include <meta/meta-background-group.h>
|
#include <meta/meta-background-group.h>
|
||||||
#include <meta/meta-background-actor.h>
|
#include <meta/meta-background-actor.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <libintl.h>
|
#include <libintl.h>
|
||||||
#define _(x) dgettext (GETTEXT_PACKAGE, x)
|
#define _(x) dgettext (GETTEXT_PACKAGE, x)
|
||||||
#define N_(x) x
|
#define N_(x) x
|
||||||
|
@@ -75,6 +75,8 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "meta-xwayland-private.h"
|
||||||
|
|
||||||
#define GRAB_OP_IS_WINDOW_SWITCH(g) \
|
#define GRAB_OP_IS_WINDOW_SWITCH(g) \
|
||||||
(g == META_GRAB_OP_KEYBOARD_TABBING_NORMAL || \
|
(g == META_GRAB_OP_KEYBOARD_TABBING_NORMAL || \
|
||||||
g == META_GRAB_OP_KEYBOARD_TABBING_DOCK || \
|
g == META_GRAB_OP_KEYBOARD_TABBING_DOCK || \
|
||||||
@@ -516,9 +518,12 @@ meta_display_open (void)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (meta_is_wayland_compositor ())
|
||||||
|
meta_xwayland_complete_init ();
|
||||||
|
|
||||||
if (meta_is_syncing ())
|
if (meta_is_syncing ())
|
||||||
XSynchronize (xdisplay, True);
|
XSynchronize (xdisplay, True);
|
||||||
|
|
||||||
g_assert (the_display == NULL);
|
g_assert (the_display == NULL);
|
||||||
the_display = g_object_new (META_TYPE_DISPLAY, NULL);
|
the_display = g_object_new (META_TYPE_DISPLAY, NULL);
|
||||||
|
|
||||||
@@ -991,8 +996,10 @@ meta_display_open (void)
|
|||||||
|
|
||||||
meta_error_trap_pop (the_display);
|
meta_error_trap_pop (the_display);
|
||||||
}
|
}
|
||||||
|
|
||||||
meta_display_ungrab (the_display);
|
meta_idle_monitor_init_dbus ();
|
||||||
|
|
||||||
|
meta_display_ungrab (the_display);
|
||||||
|
|
||||||
/* Done opening new display */
|
/* Done opening new display */
|
||||||
the_display->display_opening = FALSE;
|
the_display->display_opening = FALSE;
|
||||||
@@ -1904,9 +1911,7 @@ update_focus_window (MetaDisplay *display,
|
|||||||
Window xwindow,
|
Window xwindow,
|
||||||
gulong serial)
|
gulong serial)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
MetaWaylandCompositor *compositor;
|
MetaWaylandCompositor *compositor;
|
||||||
#endif
|
|
||||||
|
|
||||||
display->focus_serial = serial;
|
display->focus_serial = serial;
|
||||||
|
|
||||||
@@ -1947,7 +1952,6 @@ update_focus_window (MetaDisplay *display,
|
|||||||
else
|
else
|
||||||
meta_topic (META_DEBUG_FOCUS, "* Focus --> NULL with serial %lu\n", serial);
|
meta_topic (META_DEBUG_FOCUS, "* Focus --> NULL with serial %lu\n", serial);
|
||||||
|
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
if (meta_is_wayland_compositor ())
|
if (meta_is_wayland_compositor ())
|
||||||
{
|
{
|
||||||
compositor = meta_wayland_compositor_get_default ();
|
compositor = meta_wayland_compositor_get_default ();
|
||||||
@@ -1960,7 +1964,6 @@ update_focus_window (MetaDisplay *display,
|
|||||||
else
|
else
|
||||||
meta_topic (META_DEBUG_FOCUS, "Focus change has no effect, because there is no matching wayland surface");
|
meta_topic (META_DEBUG_FOCUS, "Focus change has no effect, because there is no matching wayland surface");
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
g_object_notify (G_OBJECT (display), "focus-window");
|
g_object_notify (G_OBJECT (display), "focus-window");
|
||||||
meta_display_update_active_window_hint (display);
|
meta_display_update_active_window_hint (display);
|
||||||
@@ -2317,8 +2320,8 @@ meta_display_handle_event (MetaDisplay *display,
|
|||||||
meta_window_update_sync_request_counter (alarm_window, new_counter_value);
|
meta_window_update_sync_request_counter (alarm_window, new_counter_value);
|
||||||
filter_out_event = TRUE; /* GTK doesn't want to see this really */
|
filter_out_event = TRUE; /* GTK doesn't want to see this really */
|
||||||
}
|
}
|
||||||
|
else
|
||||||
meta_idle_monitor_handle_xevent_all (event);
|
meta_idle_monitor_handle_xevent_all (event);
|
||||||
}
|
}
|
||||||
#endif /* HAVE_XSYNC */
|
#endif /* HAVE_XSYNC */
|
||||||
|
|
||||||
@@ -2333,59 +2336,9 @@ meta_display_handle_event (MetaDisplay *display,
|
|||||||
XShapeEvent *sev = (XShapeEvent*) event;
|
XShapeEvent *sev = (XShapeEvent*) event;
|
||||||
|
|
||||||
if (sev->kind == ShapeBounding)
|
if (sev->kind == ShapeBounding)
|
||||||
{
|
meta_window_update_shape_region_x11 (window);
|
||||||
if (sev->shaped && !window->has_shape)
|
|
||||||
{
|
|
||||||
window->has_shape = TRUE;
|
|
||||||
meta_topic (META_DEBUG_SHAPES,
|
|
||||||
"Window %s now has a shape\n",
|
|
||||||
window->desc);
|
|
||||||
}
|
|
||||||
else if (!sev->shaped && window->has_shape)
|
|
||||||
{
|
|
||||||
window->has_shape = FALSE;
|
|
||||||
meta_topic (META_DEBUG_SHAPES,
|
|
||||||
"Window %s no longer has a shape\n",
|
|
||||||
window->desc);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
meta_topic (META_DEBUG_SHAPES,
|
|
||||||
"Window %s shape changed\n",
|
|
||||||
window->desc);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (display->compositor)
|
|
||||||
meta_compositor_window_x11_shape_changed (display->compositor,
|
|
||||||
window);
|
|
||||||
}
|
|
||||||
else if (sev->kind == ShapeInput)
|
else if (sev->kind == ShapeInput)
|
||||||
{
|
meta_window_update_input_region_x11 (window);
|
||||||
if (sev->shaped && !window->has_input_shape)
|
|
||||||
{
|
|
||||||
window->has_input_shape = TRUE;
|
|
||||||
meta_topic (META_DEBUG_SHAPES,
|
|
||||||
"Window %s now has an input shape\n",
|
|
||||||
window->desc);
|
|
||||||
}
|
|
||||||
else if (!sev->shaped && window->has_input_shape)
|
|
||||||
{
|
|
||||||
window->has_input_shape = FALSE;
|
|
||||||
meta_topic (META_DEBUG_SHAPES,
|
|
||||||
"Window %s no longer has an input shape\n",
|
|
||||||
window->desc);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
meta_topic (META_DEBUG_SHAPES,
|
|
||||||
"Window %s input shape changed\n",
|
|
||||||
window->desc);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (display->compositor)
|
|
||||||
meta_compositor_window_x11_shape_changed (display->compositor,
|
|
||||||
window);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -3231,12 +3184,10 @@ event_callback (XEvent *event,
|
|||||||
erratically because of the lag between updating the window
|
erratically because of the lag between updating the window
|
||||||
position from the surface position. Instead we bypass the
|
position from the surface position. Instead we bypass the
|
||||||
translation altogether by directly using the Clutter events */
|
translation altogether by directly using the Clutter events */
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
if (meta_is_wayland_compositor () &&
|
if (meta_is_wayland_compositor () &&
|
||||||
event->type == GenericEvent &&
|
event->type == GenericEvent &&
|
||||||
event->xcookie.evtype == XI_Motion)
|
event->xcookie.evtype == XI_Motion)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
#endif
|
|
||||||
|
|
||||||
return meta_display_handle_event (display, event);
|
return meta_display_handle_event (display, event);
|
||||||
}
|
}
|
||||||
|
539
src/core/edid-parse.c
Normal file
539
src/core/edid-parse.c
Normal file
@@ -0,0 +1,539 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2007 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* on the rights to use, copy, modify, merge, publish, distribute, sub
|
||||||
|
* license, and/or sell copies of the Software, and to permit persons to whom
|
||||||
|
* the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Author: Soren Sandmann <sandmann@redhat.com> */
|
||||||
|
|
||||||
|
#include "edid.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_bit (int in, int bit)
|
||||||
|
{
|
||||||
|
return (in & (1 << bit)) >> bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_bits (int in, int begin, int end)
|
||||||
|
{
|
||||||
|
int mask = (1 << (end - begin + 1)) - 1;
|
||||||
|
|
||||||
|
return (in >> begin) & mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
decode_header (const uchar *edid)
|
||||||
|
{
|
||||||
|
if (memcmp (edid, "\x00\xff\xff\xff\xff\xff\xff\x00", 8) == 0)
|
||||||
|
return TRUE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
decode_vendor_and_product_identification (const uchar *edid, MonitorInfo *info)
|
||||||
|
{
|
||||||
|
int is_model_year;
|
||||||
|
|
||||||
|
/* Manufacturer Code */
|
||||||
|
info->manufacturer_code[0] = get_bits (edid[0x08], 2, 6);
|
||||||
|
info->manufacturer_code[1] = get_bits (edid[0x08], 0, 1) << 3;
|
||||||
|
info->manufacturer_code[1] |= get_bits (edid[0x09], 5, 7);
|
||||||
|
info->manufacturer_code[2] = get_bits (edid[0x09], 0, 4);
|
||||||
|
info->manufacturer_code[3] = '\0';
|
||||||
|
|
||||||
|
info->manufacturer_code[0] += 'A' - 1;
|
||||||
|
info->manufacturer_code[1] += 'A' - 1;
|
||||||
|
info->manufacturer_code[2] += 'A' - 1;
|
||||||
|
|
||||||
|
/* Product Code */
|
||||||
|
info->product_code = edid[0x0b] << 8 | edid[0x0a];
|
||||||
|
|
||||||
|
/* Serial Number */
|
||||||
|
info->serial_number =
|
||||||
|
edid[0x0c] | edid[0x0d] << 8 | edid[0x0e] << 16 | edid[0x0f] << 24;
|
||||||
|
|
||||||
|
/* Week and Year */
|
||||||
|
is_model_year = FALSE;
|
||||||
|
switch (edid[0x10])
|
||||||
|
{
|
||||||
|
case 0x00:
|
||||||
|
info->production_week = -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xff:
|
||||||
|
info->production_week = -1;
|
||||||
|
is_model_year = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
info->production_week = edid[0x10];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_model_year)
|
||||||
|
{
|
||||||
|
info->production_year = -1;
|
||||||
|
info->model_year = 1990 + edid[0x11];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
info->production_year = 1990 + edid[0x11];
|
||||||
|
info->model_year = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
decode_edid_version (const uchar *edid, MonitorInfo *info)
|
||||||
|
{
|
||||||
|
info->major_version = edid[0x12];
|
||||||
|
info->minor_version = edid[0x13];
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
decode_display_parameters (const uchar *edid, MonitorInfo *info)
|
||||||
|
{
|
||||||
|
/* Digital vs Analog */
|
||||||
|
info->is_digital = get_bit (edid[0x14], 7);
|
||||||
|
|
||||||
|
if (info->is_digital)
|
||||||
|
{
|
||||||
|
int bits;
|
||||||
|
|
||||||
|
static const int bit_depth[8] =
|
||||||
|
{
|
||||||
|
-1, 6, 8, 10, 12, 14, 16, -1
|
||||||
|
};
|
||||||
|
|
||||||
|
static const Interface interfaces[6] =
|
||||||
|
{
|
||||||
|
UNDEFINED, DVI, HDMI_A, HDMI_B, MDDI, DISPLAY_PORT
|
||||||
|
};
|
||||||
|
|
||||||
|
bits = get_bits (edid[0x14], 4, 6);
|
||||||
|
info->connector.digital.bits_per_primary = bit_depth[bits];
|
||||||
|
|
||||||
|
bits = get_bits (edid[0x14], 0, 3);
|
||||||
|
|
||||||
|
if (bits <= 5)
|
||||||
|
info->connector.digital.interface = interfaces[bits];
|
||||||
|
else
|
||||||
|
info->connector.digital.interface = UNDEFINED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int bits = get_bits (edid[0x14], 5, 6);
|
||||||
|
|
||||||
|
static const double levels[][3] =
|
||||||
|
{
|
||||||
|
{ 0.7, 0.3, 1.0 },
|
||||||
|
{ 0.714, 0.286, 1.0 },
|
||||||
|
{ 1.0, 0.4, 1.4 },
|
||||||
|
{ 0.7, 0.0, 0.7 },
|
||||||
|
};
|
||||||
|
|
||||||
|
info->connector.analog.video_signal_level = levels[bits][0];
|
||||||
|
info->connector.analog.sync_signal_level = levels[bits][1];
|
||||||
|
info->connector.analog.total_signal_level = levels[bits][2];
|
||||||
|
|
||||||
|
info->connector.analog.blank_to_black = get_bit (edid[0x14], 4);
|
||||||
|
|
||||||
|
info->connector.analog.separate_hv_sync = get_bit (edid[0x14], 3);
|
||||||
|
info->connector.analog.composite_sync_on_h = get_bit (edid[0x14], 2);
|
||||||
|
info->connector.analog.composite_sync_on_green = get_bit (edid[0x14], 1);
|
||||||
|
|
||||||
|
info->connector.analog.serration_on_vsync = get_bit (edid[0x14], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Screen Size / Aspect Ratio */
|
||||||
|
if (edid[0x15] == 0 && edid[0x16] == 0)
|
||||||
|
{
|
||||||
|
info->width_mm = -1;
|
||||||
|
info->height_mm = -1;
|
||||||
|
info->aspect_ratio = -1.0;
|
||||||
|
}
|
||||||
|
else if (edid[0x16] == 0)
|
||||||
|
{
|
||||||
|
info->width_mm = -1;
|
||||||
|
info->height_mm = -1;
|
||||||
|
info->aspect_ratio = 100.0 / (edid[0x15] + 99);
|
||||||
|
}
|
||||||
|
else if (edid[0x15] == 0)
|
||||||
|
{
|
||||||
|
info->width_mm = -1;
|
||||||
|
info->height_mm = -1;
|
||||||
|
info->aspect_ratio = 100.0 / (edid[0x16] + 99);
|
||||||
|
info->aspect_ratio = 1/info->aspect_ratio; /* portrait */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
info->width_mm = 10 * edid[0x15];
|
||||||
|
info->height_mm = 10 * edid[0x16];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Gamma */
|
||||||
|
if (edid[0x17] == 0xFF)
|
||||||
|
info->gamma = -1.0;
|
||||||
|
else
|
||||||
|
info->gamma = (edid[0x17] + 100.0) / 100.0;
|
||||||
|
|
||||||
|
/* Features */
|
||||||
|
info->standby = get_bit (edid[0x18], 7);
|
||||||
|
info->suspend = get_bit (edid[0x18], 6);
|
||||||
|
info->active_off = get_bit (edid[0x18], 5);
|
||||||
|
|
||||||
|
if (info->is_digital)
|
||||||
|
{
|
||||||
|
info->connector.digital.rgb444 = TRUE;
|
||||||
|
if (get_bit (edid[0x18], 3))
|
||||||
|
info->connector.digital.ycrcb444 = 1;
|
||||||
|
if (get_bit (edid[0x18], 4))
|
||||||
|
info->connector.digital.ycrcb422 = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int bits = get_bits (edid[0x18], 3, 4);
|
||||||
|
ColorType color_type[4] =
|
||||||
|
{
|
||||||
|
MONOCHROME, RGB, OTHER_COLOR, UNDEFINED_COLOR
|
||||||
|
};
|
||||||
|
|
||||||
|
info->connector.analog.color_type = color_type[bits];
|
||||||
|
}
|
||||||
|
|
||||||
|
info->srgb_is_standard = get_bit (edid[0x18], 2);
|
||||||
|
|
||||||
|
/* In 1.3 this is called "has preferred timing" */
|
||||||
|
info->preferred_timing_includes_native = get_bit (edid[0x18], 1);
|
||||||
|
|
||||||
|
/* FIXME: In 1.3 this indicates whether the monitor accepts GTF */
|
||||||
|
info->continuous_frequency = get_bit (edid[0x18], 0);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static double
|
||||||
|
decode_fraction (int high, int low)
|
||||||
|
{
|
||||||
|
double result = 0.0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
high = (high << 2) | low;
|
||||||
|
|
||||||
|
for (i = 0; i < 10; ++i)
|
||||||
|
result += get_bit (high, i) * pow (2, i - 10);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
decode_color_characteristics (const uchar *edid, MonitorInfo *info)
|
||||||
|
{
|
||||||
|
info->red_x = decode_fraction (edid[0x1b], get_bits (edid[0x19], 6, 7));
|
||||||
|
info->red_y = decode_fraction (edid[0x1c], get_bits (edid[0x19], 5, 4));
|
||||||
|
info->green_x = decode_fraction (edid[0x1d], get_bits (edid[0x19], 2, 3));
|
||||||
|
info->green_y = decode_fraction (edid[0x1e], get_bits (edid[0x19], 0, 1));
|
||||||
|
info->blue_x = decode_fraction (edid[0x1f], get_bits (edid[0x1a], 6, 7));
|
||||||
|
info->blue_y = decode_fraction (edid[0x20], get_bits (edid[0x1a], 4, 5));
|
||||||
|
info->white_x = decode_fraction (edid[0x21], get_bits (edid[0x1a], 2, 3));
|
||||||
|
info->white_y = decode_fraction (edid[0x22], get_bits (edid[0x1a], 0, 1));
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
decode_established_timings (const uchar *edid, MonitorInfo *info)
|
||||||
|
{
|
||||||
|
static const Timing established[][8] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
{ 800, 600, 60 },
|
||||||
|
{ 800, 600, 56 },
|
||||||
|
{ 640, 480, 75 },
|
||||||
|
{ 640, 480, 72 },
|
||||||
|
{ 640, 480, 67 },
|
||||||
|
{ 640, 480, 60 },
|
||||||
|
{ 720, 400, 88 },
|
||||||
|
{ 720, 400, 70 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{ 1280, 1024, 75 },
|
||||||
|
{ 1024, 768, 75 },
|
||||||
|
{ 1024, 768, 70 },
|
||||||
|
{ 1024, 768, 60 },
|
||||||
|
{ 1024, 768, 87 },
|
||||||
|
{ 832, 624, 75 },
|
||||||
|
{ 800, 600, 75 },
|
||||||
|
{ 800, 600, 72 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{ 0, 0, 0 },
|
||||||
|
{ 0, 0, 0 },
|
||||||
|
{ 0, 0, 0 },
|
||||||
|
{ 0, 0, 0 },
|
||||||
|
{ 0, 0, 0 },
|
||||||
|
{ 0, 0, 0 },
|
||||||
|
{ 0, 0, 0 },
|
||||||
|
{ 1152, 870, 75 }
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
int i, j, idx;
|
||||||
|
|
||||||
|
idx = 0;
|
||||||
|
for (i = 0; i < 3; ++i)
|
||||||
|
{
|
||||||
|
for (j = 0; j < 8; ++j)
|
||||||
|
{
|
||||||
|
int byte = edid[0x23 + i];
|
||||||
|
|
||||||
|
if (get_bit (byte, j) && established[i][j].frequency != 0)
|
||||||
|
info->established[idx++] = established[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
decode_standard_timings (const uchar *edid, MonitorInfo *info)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
int first = edid[0x26 + 2 * i];
|
||||||
|
int second = edid[0x27 + 2 * i];
|
||||||
|
|
||||||
|
if (first != 0x01 && second != 0x01)
|
||||||
|
{
|
||||||
|
int w = 8 * (first + 31);
|
||||||
|
int h = 0;
|
||||||
|
|
||||||
|
switch (get_bits (second, 6, 7))
|
||||||
|
{
|
||||||
|
case 0x00: h = (w / 16) * 10; break;
|
||||||
|
case 0x01: h = (w / 4) * 3; break;
|
||||||
|
case 0x02: h = (w / 5) * 4; break;
|
||||||
|
case 0x03: h = (w / 16) * 9; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
info->standard[i].width = w;
|
||||||
|
info->standard[i].height = h;
|
||||||
|
info->standard[i].frequency = get_bits (second, 0, 5) + 60;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
decode_lf_string (const uchar *s, int n_chars, char *result)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < n_chars; ++i)
|
||||||
|
{
|
||||||
|
if (s[i] == 0x0a)
|
||||||
|
{
|
||||||
|
*result++ = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (s[i] == 0x00)
|
||||||
|
{
|
||||||
|
/* Convert embedded 0's to spaces */
|
||||||
|
*result++ = ' ';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*result++ = s[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
decode_display_descriptor (const uchar *desc,
|
||||||
|
MonitorInfo *info)
|
||||||
|
{
|
||||||
|
switch (desc[0x03])
|
||||||
|
{
|
||||||
|
case 0xFC:
|
||||||
|
decode_lf_string (desc + 5, 13, info->dsc_product_name);
|
||||||
|
break;
|
||||||
|
case 0xFF:
|
||||||
|
decode_lf_string (desc + 5, 13, info->dsc_serial_number);
|
||||||
|
break;
|
||||||
|
case 0xFE:
|
||||||
|
decode_lf_string (desc + 5, 13, info->dsc_string);
|
||||||
|
break;
|
||||||
|
case 0xFD:
|
||||||
|
/* Range Limits */
|
||||||
|
break;
|
||||||
|
case 0xFB:
|
||||||
|
/* Color Point */
|
||||||
|
break;
|
||||||
|
case 0xFA:
|
||||||
|
/* Timing Identifications */
|
||||||
|
break;
|
||||||
|
case 0xF9:
|
||||||
|
/* Color Management */
|
||||||
|
break;
|
||||||
|
case 0xF8:
|
||||||
|
/* Timing Codes */
|
||||||
|
break;
|
||||||
|
case 0xF7:
|
||||||
|
/* Established Timings */
|
||||||
|
break;
|
||||||
|
case 0x10:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
decode_detailed_timing (const uchar *timing,
|
||||||
|
DetailedTiming *detailed)
|
||||||
|
{
|
||||||
|
int bits;
|
||||||
|
StereoType stereo[] =
|
||||||
|
{
|
||||||
|
NO_STEREO, NO_STEREO, FIELD_RIGHT, FIELD_LEFT,
|
||||||
|
TWO_WAY_RIGHT_ON_EVEN, TWO_WAY_LEFT_ON_EVEN,
|
||||||
|
FOUR_WAY_INTERLEAVED, SIDE_BY_SIDE
|
||||||
|
};
|
||||||
|
|
||||||
|
detailed->pixel_clock = (timing[0x00] | timing[0x01] << 8) * 10000;
|
||||||
|
detailed->h_addr = timing[0x02] | ((timing[0x04] & 0xf0) << 4);
|
||||||
|
detailed->h_blank = timing[0x03] | ((timing[0x04] & 0x0f) << 8);
|
||||||
|
detailed->v_addr = timing[0x05] | ((timing[0x07] & 0xf0) << 4);
|
||||||
|
detailed->v_blank = timing[0x06] | ((timing[0x07] & 0x0f) << 8);
|
||||||
|
detailed->h_front_porch = timing[0x08] | get_bits (timing[0x0b], 6, 7) << 8;
|
||||||
|
detailed->h_sync = timing[0x09] | get_bits (timing[0x0b], 4, 5) << 8;
|
||||||
|
detailed->v_front_porch =
|
||||||
|
get_bits (timing[0x0a], 4, 7) | get_bits (timing[0x0b], 2, 3) << 4;
|
||||||
|
detailed->v_sync =
|
||||||
|
get_bits (timing[0x0a], 0, 3) | get_bits (timing[0x0b], 0, 1) << 4;
|
||||||
|
detailed->width_mm = timing[0x0c] | get_bits (timing[0x0e], 4, 7) << 8;
|
||||||
|
detailed->height_mm = timing[0x0d] | get_bits (timing[0x0e], 0, 3) << 8;
|
||||||
|
detailed->right_border = timing[0x0f];
|
||||||
|
detailed->top_border = timing[0x10];
|
||||||
|
|
||||||
|
detailed->interlaced = get_bit (timing[0x11], 7);
|
||||||
|
|
||||||
|
/* Stereo */
|
||||||
|
bits = get_bits (timing[0x11], 5, 6) << 1 | get_bit (timing[0x11], 0);
|
||||||
|
detailed->stereo = stereo[bits];
|
||||||
|
|
||||||
|
/* Sync */
|
||||||
|
bits = timing[0x11];
|
||||||
|
|
||||||
|
detailed->digital_sync = get_bit (bits, 4);
|
||||||
|
if (detailed->digital_sync)
|
||||||
|
{
|
||||||
|
detailed->connector.digital.composite = !get_bit (bits, 3);
|
||||||
|
|
||||||
|
if (detailed->connector.digital.composite)
|
||||||
|
{
|
||||||
|
detailed->connector.digital.serrations = get_bit (bits, 2);
|
||||||
|
detailed->connector.digital.negative_vsync = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
detailed->connector.digital.serrations = FALSE;
|
||||||
|
detailed->connector.digital.negative_vsync = !get_bit (bits, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
detailed->connector.digital.negative_hsync = !get_bit (bits, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
detailed->connector.analog.bipolar = get_bit (bits, 3);
|
||||||
|
detailed->connector.analog.serrations = get_bit (bits, 2);
|
||||||
|
detailed->connector.analog.sync_on_green = !get_bit (bits, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
decode_descriptors (const uchar *edid, MonitorInfo *info)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int timing_idx;
|
||||||
|
|
||||||
|
timing_idx = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
int index = 0x36 + i * 18;
|
||||||
|
|
||||||
|
if (edid[index + 0] == 0x00 && edid[index + 1] == 0x00)
|
||||||
|
{
|
||||||
|
decode_display_descriptor (edid + index, info);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
decode_detailed_timing (edid + index, &(info->detailed_timings[timing_idx++]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
info->n_detailed_timings = timing_idx;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
decode_check_sum (const uchar *edid,
|
||||||
|
MonitorInfo *info)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uchar check = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < 128; ++i)
|
||||||
|
check += edid[i];
|
||||||
|
|
||||||
|
info->checksum = check;
|
||||||
|
}
|
||||||
|
|
||||||
|
MonitorInfo *
|
||||||
|
decode_edid (const uchar *edid)
|
||||||
|
{
|
||||||
|
MonitorInfo *info = g_new0 (MonitorInfo, 1);
|
||||||
|
|
||||||
|
decode_check_sum (edid, info);
|
||||||
|
|
||||||
|
if (decode_header (edid)
|
||||||
|
&& decode_vendor_and_product_identification (edid, info)
|
||||||
|
&& decode_edid_version (edid, info)
|
||||||
|
&& decode_display_parameters (edid, info)
|
||||||
|
&& decode_color_characteristics (edid, info)
|
||||||
|
&& decode_established_timings (edid, info)
|
||||||
|
&& decode_standard_timings (edid, info)
|
||||||
|
&& decode_descriptors (edid, info))
|
||||||
|
{
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_free (info);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
195
src/core/edid.h
Normal file
195
src/core/edid.h
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
/* edid.h
|
||||||
|
*
|
||||||
|
* Copyright 2007, 2008, Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of the Gnome Library.
|
||||||
|
*
|
||||||
|
* The Gnome Library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* The Gnome Library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with the Gnome Library; see the file COPYING.LIB. If not,
|
||||||
|
* write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* Author: Soren Sandmann <sandmann@redhat.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EDID_H
|
||||||
|
#define EDID_H
|
||||||
|
|
||||||
|
typedef unsigned char uchar;
|
||||||
|
typedef struct MonitorInfo MonitorInfo;
|
||||||
|
typedef struct Timing Timing;
|
||||||
|
typedef struct DetailedTiming DetailedTiming;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
UNDEFINED,
|
||||||
|
DVI,
|
||||||
|
HDMI_A,
|
||||||
|
HDMI_B,
|
||||||
|
MDDI,
|
||||||
|
DISPLAY_PORT
|
||||||
|
} Interface;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
UNDEFINED_COLOR,
|
||||||
|
MONOCHROME,
|
||||||
|
RGB,
|
||||||
|
OTHER_COLOR
|
||||||
|
} ColorType;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
NO_STEREO,
|
||||||
|
FIELD_RIGHT,
|
||||||
|
FIELD_LEFT,
|
||||||
|
TWO_WAY_RIGHT_ON_EVEN,
|
||||||
|
TWO_WAY_LEFT_ON_EVEN,
|
||||||
|
FOUR_WAY_INTERLEAVED,
|
||||||
|
SIDE_BY_SIDE
|
||||||
|
} StereoType;
|
||||||
|
|
||||||
|
struct Timing
|
||||||
|
{
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int frequency;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DetailedTiming
|
||||||
|
{
|
||||||
|
int pixel_clock;
|
||||||
|
int h_addr;
|
||||||
|
int h_blank;
|
||||||
|
int h_sync;
|
||||||
|
int h_front_porch;
|
||||||
|
int v_addr;
|
||||||
|
int v_blank;
|
||||||
|
int v_sync;
|
||||||
|
int v_front_porch;
|
||||||
|
int width_mm;
|
||||||
|
int height_mm;
|
||||||
|
int right_border;
|
||||||
|
int top_border;
|
||||||
|
int interlaced;
|
||||||
|
StereoType stereo;
|
||||||
|
|
||||||
|
int digital_sync;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int bipolar;
|
||||||
|
int serrations;
|
||||||
|
int sync_on_green;
|
||||||
|
} analog;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int composite;
|
||||||
|
int serrations;
|
||||||
|
int negative_vsync;
|
||||||
|
int negative_hsync;
|
||||||
|
} digital;
|
||||||
|
} connector;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MonitorInfo
|
||||||
|
{
|
||||||
|
int checksum;
|
||||||
|
char manufacturer_code[4];
|
||||||
|
int product_code;
|
||||||
|
unsigned int serial_number;
|
||||||
|
|
||||||
|
int production_week; /* -1 if not specified */
|
||||||
|
int production_year; /* -1 if not specified */
|
||||||
|
int model_year; /* -1 if not specified */
|
||||||
|
|
||||||
|
int major_version;
|
||||||
|
int minor_version;
|
||||||
|
|
||||||
|
int is_digital;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int bits_per_primary;
|
||||||
|
Interface interface;
|
||||||
|
int rgb444;
|
||||||
|
int ycrcb444;
|
||||||
|
int ycrcb422;
|
||||||
|
} digital;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
double video_signal_level;
|
||||||
|
double sync_signal_level;
|
||||||
|
double total_signal_level;
|
||||||
|
|
||||||
|
int blank_to_black;
|
||||||
|
|
||||||
|
int separate_hv_sync;
|
||||||
|
int composite_sync_on_h;
|
||||||
|
int composite_sync_on_green;
|
||||||
|
int serration_on_vsync;
|
||||||
|
ColorType color_type;
|
||||||
|
} analog;
|
||||||
|
} connector;
|
||||||
|
|
||||||
|
int width_mm; /* -1 if not specified */
|
||||||
|
int height_mm; /* -1 if not specified */
|
||||||
|
double aspect_ratio; /* -1.0 if not specififed */
|
||||||
|
|
||||||
|
double gamma; /* -1.0 if not specified */
|
||||||
|
|
||||||
|
int standby;
|
||||||
|
int suspend;
|
||||||
|
int active_off;
|
||||||
|
|
||||||
|
int srgb_is_standard;
|
||||||
|
int preferred_timing_includes_native;
|
||||||
|
int continuous_frequency;
|
||||||
|
|
||||||
|
double red_x;
|
||||||
|
double red_y;
|
||||||
|
double green_x;
|
||||||
|
double green_y;
|
||||||
|
double blue_x;
|
||||||
|
double blue_y;
|
||||||
|
double white_x;
|
||||||
|
double white_y;
|
||||||
|
|
||||||
|
Timing established[24]; /* Terminated by 0x0x0 */
|
||||||
|
Timing standard[8];
|
||||||
|
|
||||||
|
int n_detailed_timings;
|
||||||
|
DetailedTiming detailed_timings[4]; /* If monitor has a preferred
|
||||||
|
* mode, it is the first one
|
||||||
|
* (whether it has, is
|
||||||
|
* determined by the
|
||||||
|
* preferred_timing_includes
|
||||||
|
* bit.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Optional product description */
|
||||||
|
char dsc_serial_number[14];
|
||||||
|
char dsc_product_name[14];
|
||||||
|
char dsc_string[14]; /* Unspecified ASCII data */
|
||||||
|
};
|
||||||
|
|
||||||
|
MonitorInfo *decode_edid (const uchar *data);
|
||||||
|
char *make_display_name (const MonitorInfo *info);
|
||||||
|
char *make_display_size_string (int width_mm, int height_mm);
|
||||||
|
|
||||||
|
#endif
|
@@ -53,10 +53,6 @@
|
|||||||
#include <X11/XKBlib.h>
|
#include <X11/XKBlib.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
#include "meta-wayland-private.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define SCHEMA_COMMON_KEYBINDINGS "org.gnome.desktop.wm.keybindings"
|
#define SCHEMA_COMMON_KEYBINDINGS "org.gnome.desktop.wm.keybindings"
|
||||||
#define SCHEMA_MUTTER_KEYBINDINGS "org.gnome.mutter.keybindings"
|
#define SCHEMA_MUTTER_KEYBINDINGS "org.gnome.mutter.keybindings"
|
||||||
|
|
||||||
@@ -1969,6 +1965,23 @@ process_overlay_key (MetaDisplay *display,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
meta_display_overlay_key_activate (display);
|
meta_display_overlay_key_activate (display);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* In some rare race condition, mutter might not receive the Super_L
|
||||||
|
* KeyRelease event because:
|
||||||
|
* - the compositor might end the modal mode and call XIUngrabDevice
|
||||||
|
* while the key is still down
|
||||||
|
* - passive grabs are only activated on KeyPress and not KeyRelease.
|
||||||
|
*
|
||||||
|
* In this case, display->overlay_key_only_pressed might be wrong.
|
||||||
|
* Mutter still ought to acknowledge events, otherwise the X server
|
||||||
|
* will not send the next events.
|
||||||
|
*
|
||||||
|
* https://bugzilla.gnome.org/show_bug.cgi?id=666101
|
||||||
|
*/
|
||||||
|
XIAllowEvents (display->xdisplay, event->deviceid,
|
||||||
|
XIAsyncDevice, event->time);
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -4085,40 +4098,6 @@ handle_set_spew_mark (MetaDisplay *display,
|
|||||||
meta_verbose ("-- MARK MARK MARK MARK --\n");
|
meta_verbose ("-- MARK MARK MARK MARK --\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
static void
|
|
||||||
handle_switch_vt (MetaDisplay *display,
|
|
||||||
MetaScreen *screen,
|
|
||||||
MetaWindow *window,
|
|
||||||
XIDeviceEvent *event,
|
|
||||||
MetaKeyBinding *binding,
|
|
||||||
gpointer dummy)
|
|
||||||
{
|
|
||||||
gint vt = binding->handler->data;
|
|
||||||
MetaWaylandCompositor *compositor;
|
|
||||||
MetaTTY *tty;
|
|
||||||
|
|
||||||
compositor = meta_wayland_compositor_get_default ();
|
|
||||||
tty = meta_wayland_compositor_get_tty (compositor);
|
|
||||||
|
|
||||||
if (tty)
|
|
||||||
{
|
|
||||||
GError *error;
|
|
||||||
|
|
||||||
error = NULL;
|
|
||||||
if (!meta_tty_activate_vt (tty, vt, &error))
|
|
||||||
{
|
|
||||||
g_warning ("Failed to switch VT: %s", error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_debug ("Ignoring VT switch keybinding, not running as VT manager");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* meta_keybindings_set_custom_handler:
|
* meta_keybindings_set_custom_handler:
|
||||||
* @name: The name of the keybinding to set
|
* @name: The name of the keybinding to set
|
||||||
@@ -4443,60 +4422,6 @@ init_builtin_key_bindings (MetaDisplay *display)
|
|||||||
META_KEYBINDING_ACTION_SET_SPEW_MARK,
|
META_KEYBINDING_ACTION_SET_SPEW_MARK,
|
||||||
handle_set_spew_mark, 0);
|
handle_set_spew_mark, 0);
|
||||||
|
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
if (meta_is_wayland_compositor ())
|
|
||||||
{
|
|
||||||
add_builtin_keybinding (display,
|
|
||||||
"switch-to-session-1",
|
|
||||||
mutter_keybindings,
|
|
||||||
META_KEY_BINDING_NONE,
|
|
||||||
META_KEYBINDING_ACTION_NONE,
|
|
||||||
handle_switch_vt, 1);
|
|
||||||
|
|
||||||
add_builtin_keybinding (display,
|
|
||||||
"switch-to-session-2",
|
|
||||||
mutter_keybindings,
|
|
||||||
META_KEY_BINDING_NONE,
|
|
||||||
META_KEYBINDING_ACTION_NONE,
|
|
||||||
handle_switch_vt, 2);
|
|
||||||
|
|
||||||
add_builtin_keybinding (display,
|
|
||||||
"switch-to-session-3",
|
|
||||||
mutter_keybindings,
|
|
||||||
META_KEY_BINDING_NONE,
|
|
||||||
META_KEYBINDING_ACTION_NONE,
|
|
||||||
handle_switch_vt, 3);
|
|
||||||
|
|
||||||
add_builtin_keybinding (display,
|
|
||||||
"switch-to-session-4",
|
|
||||||
mutter_keybindings,
|
|
||||||
META_KEY_BINDING_NONE,
|
|
||||||
META_KEYBINDING_ACTION_NONE,
|
|
||||||
handle_switch_vt, 4);
|
|
||||||
|
|
||||||
add_builtin_keybinding (display,
|
|
||||||
"switch-to-session-5",
|
|
||||||
mutter_keybindings,
|
|
||||||
META_KEY_BINDING_NONE,
|
|
||||||
META_KEYBINDING_ACTION_NONE,
|
|
||||||
handle_switch_vt, 5);
|
|
||||||
|
|
||||||
add_builtin_keybinding (display,
|
|
||||||
"switch-to-session-6",
|
|
||||||
mutter_keybindings,
|
|
||||||
META_KEY_BINDING_NONE,
|
|
||||||
META_KEYBINDING_ACTION_NONE,
|
|
||||||
handle_switch_vt, 6);
|
|
||||||
|
|
||||||
add_builtin_keybinding (display,
|
|
||||||
"switch-to-session-7",
|
|
||||||
mutter_keybindings,
|
|
||||||
META_KEY_BINDING_NONE,
|
|
||||||
META_KEYBINDING_ACTION_NONE,
|
|
||||||
handle_switch_vt, 7);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#undef REVERSES_AND_REVERSED
|
#undef REVERSES_AND_REVERSED
|
||||||
|
|
||||||
/************************ PER WINDOW BINDINGS ************************/
|
/************************ PER WINDOW BINDINGS ************************/
|
||||||
|
105
src/core/main.c
105
src/core/main.c
@@ -55,12 +55,9 @@
|
|||||||
#include "session.h"
|
#include "session.h"
|
||||||
#include <meta/prefs.h>
|
#include <meta/prefs.h>
|
||||||
#include <meta/compositor.h>
|
#include <meta/compositor.h>
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
#include "meta-wayland-private.h"
|
#include "meta-wayland-private.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
#include <glib-unix.h>
|
|
||||||
#include <gdk/gdkx.h>
|
#include <gdk/gdkx.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -351,40 +348,63 @@ meta_finalize (void)
|
|||||||
meta_display_close (display,
|
meta_display_close (display,
|
||||||
CurrentTime); /* I doubt correct timestamps matter here */
|
CurrentTime); /* I doubt correct timestamps matter here */
|
||||||
|
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
if (meta_is_wayland_compositor ())
|
if (meta_is_wayland_compositor ())
|
||||||
meta_wayland_finalize ();
|
meta_wayland_finalize ();
|
||||||
#endif
|
}
|
||||||
|
|
||||||
|
static int signal_pipe_fds[2] = { -1, -1 };
|
||||||
|
|
||||||
|
static void
|
||||||
|
signal_handler (int signum)
|
||||||
|
{
|
||||||
|
if (signal_pipe_fds[1] >= 0)
|
||||||
|
{
|
||||||
|
switch (signum)
|
||||||
|
{
|
||||||
|
case SIGTERM:
|
||||||
|
write (signal_pipe_fds[1], "T", 1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
on_sigterm (gpointer user_data)
|
on_signal (GIOChannel *source,
|
||||||
|
GIOCondition condition,
|
||||||
|
void *data)
|
||||||
{
|
{
|
||||||
meta_quit (EXIT_SUCCESS);
|
char signal;
|
||||||
|
int count;
|
||||||
|
|
||||||
return G_SOURCE_REMOVE;
|
for (;;)
|
||||||
}
|
{
|
||||||
|
count = read (signal_pipe_fds[0], &signal, 1);
|
||||||
|
if (count == EINTR)
|
||||||
|
continue;
|
||||||
|
if (count < 0)
|
||||||
|
{
|
||||||
|
const char *msg = strerror (errno);
|
||||||
|
g_warning ("Error handling signal: %s", msg);
|
||||||
|
}
|
||||||
|
if (count != 1)
|
||||||
|
{
|
||||||
|
g_warning ("Unexpectedly failed to read byte from signal pipe\n");
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (signal)
|
||||||
|
{
|
||||||
|
case 'T': /* SIGTERM */
|
||||||
|
meta_quit (META_EXIT_SUCCESS);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_warning ("Spurious character '%c' read from signal pipe", signal);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
return TRUE;
|
||||||
crash_handler (int signum)
|
|
||||||
{
|
|
||||||
char buffer[256];
|
|
||||||
MetaWaylandCompositor *compositor;
|
|
||||||
MetaTTY *tty;
|
|
||||||
|
|
||||||
snprintf (buffer, 256, "Fatal server error: %d\n", signum);
|
|
||||||
write (STDERR_FILENO, buffer, strlen (buffer));
|
|
||||||
|
|
||||||
compositor = meta_wayland_compositor_get_default ();
|
|
||||||
tty = meta_wayland_compositor_get_tty (compositor);
|
|
||||||
|
|
||||||
/* Passing FALSE ensures that we only do ioctls, which is
|
|
||||||
safe from a signal handler */
|
|
||||||
if (tty)
|
|
||||||
meta_tty_reset (tty, FALSE);
|
|
||||||
|
|
||||||
/* We can't continue with the default handling, so just exit here */
|
|
||||||
_exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -398,6 +418,7 @@ meta_init (void)
|
|||||||
{
|
{
|
||||||
struct sigaction act;
|
struct sigaction act;
|
||||||
sigset_t empty_mask;
|
sigset_t empty_mask;
|
||||||
|
GIOChannel *channel;
|
||||||
|
|
||||||
sigemptyset (&empty_mask);
|
sigemptyset (&empty_mask);
|
||||||
act.sa_handler = SIG_IGN;
|
act.sa_handler = SIG_IGN;
|
||||||
@@ -412,20 +433,20 @@ meta_init (void)
|
|||||||
g_strerror (errno));
|
g_strerror (errno));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (meta_is_wayland_compositor ())
|
if (pipe (signal_pipe_fds) != 0)
|
||||||
{
|
g_printerr ("Failed to create signal pipe: %s\n",
|
||||||
act.sa_handler = crash_handler;
|
g_strerror (errno));
|
||||||
|
|
||||||
/* Ignore if we can't register signal handlers, worse
|
channel = g_io_channel_unix_new (signal_pipe_fds[0]);
|
||||||
that can happen one needs the sysrq to get out of the VT */
|
g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, NULL);
|
||||||
sigaction (SIGABRT, &act, NULL);
|
g_io_add_watch (channel, G_IO_IN, (GIOFunc) on_signal, NULL);
|
||||||
sigaction (SIGSEGV, &act, NULL);
|
g_io_channel_set_close_on_unref (channel, TRUE);
|
||||||
sigaction (SIGBUS, &act, NULL);
|
g_io_channel_unref (channel);
|
||||||
sigaction (SIGFPE, &act, NULL);
|
|
||||||
sigaction (SIGTRAP, &act, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_unix_signal_add (SIGTERM, on_sigterm, NULL);
|
act.sa_handler = &signal_handler;
|
||||||
|
if (sigaction (SIGTERM, &act, NULL) < 0)
|
||||||
|
g_printerr ("Failed to register SIGTERM handler: %s\n",
|
||||||
|
g_strerror (errno));
|
||||||
|
|
||||||
if (g_getenv ("MUTTER_VERBOSE"))
|
if (g_getenv ("MUTTER_VERBOSE"))
|
||||||
meta_set_verbose (TRUE);
|
meta_set_verbose (TRUE);
|
||||||
@@ -443,7 +464,6 @@ meta_init (void)
|
|||||||
g_irepository_prepend_search_path (MUTTER_PKGLIBDIR);
|
g_irepository_prepend_search_path (MUTTER_PKGLIBDIR);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
if (meta_is_wayland_compositor ())
|
if (meta_is_wayland_compositor ())
|
||||||
{
|
{
|
||||||
/* NB: When running as a hybrid wayland compositor we run our own headless X
|
/* NB: When running as a hybrid wayland compositor we run our own headless X
|
||||||
@@ -451,7 +471,6 @@ meta_init (void)
|
|||||||
meta_wayland_init ();
|
meta_wayland_init ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
|
||||||
meta_select_display (opt_display_name);
|
meta_select_display (opt_display_name);
|
||||||
|
|
||||||
meta_set_syncing (opt_sync || (g_getenv ("MUTTER_SYNC") != NULL));
|
meta_set_syncing (opt_sync || (g_getenv ("MUTTER_SYNC") != NULL));
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
#define META_CURSOR_TRACKER_PRIVATE_H
|
#define META_CURSOR_TRACKER_PRIVATE_H
|
||||||
|
|
||||||
#include <meta/meta-cursor-tracker.h>
|
#include <meta/meta-cursor-tracker.h>
|
||||||
|
#include <clutter/clutter.h>
|
||||||
|
|
||||||
gboolean meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
|
gboolean meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
|
||||||
XEvent *xevent);
|
XEvent *xevent);
|
||||||
|
@@ -39,7 +39,10 @@
|
|||||||
|
|
||||||
#include "meta-cursor-tracker-private.h"
|
#include "meta-cursor-tracker-private.h"
|
||||||
#include "screen-private.h"
|
#include "screen-private.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_WAYLAND
|
||||||
#include "meta-wayland-private.h"
|
#include "meta-wayland-private.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_X 7
|
#define META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_X 7
|
||||||
#define META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_Y 4
|
#define META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_Y 4
|
||||||
@@ -123,6 +126,7 @@ meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass)
|
|||||||
G_TYPE_NONE, 0);
|
G_TYPE_NONE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_WAYLAND
|
||||||
static MetaCursorTracker *
|
static MetaCursorTracker *
|
||||||
make_wayland_cursor_tracker (MetaScreen *screen)
|
make_wayland_cursor_tracker (MetaScreen *screen)
|
||||||
{
|
{
|
||||||
@@ -139,6 +143,7 @@ make_wayland_cursor_tracker (MetaScreen *screen)
|
|||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static MetaCursorTracker *
|
static MetaCursorTracker *
|
||||||
make_x11_cursor_tracker (MetaScreen *screen)
|
make_x11_cursor_tracker (MetaScreen *screen)
|
||||||
@@ -169,9 +174,11 @@ meta_cursor_tracker_get_for_screen (MetaScreen *screen)
|
|||||||
if (screen->cursor_tracker)
|
if (screen->cursor_tracker)
|
||||||
return screen->cursor_tracker;
|
return screen->cursor_tracker;
|
||||||
|
|
||||||
|
#ifdef HAVE_WAYLAND
|
||||||
if (meta_is_wayland_compositor ())
|
if (meta_is_wayland_compositor ())
|
||||||
self = make_wayland_cursor_tracker (screen);
|
self = make_wayland_cursor_tracker (screen);
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
self = make_x11_cursor_tracker (screen);
|
self = make_x11_cursor_tracker (screen);
|
||||||
|
|
||||||
screen->cursor_tracker = self;
|
screen->cursor_tracker = self;
|
||||||
@@ -312,8 +319,8 @@ ensure_wayland_cursor (MetaCursorTracker *tracker)
|
|||||||
if (tracker->default_cursor)
|
if (tracker->default_cursor)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
filename = g_build_filename (MUTTER_DATADIR,
|
filename = g_build_filename (MUTTER_PKGDATADIR,
|
||||||
"mutter/cursors/left_ptr.png",
|
"cursors/left_ptr.png",
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
bitmap = cogl_bitmap_new_from_file (filename, NULL);
|
bitmap = cogl_bitmap_new_from_file (filename, NULL);
|
||||||
|
@@ -104,25 +104,26 @@ _xsyncvalue_to_int64 (XSyncValue value)
|
|||||||
| (guint64) XSyncValueLow32 (value);
|
| (guint64) XSyncValueLow32 (value);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define GINT64_TO_XSYNCVALUE(value, ret) XSyncIntsToValue (ret, value, ((guint64)value) >> 32)
|
#define GUINT64_TO_XSYNCVALUE(value, ret) XSyncIntsToValue (ret, (value) & 0xFFFFFFFF, ((guint64)(value)) >> 32)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fire_watch (MetaIdleMonitorWatch *watch)
|
fire_watch (MetaIdleMonitorWatch *watch)
|
||||||
{
|
{
|
||||||
MetaIdleMonitor *monitor;
|
MetaIdleMonitor *monitor;
|
||||||
|
guint id;
|
||||||
|
gboolean is_user_active_watch;
|
||||||
|
|
||||||
monitor = watch->monitor;
|
monitor = watch->monitor;
|
||||||
g_object_ref (monitor);
|
g_object_ref (monitor);
|
||||||
|
|
||||||
if (watch->callback)
|
id = watch->id;
|
||||||
{
|
is_user_active_watch = (watch->timeout_msec == 0);
|
||||||
watch->callback (watch->monitor,
|
|
||||||
watch->id,
|
|
||||||
watch->user_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (watch->timeout_msec == 0)
|
if (watch->callback)
|
||||||
meta_idle_monitor_remove_watch (watch->monitor, watch->id);
|
watch->callback (monitor, id, watch->user_data);
|
||||||
|
|
||||||
|
if (is_user_active_watch)
|
||||||
|
meta_idle_monitor_remove_watch (monitor, id);
|
||||||
|
|
||||||
g_object_unref (monitor);
|
g_object_unref (monitor);
|
||||||
}
|
}
|
||||||
@@ -146,7 +147,7 @@ _xsync_alarm_set (MetaIdleMonitor *monitor,
|
|||||||
attr.delta = delta;
|
attr.delta = delta;
|
||||||
attr.events = want_events;
|
attr.events = want_events;
|
||||||
|
|
||||||
GINT64_TO_XSYNCVALUE (interval, &attr.trigger.wait_value);
|
GUINT64_TO_XSYNCVALUE (interval, &attr.trigger.wait_value);
|
||||||
attr.trigger.test_type = test_type;
|
attr.trigger.test_type = test_type;
|
||||||
return XSyncCreateAlarm (monitor->display, flags, &attr);
|
return XSyncCreateAlarm (monitor->display, flags, &attr);
|
||||||
}
|
}
|
||||||
@@ -219,7 +220,7 @@ meta_idle_monitor_handle_xevent (MetaIdleMonitor *monitor,
|
|||||||
{
|
{
|
||||||
watches = g_hash_table_get_values (monitor->watches);
|
watches = g_hash_table_get_values (monitor->watches);
|
||||||
|
|
||||||
g_list_foreach (watches, check_x11_watch, monitor);
|
g_list_foreach (watches, check_x11_watch, (gpointer) alarm);
|
||||||
g_list_free (watches);
|
g_list_free (watches);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -308,7 +309,10 @@ init_xsync (MetaIdleMonitor *monitor)
|
|||||||
monitor->counter = find_idletime_counter (monitor);
|
monitor->counter = find_idletime_counter (monitor);
|
||||||
/* IDLETIME counter not found? */
|
/* IDLETIME counter not found? */
|
||||||
if (monitor->counter == None)
|
if (monitor->counter == None)
|
||||||
return;
|
{
|
||||||
|
meta_warning ("IDLETIME counter not found\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
monitor->user_active_alarm = _xsync_alarm_set (monitor, XSyncNegativeTransition, 1, FALSE);
|
monitor->user_active_alarm = _xsync_alarm_set (monitor, XSyncNegativeTransition, 1, FALSE);
|
||||||
}
|
}
|
||||||
@@ -632,7 +636,7 @@ meta_idle_monitor_remove_watch (MetaIdleMonitor *monitor,
|
|||||||
*
|
*
|
||||||
* Returns: The current idle time, in milliseconds, or -1 for not supported
|
* Returns: The current idle time, in milliseconds, or -1 for not supported
|
||||||
*/
|
*/
|
||||||
guint64
|
gint64
|
||||||
meta_idle_monitor_get_idletime (MetaIdleMonitor *monitor)
|
meta_idle_monitor_get_idletime (MetaIdleMonitor *monitor)
|
||||||
{
|
{
|
||||||
XSyncValue value;
|
XSyncValue value;
|
||||||
@@ -787,7 +791,7 @@ make_dbus_watch (MetaDBusIdleMonitor *skeleton,
|
|||||||
static gboolean
|
static gboolean
|
||||||
handle_add_idle_watch (MetaDBusIdleMonitor *skeleton,
|
handle_add_idle_watch (MetaDBusIdleMonitor *skeleton,
|
||||||
GDBusMethodInvocation *invocation,
|
GDBusMethodInvocation *invocation,
|
||||||
guint64 interval,
|
guint64 interval,
|
||||||
MetaIdleMonitor *monitor)
|
MetaIdleMonitor *monitor)
|
||||||
{
|
{
|
||||||
DBusWatch *watch;
|
DBusWatch *watch;
|
||||||
@@ -831,30 +835,12 @@ handle_remove_watch (MetaDBusIdleMonitor *skeleton,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_device_added (ClutterDeviceManager *device_manager,
|
create_monitor_skeleton (GDBusObjectManagerServer *manager,
|
||||||
ClutterInputDevice *device,
|
MetaIdleMonitor *monitor,
|
||||||
GDBusObjectManagerServer *manager)
|
const char *path)
|
||||||
{
|
{
|
||||||
MetaDBusIdleMonitor *skeleton;
|
MetaDBusIdleMonitor *skeleton;
|
||||||
MetaIdleMonitor *monitor;
|
|
||||||
MetaDBusObjectSkeleton *object;
|
MetaDBusObjectSkeleton *object;
|
||||||
int device_id;
|
|
||||||
gboolean is_core;
|
|
||||||
char *path;
|
|
||||||
|
|
||||||
is_core = clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_MASTER;
|
|
||||||
|
|
||||||
if (is_core)
|
|
||||||
{
|
|
||||||
monitor = meta_idle_monitor_get_core ();
|
|
||||||
path = g_strdup ("/org/gnome/Mutter/IdleMonitor/Core");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
device_id = clutter_input_device_get_device_id (device);
|
|
||||||
monitor = meta_idle_monitor_get_for_device (device_id);
|
|
||||||
path = g_strdup_printf ("/org/gnome/Mutter/IdleMonitor/Device%d", device_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
skeleton = meta_dbus_idle_monitor_skeleton_new ();
|
skeleton = meta_dbus_idle_monitor_skeleton_new ();
|
||||||
g_signal_connect_object (skeleton, "handle-add-idle-watch",
|
g_signal_connect_object (skeleton, "handle-add-idle-watch",
|
||||||
@@ -872,6 +858,42 @@ on_device_added (ClutterDeviceManager *device_manager,
|
|||||||
g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (object));
|
g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (object));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_device_added (ClutterDeviceManager *device_manager,
|
||||||
|
ClutterInputDevice *device,
|
||||||
|
GDBusObjectManagerServer *manager)
|
||||||
|
{
|
||||||
|
|
||||||
|
MetaIdleMonitor *monitor;
|
||||||
|
int device_id;
|
||||||
|
char *path;
|
||||||
|
|
||||||
|
device_id = clutter_input_device_get_device_id (device);
|
||||||
|
monitor = meta_idle_monitor_get_for_device (device_id);
|
||||||
|
path = g_strdup_printf ("/org/gnome/Mutter/IdleMonitor/Device%d", device_id);
|
||||||
|
|
||||||
|
create_monitor_skeleton (manager, monitor, path);
|
||||||
|
g_free (path);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_device_removed (ClutterDeviceManager *device_manager,
|
||||||
|
ClutterInputDevice *device,
|
||||||
|
GDBusObjectManagerServer *manager)
|
||||||
|
{
|
||||||
|
int device_id;
|
||||||
|
char *path;
|
||||||
|
|
||||||
|
device_id = clutter_input_device_get_device_id (device);
|
||||||
|
path = g_strdup_printf ("/org/gnome/Mutter/IdleMonitor/Device%d", device_id);
|
||||||
|
g_dbus_object_manager_server_unexport (manager, path);
|
||||||
|
g_free (path);
|
||||||
|
|
||||||
|
g_clear_object (&device_monitors[device_id]);
|
||||||
|
if (device_id == device_id_max)
|
||||||
|
device_id_max--;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_bus_acquired (GDBusConnection *connection,
|
on_bus_acquired (GDBusConnection *connection,
|
||||||
const char *name,
|
const char *name,
|
||||||
@@ -879,10 +901,19 @@ on_bus_acquired (GDBusConnection *connection,
|
|||||||
{
|
{
|
||||||
GDBusObjectManagerServer *manager;
|
GDBusObjectManagerServer *manager;
|
||||||
ClutterDeviceManager *device_manager;
|
ClutterDeviceManager *device_manager;
|
||||||
|
MetaIdleMonitor *monitor;
|
||||||
GSList *devices, *iter;
|
GSList *devices, *iter;
|
||||||
|
char *path;
|
||||||
|
|
||||||
manager = g_dbus_object_manager_server_new ("/org/gnome/Mutter/IdleMonitor");
|
manager = g_dbus_object_manager_server_new ("/org/gnome/Mutter/IdleMonitor");
|
||||||
|
|
||||||
|
/* We never clear the core monitor, as that's supposed to cumulate idle times from
|
||||||
|
all devices */
|
||||||
|
monitor = meta_idle_monitor_get_core ();
|
||||||
|
path = g_strdup ("/org/gnome/Mutter/IdleMonitor/Core");
|
||||||
|
create_monitor_skeleton (manager, monitor, path);
|
||||||
|
g_free (path);
|
||||||
|
|
||||||
device_manager = clutter_device_manager_get_default ();
|
device_manager = clutter_device_manager_get_default ();
|
||||||
devices = clutter_device_manager_list_devices (device_manager);
|
devices = clutter_device_manager_list_devices (device_manager);
|
||||||
|
|
||||||
@@ -891,8 +922,10 @@ on_bus_acquired (GDBusConnection *connection,
|
|||||||
|
|
||||||
g_signal_connect_object (device_manager, "device-added",
|
g_signal_connect_object (device_manager, "device-added",
|
||||||
G_CALLBACK (on_device_added), manager, 0);
|
G_CALLBACK (on_device_added), manager, 0);
|
||||||
|
g_signal_connect_object (device_manager, "device-removed",
|
||||||
|
G_CALLBACK (on_device_removed), manager, 0);
|
||||||
|
|
||||||
g_dbus_object_manager_server_set_connection (manager, g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL));
|
g_dbus_object_manager_server_set_connection (manager, connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -900,7 +933,7 @@ on_name_acquired (GDBusConnection *connection,
|
|||||||
const char *name,
|
const char *name,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
meta_topic (META_DEBUG_DBUS, "Acquired name %s\n", name);
|
meta_verbose ("Acquired name %s\n", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -908,7 +941,7 @@ on_name_lost (GDBusConnection *connection,
|
|||||||
const char *name,
|
const char *name,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
meta_topic (META_DEBUG_DBUS, "Lost or failed to acquire name %s\n", name);
|
meta_verbose ("Lost or failed to acquire name %s\n", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@@ -190,7 +190,7 @@ meta_monitor_config_init (MetaMonitorConfig *self)
|
|||||||
|
|
||||||
filename = g_getenv ("MUTTER_MONITOR_FILENAME");
|
filename = g_getenv ("MUTTER_MONITOR_FILENAME");
|
||||||
if (filename == NULL)
|
if (filename == NULL)
|
||||||
filename = "monitors-test.xml"; /* FIXME after testing */
|
filename = "monitors.xml";
|
||||||
|
|
||||||
path = g_build_filename (g_get_user_config_dir (), filename, NULL);
|
path = g_build_filename (g_get_user_config_dir (), filename, NULL);
|
||||||
self->file = g_file_new_for_path (path);
|
self->file = g_file_new_for_path (path);
|
||||||
@@ -952,8 +952,6 @@ meta_monitor_config_apply_stored (MetaMonitorConfig *self,
|
|||||||
* or failing that, an output that is good to be a primary (LVDS or eDP,
|
* or failing that, an output that is good to be a primary (LVDS or eDP,
|
||||||
* which are internal monitors), or failing that, the one with the
|
* which are internal monitors), or failing that, the one with the
|
||||||
* best resolution
|
* best resolution
|
||||||
*
|
|
||||||
* Input assertions: there is at least one output
|
|
||||||
*/
|
*/
|
||||||
static MetaOutput *
|
static MetaOutput *
|
||||||
find_primary_output (MetaOutput *outputs,
|
find_primary_output (MetaOutput *outputs,
|
||||||
@@ -963,6 +961,8 @@ find_primary_output (MetaOutput *outputs,
|
|||||||
MetaOutput *best;
|
MetaOutput *best;
|
||||||
int best_width, best_height;
|
int best_width, best_height;
|
||||||
|
|
||||||
|
g_assert (n_outputs >= 1);
|
||||||
|
|
||||||
for (i = 0; i < n_outputs; i++)
|
for (i = 0; i < n_outputs; i++)
|
||||||
{
|
{
|
||||||
if (outputs[i].is_primary)
|
if (outputs[i].is_primary)
|
||||||
@@ -1029,6 +1029,9 @@ make_default_config (MetaMonitorConfig *self,
|
|||||||
In the latter case, search for a configuration that includes one
|
In the latter case, search for a configuration that includes one
|
||||||
less screen, then add the new one as a presentation screen
|
less screen, then add the new one as a presentation screen
|
||||||
in preferred mode.
|
in preferred mode.
|
||||||
|
|
||||||
|
XXX: but presentation mode is not implemented in the control-center
|
||||||
|
or in mutter core, so let's do extended for now.
|
||||||
*/
|
*/
|
||||||
x = 0;
|
x = 0;
|
||||||
y = 0;
|
y = 0;
|
||||||
@@ -1054,7 +1057,7 @@ make_default_config (MetaMonitorConfig *self,
|
|||||||
}
|
}
|
||||||
else if (j > i)
|
else if (j > i)
|
||||||
{
|
{
|
||||||
g_assert (output_key_equal (&ret->keys[i], &ref->keys[j - 1]));
|
g_assert (output_key_equal (&ret->keys[j], &ref->keys[j - 1]));
|
||||||
ret->outputs[j] = ref->outputs[j - 1];
|
ret->outputs[j] = ref->outputs[j - 1];
|
||||||
x = MAX (x, ref->outputs[j - 1].rect.x + ref->outputs[j - 1].rect.width);
|
x = MAX (x, ref->outputs[j - 1].rect.x + ref->outputs[j - 1].rect.width);
|
||||||
y = MAX (y, ref->outputs[j - 1].rect.y + ref->outputs[j - 1].rect.height);
|
y = MAX (y, ref->outputs[j - 1].rect.y + ref->outputs[j - 1].rect.height);
|
||||||
@@ -1069,7 +1072,7 @@ make_default_config (MetaMonitorConfig *self,
|
|||||||
ret->outputs[j].refresh_rate = outputs[0].preferred_mode->refresh_rate;
|
ret->outputs[j].refresh_rate = outputs[0].preferred_mode->refresh_rate;
|
||||||
ret->outputs[j].transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
ret->outputs[j].transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||||
ret->outputs[j].is_primary = FALSE;
|
ret->outputs[j].is_primary = FALSE;
|
||||||
ret->outputs[j].is_presentation = TRUE;
|
ret->outputs[j].is_presentation = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1252,9 +1255,7 @@ meta_monitor_config_restore_previous (MetaMonitorConfig *self,
|
|||||||
MetaMonitorManager *manager)
|
MetaMonitorManager *manager)
|
||||||
{
|
{
|
||||||
if (self->previous)
|
if (self->previous)
|
||||||
{
|
apply_configuration (self, self->previous, manager, FALSE);
|
||||||
apply_configuration (self, self->previous, manager, FALSE);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!meta_monitor_config_apply_stored (self, manager))
|
if (!meta_monitor_config_apply_stored (self, manager))
|
||||||
@@ -1543,7 +1544,7 @@ crtc_assignment_assign (CrtcAssignment *assign,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MetaCRTCInfo *info = g_slice_new0 (MetaCRTCInfo);
|
MetaCRTCInfo *info = g_slice_new0 (MetaCRTCInfo);
|
||||||
|
|
||||||
info->crtc = crtc;
|
info->crtc = crtc;
|
||||||
@@ -1555,7 +1556,7 @@ crtc_assignment_assign (CrtcAssignment *assign,
|
|||||||
|
|
||||||
g_ptr_array_add (info->outputs, output);
|
g_ptr_array_add (info->outputs, output);
|
||||||
g_hash_table_insert (assign->info, crtc, info);
|
g_hash_table_insert (assign->info, crtc, info);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1653,15 +1654,28 @@ real_assign_crtcs (CrtcAssignment *assignment,
|
|||||||
for (j = 0; j < n_modes; j++)
|
for (j = 0; j < n_modes; j++)
|
||||||
{
|
{
|
||||||
MetaMonitorMode *mode = &modes[j];
|
MetaMonitorMode *mode = &modes[j];
|
||||||
|
int width, height;
|
||||||
|
|
||||||
if (mode->width == output_config->rect.width &&
|
if (meta_monitor_transform_is_rotated (output_config->transform))
|
||||||
mode->height == output_config->rect.height &&
|
{
|
||||||
|
width = mode->height;
|
||||||
|
height = mode->width;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
width = mode->width;
|
||||||
|
height = mode->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (width == output_config->rect.width &&
|
||||||
|
height == output_config->rect.height &&
|
||||||
(pass == 1 || mode->refresh_rate == output_config->refresh_rate))
|
(pass == 1 || mode->refresh_rate == output_config->refresh_rate))
|
||||||
{
|
{
|
||||||
meta_verbose ("CRTC %ld: trying mode %dx%d@%fHz with output at %dx%d@%fHz (pass %d)\n",
|
meta_verbose ("CRTC %ld: trying mode %dx%d@%fHz with output at %dx%d@%fHz (transform %d) (pass %d)\n",
|
||||||
crtc->crtc_id,
|
crtc->crtc_id,
|
||||||
mode->width, mode->height, mode->refresh_rate,
|
mode->width, mode->height, mode->refresh_rate,
|
||||||
output_config->rect.width, output_config->rect.height, output_config->refresh_rate,
|
output_config->rect.width, output_config->rect.height, output_config->refresh_rate,
|
||||||
|
output_config->transform,
|
||||||
pass);
|
pass);
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,767 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2013 Red Hat Inc.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
||||||
* 02111-1307, USA.
|
|
||||||
*
|
|
||||||
* Author: Giovanni Campagna <gcampagn@redhat.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <clutter/clutter.h>
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <xf86drm.h>
|
|
||||||
#include <xf86drmMode.h>
|
|
||||||
|
|
||||||
#include <meta/main.h>
|
|
||||||
#include <meta/errors.h>
|
|
||||||
#include "monitor-private.h"
|
|
||||||
|
|
||||||
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
drmModeConnector *connector;
|
|
||||||
|
|
||||||
unsigned n_encoders;
|
|
||||||
drmModeEncoderPtr *encoders;
|
|
||||||
drmModeEncoderPtr current_encoder;
|
|
||||||
|
|
||||||
/* bitmasks of encoder position in the resources array */
|
|
||||||
uint32_t encoder_mask;
|
|
||||||
uint32_t enc_clone_mask;
|
|
||||||
|
|
||||||
uint32_t dpms_prop_id;
|
|
||||||
} MetaOutputKms;
|
|
||||||
|
|
||||||
struct _MetaMonitorManagerKms
|
|
||||||
{
|
|
||||||
MetaMonitorManager parent_instance;
|
|
||||||
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
drmModeConnector **connectors;
|
|
||||||
unsigned int n_connectors;
|
|
||||||
|
|
||||||
drmModeEncoder **encoders;
|
|
||||||
unsigned int n_encoders;
|
|
||||||
|
|
||||||
drmModeEncoder *current_encoder;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _MetaMonitorManagerKmsClass
|
|
||||||
{
|
|
||||||
MetaMonitorManagerClass parent_class;
|
|
||||||
};
|
|
||||||
|
|
||||||
G_DEFINE_TYPE (MetaMonitorManagerKms, meta_monitor_manager_kms, META_TYPE_MONITOR_MANAGER);
|
|
||||||
|
|
||||||
static int
|
|
||||||
compare_outputs (const void *one,
|
|
||||||
const void *two)
|
|
||||||
{
|
|
||||||
const MetaOutput *o_one = one, *o_two = two;
|
|
||||||
|
|
||||||
return strcmp (o_one->name, o_two->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *
|
|
||||||
make_output_name (drmModeConnector *connector)
|
|
||||||
{
|
|
||||||
static const char * const connector_type_names[] = {
|
|
||||||
"unknown", "VGA", "DVII", "DVID", "DVID", "Composite",
|
|
||||||
"SVIDEO", "LVDS", "Component", "9PinDIN", "DisplayPort",
|
|
||||||
"HDMIA", "HDMIB", "TV", "eDP"
|
|
||||||
};
|
|
||||||
const char *connector_type_name;
|
|
||||||
|
|
||||||
if (connector->connector_type >= 0 &&
|
|
||||||
connector->connector_type < G_N_ELEMENTS (connector_type_names))
|
|
||||||
connector_type_name = connector_type_names[connector->connector_type];
|
|
||||||
else
|
|
||||||
connector_type_name = "unknown";
|
|
||||||
|
|
||||||
return g_strdup_printf ("%s%d", connector_type_name, connector->connector_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_output_destroy_notify (MetaOutput *output)
|
|
||||||
{
|
|
||||||
MetaOutputKms *output_kms;
|
|
||||||
unsigned i;
|
|
||||||
|
|
||||||
output_kms = output->driver_private;
|
|
||||||
|
|
||||||
for (i = 0; i < output_kms->n_encoders; i++)
|
|
||||||
drmModeFreeEncoder (output_kms->encoders[i]);
|
|
||||||
|
|
||||||
g_slice_free (MetaOutputKms, output_kms);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_monitor_mode_destroy_notify (MetaMonitorMode *output)
|
|
||||||
{
|
|
||||||
g_slice_free (drmModeModeInfo, output->driver_private);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
drm_mode_equal (gconstpointer one,
|
|
||||||
gconstpointer two)
|
|
||||||
{
|
|
||||||
return memcmp (one, two, sizeof (drmModeModeInfo)) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static guint
|
|
||||||
drm_mode_hash (gconstpointer ptr)
|
|
||||||
{
|
|
||||||
const drmModeModeInfo *mode = ptr;
|
|
||||||
guint hash = 0;
|
|
||||||
|
|
||||||
hash ^= mode->clock;
|
|
||||||
hash ^= mode->hdisplay ^ mode->hsync_start ^ mode->hsync_end;
|
|
||||||
hash ^= mode->vdisplay ^ mode->vsync_start ^ mode->vsync_end;
|
|
||||||
hash ^= mode->vrefresh;
|
|
||||||
hash ^= mode->flags ^ mode->type;
|
|
||||||
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
|
|
||||||
{
|
|
||||||
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
|
|
||||||
drmModeRes *resources;
|
|
||||||
GHashTable *modes;
|
|
||||||
GHashTableIter iter;
|
|
||||||
drmModeModeInfo *mode;
|
|
||||||
unsigned int i, j, k;
|
|
||||||
unsigned int n_actual_outputs;
|
|
||||||
int width, height;
|
|
||||||
|
|
||||||
resources = drmModeGetResources(manager_kms->fd);
|
|
||||||
modes = g_hash_table_new (drm_mode_hash, drm_mode_equal);
|
|
||||||
|
|
||||||
manager->max_screen_width = resources->max_width;
|
|
||||||
manager->max_screen_height = resources->max_height;
|
|
||||||
|
|
||||||
manager->power_save_mode = META_POWER_SAVE_ON;
|
|
||||||
|
|
||||||
manager_kms->n_connectors = resources->count_connectors;
|
|
||||||
manager_kms->connectors = g_new (drmModeConnector *, manager_kms->n_connectors);
|
|
||||||
for (i = 0; i < manager_kms->n_connectors; i++)
|
|
||||||
{
|
|
||||||
drmModeConnector *connector;
|
|
||||||
|
|
||||||
connector = drmModeGetConnector (manager_kms->fd, resources->connectors[i]);
|
|
||||||
manager_kms->connectors[i] = connector;
|
|
||||||
|
|
||||||
if (connector->connection == DRM_MODE_CONNECTED)
|
|
||||||
{
|
|
||||||
/* Collect all modes for this connector */
|
|
||||||
for (j = 0; j < (unsigned)connector->count_modes; j++)
|
|
||||||
g_hash_table_add (modes, &connector->modes[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
manager_kms->n_encoders = resources->count_encoders;
|
|
||||||
manager_kms->encoders = g_new (drmModeEncoder *, manager_kms->n_encoders);
|
|
||||||
for (i = 0; i < manager_kms->n_encoders; i++)
|
|
||||||
{
|
|
||||||
manager_kms->encoders[i] = drmModeGetEncoder (manager_kms->fd,
|
|
||||||
resources->encoders[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
manager->n_modes = g_hash_table_size (modes);
|
|
||||||
manager->modes = g_new0 (MetaMonitorMode, manager->n_modes);
|
|
||||||
g_hash_table_iter_init (&iter, modes);
|
|
||||||
i = 0;
|
|
||||||
while (g_hash_table_iter_next (&iter, NULL, (gpointer)&mode))
|
|
||||||
{
|
|
||||||
MetaMonitorMode *meta_mode;
|
|
||||||
|
|
||||||
meta_mode = &manager->modes[i];
|
|
||||||
|
|
||||||
meta_mode->mode_id = i;
|
|
||||||
meta_mode->name = g_strndup (mode->name, DRM_DISPLAY_MODE_LEN);
|
|
||||||
meta_mode->width = mode->hdisplay;
|
|
||||||
meta_mode->height = mode->vdisplay;
|
|
||||||
meta_mode->refresh_rate = (1000 * mode->clock /
|
|
||||||
((float)mode->htotal * mode->vtotal));
|
|
||||||
|
|
||||||
meta_mode->driver_private = g_slice_dup (drmModeModeInfo, mode);
|
|
||||||
meta_mode->driver_notify = (GDestroyNotify)meta_monitor_mode_destroy_notify;
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
g_hash_table_destroy (modes);
|
|
||||||
|
|
||||||
manager->n_crtcs = resources->count_crtcs;
|
|
||||||
manager->crtcs = g_new0 (MetaCRTC, manager->n_crtcs);
|
|
||||||
width = 0; height = 0;
|
|
||||||
for (i = 0; i < (unsigned)resources->count_crtcs; i++)
|
|
||||||
{
|
|
||||||
drmModeCrtc *crtc;
|
|
||||||
MetaCRTC *meta_crtc;
|
|
||||||
|
|
||||||
crtc = drmModeGetCrtc (manager_kms->fd, resources->crtcs[i]);
|
|
||||||
|
|
||||||
meta_crtc = &manager->crtcs[i];
|
|
||||||
|
|
||||||
meta_crtc->crtc_id = crtc->crtc_id;
|
|
||||||
meta_crtc->rect.x = crtc->x;
|
|
||||||
meta_crtc->rect.y = crtc->y;
|
|
||||||
meta_crtc->rect.width = crtc->width;
|
|
||||||
meta_crtc->rect.height = crtc->height;
|
|
||||||
meta_crtc->dirty = FALSE;
|
|
||||||
|
|
||||||
/* FIXME: we can handle some transforms, with a combination of
|
|
||||||
scaling and fitting, but it is very driver dependent */
|
|
||||||
meta_crtc->transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
|
||||||
meta_crtc->all_transforms = 1 << WL_OUTPUT_TRANSFORM_NORMAL;
|
|
||||||
|
|
||||||
if (crtc->mode_valid)
|
|
||||||
{
|
|
||||||
for (j = 0; j < manager->n_modes; j++)
|
|
||||||
{
|
|
||||||
if (drm_mode_equal (&crtc->mode, manager->modes[j].driver_private))
|
|
||||||
{
|
|
||||||
meta_crtc->current_mode = &manager->modes[j];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
width = MAX (width, meta_crtc->rect.x + meta_crtc->rect.width);
|
|
||||||
height = MAX (height, meta_crtc->rect.y + meta_crtc->rect.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
drmModeFreeCrtc (crtc);
|
|
||||||
}
|
|
||||||
|
|
||||||
manager->screen_width = width;
|
|
||||||
manager->screen_height = height;
|
|
||||||
|
|
||||||
manager->outputs = g_new0 (MetaOutput, manager_kms->n_connectors);
|
|
||||||
n_actual_outputs = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < manager_kms->n_connectors; i++)
|
|
||||||
{
|
|
||||||
MetaOutput *meta_output;
|
|
||||||
MetaOutputKms *output_kms;
|
|
||||||
drmModeConnector *connector;
|
|
||||||
GArray *crtcs;
|
|
||||||
unsigned int crtc_mask;
|
|
||||||
|
|
||||||
connector = manager_kms->connectors[i];
|
|
||||||
meta_output = &manager->outputs[n_actual_outputs];
|
|
||||||
|
|
||||||
if (connector->connection == DRM_MODE_CONNECTED)
|
|
||||||
{
|
|
||||||
meta_output->output_id = connector->connector_id;
|
|
||||||
meta_output->name = make_output_name (connector);
|
|
||||||
meta_output->vendor = g_strdup ("unknown");
|
|
||||||
meta_output->product = g_strdup ("unknown");
|
|
||||||
meta_output->serial = g_strdup ("");
|
|
||||||
meta_output->width_mm = connector->mmWidth;
|
|
||||||
meta_output->height_mm = connector->mmHeight;
|
|
||||||
|
|
||||||
if (connector->subpixel == DRM_MODE_SUBPIXEL_UNKNOWN)
|
|
||||||
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
|
|
||||||
else if (connector->subpixel == DRM_MODE_SUBPIXEL_NONE)
|
|
||||||
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_NONE;
|
|
||||||
else
|
|
||||||
meta_output->subpixel_order = connector->subpixel;
|
|
||||||
|
|
||||||
meta_output->n_modes = connector->count_modes;
|
|
||||||
meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
|
|
||||||
for (j = 0; j < meta_output->n_modes; j++)
|
|
||||||
{
|
|
||||||
for (k = 0; k < manager->n_modes; k++)
|
|
||||||
{
|
|
||||||
if (drm_mode_equal (&connector->modes[j], manager->modes[k].driver_private))
|
|
||||||
{
|
|
||||||
meta_output->modes[j] = &manager->modes[k];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
meta_output->preferred_mode = meta_output->modes[0];
|
|
||||||
|
|
||||||
meta_output->driver_private = output_kms = g_slice_new0 (MetaOutputKms);
|
|
||||||
meta_output->driver_notify = (GDestroyNotify)meta_output_destroy_notify;
|
|
||||||
|
|
||||||
output_kms->connector = connector;
|
|
||||||
output_kms->n_encoders = connector->count_encoders;
|
|
||||||
output_kms->encoders = g_new0 (drmModeEncoderPtr, output_kms->n_encoders);
|
|
||||||
|
|
||||||
crtc_mask = 0x7F;
|
|
||||||
for (j = 0; j < output_kms->n_encoders; j++)
|
|
||||||
{
|
|
||||||
output_kms->encoders[j] = drmModeGetEncoder (manager_kms->fd, connector->encoders[j]);
|
|
||||||
|
|
||||||
crtc_mask &= output_kms->encoders[j]->possible_crtcs;
|
|
||||||
|
|
||||||
if (output_kms->encoders[j]->encoder_id == connector->encoder_id)
|
|
||||||
output_kms->current_encoder = output_kms->encoders[j];
|
|
||||||
}
|
|
||||||
|
|
||||||
crtcs = g_array_new (FALSE, FALSE, sizeof (MetaCRTC*));
|
|
||||||
|
|
||||||
for (j = 0; j < manager->n_crtcs; j++)
|
|
||||||
{
|
|
||||||
if (crtc_mask & (1 << j))
|
|
||||||
{
|
|
||||||
MetaCRTC *crtc = &manager->crtcs[j];
|
|
||||||
g_array_append_val (crtcs, crtc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
meta_output->n_possible_crtcs = crtcs->len;
|
|
||||||
meta_output->possible_crtcs = (void*)g_array_free (crtcs, FALSE);
|
|
||||||
|
|
||||||
if (output_kms->current_encoder && output_kms->current_encoder->crtc_id != 0)
|
|
||||||
{
|
|
||||||
for (j = 0; j < manager->n_crtcs; j++)
|
|
||||||
{
|
|
||||||
if (manager->crtcs[j].crtc_id == output_kms->current_encoder->crtc_id)
|
|
||||||
{
|
|
||||||
meta_output->crtc = &manager->crtcs[j];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
meta_output->crtc = NULL;
|
|
||||||
|
|
||||||
meta_output->is_primary = FALSE;
|
|
||||||
meta_output->is_presentation = FALSE;
|
|
||||||
|
|
||||||
for (j = 0; j < (unsigned)connector->count_props; j++)
|
|
||||||
{
|
|
||||||
drmModePropertyPtr prop;
|
|
||||||
|
|
||||||
prop = drmModeGetProperty(manager_kms->fd, connector->props[j]);
|
|
||||||
|
|
||||||
if (prop)
|
|
||||||
{
|
|
||||||
if ((prop->flags & DRM_MODE_PROP_ENUM) &&
|
|
||||||
strcmp(prop->name, "DPMS") == 0)
|
|
||||||
{
|
|
||||||
output_kms->dpms_prop_id = prop->prop_id;
|
|
||||||
drmModeFreeProperty(prop);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
drmModeFreeProperty(prop);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: backlight is a very driver specific thing unfortunately,
|
|
||||||
every DDX does its own thing, and the dumb KMS API does not include it.
|
|
||||||
|
|
||||||
For example, xf86-video-intel has a list of paths to probe in /sys/class/backlight
|
|
||||||
(one for each major HW maker, and then some).
|
|
||||||
We can't do the same because we're not root.
|
|
||||||
It might be best to leave backlight out of the story and rely on the setuid
|
|
||||||
helper in gnome-settings-daemon.
|
|
||||||
*/
|
|
||||||
meta_output->backlight_min = 0;
|
|
||||||
meta_output->backlight_max = 0;
|
|
||||||
meta_output->backlight = -1;
|
|
||||||
|
|
||||||
n_actual_outputs++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
manager->n_outputs = n_actual_outputs;
|
|
||||||
manager->outputs = g_renew (MetaOutput, manager->outputs, manager->n_outputs);
|
|
||||||
|
|
||||||
/* Sort the outputs for easier handling in MetaMonitorConfig */
|
|
||||||
qsort (manager->outputs, manager->n_outputs, sizeof (MetaOutput), compare_outputs);
|
|
||||||
|
|
||||||
/* Now fix the clones.
|
|
||||||
Code mostly inspired by xf86-video-modesetting. */
|
|
||||||
|
|
||||||
/* XXX: intel hardware doesn't usually have clones, but we only have intel
|
|
||||||
cards, so this code was never tested! */
|
|
||||||
for (i = 0; i < manager->n_outputs; i++)
|
|
||||||
{
|
|
||||||
MetaOutput *meta_output;
|
|
||||||
MetaOutputKms *output_kms;
|
|
||||||
|
|
||||||
meta_output = &manager->outputs[i];
|
|
||||||
output_kms = meta_output->driver_private;
|
|
||||||
|
|
||||||
output_kms->enc_clone_mask = 0xff;
|
|
||||||
output_kms->encoder_mask = 0;
|
|
||||||
|
|
||||||
for (j = 0; j < output_kms->n_encoders; j++)
|
|
||||||
{
|
|
||||||
for (k = 0; k < manager_kms->n_encoders; k++)
|
|
||||||
{
|
|
||||||
if (output_kms->encoders[j]->encoder_id == manager_kms->encoders[k]->encoder_id)
|
|
||||||
{
|
|
||||||
output_kms->encoder_mask |= (1 << k);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
output_kms->enc_clone_mask &= output_kms->encoders[j]->possible_clones;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < manager->n_outputs; i++)
|
|
||||||
{
|
|
||||||
MetaOutput *meta_output;
|
|
||||||
MetaOutputKms *output_kms;
|
|
||||||
|
|
||||||
meta_output = &manager->outputs[i];
|
|
||||||
output_kms = meta_output->driver_private;
|
|
||||||
|
|
||||||
if (output_kms->enc_clone_mask == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (j = 0; j < manager->n_outputs; j++)
|
|
||||||
{
|
|
||||||
MetaOutput *meta_clone;
|
|
||||||
MetaOutputKms *clone_kms;
|
|
||||||
|
|
||||||
meta_clone = &manager->outputs[i];
|
|
||||||
clone_kms = meta_clone->driver_private;
|
|
||||||
|
|
||||||
if (meta_clone == meta_output)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (clone_kms->encoder_mask == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (clone_kms->encoder_mask == output_kms->enc_clone_mask)
|
|
||||||
{
|
|
||||||
meta_output->n_possible_clones++;
|
|
||||||
meta_output->possible_clones = g_renew (MetaOutput *,
|
|
||||||
meta_output->possible_clones,
|
|
||||||
meta_output->n_possible_clones);
|
|
||||||
meta_output->possible_clones[meta_output->n_possible_clones - 1] = meta_clone;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
drmModeFreeResources (resources);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
|
|
||||||
MetaPowerSave mode)
|
|
||||||
{
|
|
||||||
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
|
|
||||||
uint64_t state;
|
|
||||||
unsigned i;
|
|
||||||
|
|
||||||
switch (mode) {
|
|
||||||
case META_POWER_SAVE_ON:
|
|
||||||
state = DRM_MODE_DPMS_ON;
|
|
||||||
break;
|
|
||||||
case META_POWER_SAVE_STANDBY:
|
|
||||||
state = DRM_MODE_DPMS_STANDBY;
|
|
||||||
break;
|
|
||||||
case META_POWER_SAVE_SUSPEND:
|
|
||||||
state = DRM_MODE_DPMS_SUSPEND;
|
|
||||||
break;
|
|
||||||
case META_POWER_SAVE_OFF:
|
|
||||||
state = DRM_MODE_DPMS_SUSPEND;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < manager->n_outputs; i++)
|
|
||||||
{
|
|
||||||
MetaOutput *meta_output;
|
|
||||||
MetaOutputKms *output_kms;
|
|
||||||
|
|
||||||
meta_output = &manager->outputs[i];
|
|
||||||
output_kms = meta_output->driver_private;
|
|
||||||
|
|
||||||
if (output_kms->dpms_prop_id)
|
|
||||||
{
|
|
||||||
int ok = drmModeConnectorSetProperty(manager_kms->fd, meta_output->output_id,
|
|
||||||
output_kms->dpms_prop_id, state);
|
|
||||||
|
|
||||||
if (ok < 0)
|
|
||||||
meta_warning ("Failed to set power save mode for output %s: %s\n",
|
|
||||||
meta_output->name, strerror (errno));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
crtc_free (CoglKmsCrtc *crtc)
|
|
||||||
{
|
|
||||||
g_free (crtc->connectors);
|
|
||||||
g_slice_free (CoglKmsCrtc, crtc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
|
|
||||||
MetaCRTCInfo **crtcs,
|
|
||||||
unsigned int n_crtcs,
|
|
||||||
MetaOutputInfo **outputs,
|
|
||||||
unsigned int n_outputs)
|
|
||||||
{
|
|
||||||
ClutterBackend *backend;
|
|
||||||
CoglContext *cogl_context;
|
|
||||||
CoglDisplay *cogl_display;
|
|
||||||
unsigned i;
|
|
||||||
GList *cogl_crtcs;
|
|
||||||
int width, height;
|
|
||||||
gboolean ok;
|
|
||||||
GError *error;
|
|
||||||
|
|
||||||
cogl_crtcs = NULL;
|
|
||||||
width = 0; height = 0;
|
|
||||||
for (i = 0; i < n_crtcs; i++)
|
|
||||||
{
|
|
||||||
MetaCRTCInfo *crtc_info = crtcs[i];
|
|
||||||
MetaCRTC *crtc = crtc_info->crtc;
|
|
||||||
CoglKmsCrtc *cogl_crtc;
|
|
||||||
|
|
||||||
crtc->dirty = TRUE;
|
|
||||||
|
|
||||||
cogl_crtc = g_slice_new0 (CoglKmsCrtc);
|
|
||||||
cogl_crtcs = g_list_prepend (cogl_crtcs, cogl_crtc);
|
|
||||||
|
|
||||||
if (crtc_info->mode == NULL)
|
|
||||||
{
|
|
||||||
cogl_crtc->id = crtc->crtc_id;
|
|
||||||
cogl_crtc->x = 0;
|
|
||||||
cogl_crtc->y = 0;
|
|
||||||
cogl_crtc->count = 0;
|
|
||||||
memset (&cogl_crtc->mode, 0, sizeof (drmModeModeInfo));
|
|
||||||
cogl_crtc->connectors = NULL;
|
|
||||||
cogl_crtc->count = 0;
|
|
||||||
|
|
||||||
crtc->rect.x = 0;
|
|
||||||
crtc->rect.y = 0;
|
|
||||||
crtc->rect.width = 0;
|
|
||||||
crtc->rect.height = 0;
|
|
||||||
crtc->current_mode = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MetaMonitorMode *mode;
|
|
||||||
uint32_t *outputs;
|
|
||||||
unsigned int j, n_outputs;
|
|
||||||
|
|
||||||
mode = crtc_info->mode;
|
|
||||||
|
|
||||||
cogl_crtc->id = crtc->crtc_id;
|
|
||||||
cogl_crtc->x = crtc_info->x;
|
|
||||||
cogl_crtc->y = crtc_info->y;
|
|
||||||
cogl_crtc->count = n_outputs = crtc_info->outputs->len;
|
|
||||||
cogl_crtc->connectors = outputs = g_new (uint32_t, n_outputs);
|
|
||||||
|
|
||||||
for (j = 0; j < n_outputs; j++)
|
|
||||||
{
|
|
||||||
MetaOutput *output = ((MetaOutput**)crtc_info->outputs->pdata)[j];
|
|
||||||
|
|
||||||
outputs[j] = output->output_id;
|
|
||||||
|
|
||||||
output->dirty = TRUE;
|
|
||||||
output->crtc = crtc;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy (&cogl_crtc->mode, crtc_info->mode->driver_private,
|
|
||||||
sizeof (drmModeModeInfo));
|
|
||||||
|
|
||||||
width = MAX (width, crtc_info->x + crtc_info->mode->width);
|
|
||||||
height = MAX (height, crtc_info->y + crtc_info->mode->height);
|
|
||||||
|
|
||||||
crtc->rect.x = crtc_info->x;
|
|
||||||
crtc->rect.y = crtc_info->y;
|
|
||||||
crtc->rect.width = mode->width;
|
|
||||||
crtc->rect.height = mode->height;
|
|
||||||
crtc->current_mode = mode;
|
|
||||||
crtc->transform = crtc_info->transform;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Disable CRTCs not mentioned in the list */
|
|
||||||
for (i = 0; i < manager->n_crtcs; i++)
|
|
||||||
{
|
|
||||||
MetaCRTC *crtc = &manager->crtcs[i];
|
|
||||||
CoglKmsCrtc *cogl_crtc;
|
|
||||||
|
|
||||||
crtc->logical_monitor = NULL;
|
|
||||||
|
|
||||||
if (crtc->dirty)
|
|
||||||
{
|
|
||||||
crtc->dirty = FALSE;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
cogl_crtc = g_slice_new0 (CoglKmsCrtc);
|
|
||||||
cogl_crtcs = g_list_prepend (cogl_crtcs, cogl_crtc);
|
|
||||||
|
|
||||||
cogl_crtc->id = crtc->crtc_id;
|
|
||||||
cogl_crtc->x = 0;
|
|
||||||
cogl_crtc->y = 0;
|
|
||||||
cogl_crtc->count = 0;
|
|
||||||
memset (&cogl_crtc->mode, 0, sizeof (drmModeModeInfo));
|
|
||||||
cogl_crtc->connectors = NULL;
|
|
||||||
cogl_crtc->count = 0;
|
|
||||||
|
|
||||||
crtc->rect.x = 0;
|
|
||||||
crtc->rect.y = 0;
|
|
||||||
crtc->rect.width = 0;
|
|
||||||
crtc->rect.height = 0;
|
|
||||||
crtc->current_mode = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
backend = clutter_get_default_backend ();
|
|
||||||
cogl_context = clutter_backend_get_cogl_context (backend);
|
|
||||||
cogl_display = cogl_context_get_display (cogl_context);
|
|
||||||
|
|
||||||
error = NULL;
|
|
||||||
ok = cogl_kms_display_set_layout (cogl_display, width, height, cogl_crtcs, &error);
|
|
||||||
g_list_free_full (cogl_crtcs, (GDestroyNotify) crtc_free);
|
|
||||||
|
|
||||||
if (!ok)
|
|
||||||
{
|
|
||||||
meta_warning ("Applying display configuration failed: %s\n", error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < n_outputs; i++)
|
|
||||||
{
|
|
||||||
MetaOutputInfo *output_info = outputs[i];
|
|
||||||
MetaOutput *output = output_info->output;
|
|
||||||
|
|
||||||
output->is_primary = output_info->is_primary;
|
|
||||||
output->is_presentation = output_info->is_presentation;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Disable outputs not mentioned in the list */
|
|
||||||
for (i = 0; i < manager->n_outputs; i++)
|
|
||||||
{
|
|
||||||
MetaOutput *output = &manager->outputs[i];
|
|
||||||
|
|
||||||
if (output->dirty)
|
|
||||||
{
|
|
||||||
output->dirty = FALSE;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
output->crtc = NULL;
|
|
||||||
output->is_primary = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
manager->screen_width = width;
|
|
||||||
manager->screen_height = height;
|
|
||||||
|
|
||||||
meta_monitor_manager_rebuild_derived (manager);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_monitor_manager_kms_get_crtc_gamma (MetaMonitorManager *manager,
|
|
||||||
MetaCRTC *crtc,
|
|
||||||
gsize *size,
|
|
||||||
unsigned short **red,
|
|
||||||
unsigned short **green,
|
|
||||||
unsigned short **blue)
|
|
||||||
{
|
|
||||||
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
|
|
||||||
drmModeCrtc *kms_crtc;
|
|
||||||
|
|
||||||
kms_crtc = drmModeGetCrtc (manager_kms->fd, crtc->crtc_id);
|
|
||||||
|
|
||||||
*size = kms_crtc->gamma_size;
|
|
||||||
*red = g_new (unsigned short, *size);
|
|
||||||
*green = g_new (unsigned short, *size);
|
|
||||||
*blue = g_new (unsigned short, *size);
|
|
||||||
|
|
||||||
drmModeCrtcGetGamma (manager_kms->fd, crtc->crtc_id, *size, *red, *green, *blue);
|
|
||||||
|
|
||||||
drmModeFreeCrtc (kms_crtc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_monitor_manager_kms_set_crtc_gamma (MetaMonitorManager *manager,
|
|
||||||
MetaCRTC *crtc,
|
|
||||||
gsize size,
|
|
||||||
unsigned short *red,
|
|
||||||
unsigned short *green,
|
|
||||||
unsigned short *blue)
|
|
||||||
{
|
|
||||||
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
|
|
||||||
|
|
||||||
drmModeCrtcSetGamma (manager_kms->fd, crtc->crtc_id, size, red, green, blue);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_monitor_manager_kms_init (MetaMonitorManagerKms *manager_kms)
|
|
||||||
{
|
|
||||||
ClutterBackend *backend;
|
|
||||||
CoglContext *cogl_context;
|
|
||||||
CoglDisplay *cogl_display;
|
|
||||||
CoglRenderer *cogl_renderer;
|
|
||||||
|
|
||||||
backend = clutter_get_default_backend ();
|
|
||||||
cogl_context = clutter_backend_get_cogl_context (backend);
|
|
||||||
cogl_display = cogl_context_get_display (cogl_context);
|
|
||||||
cogl_renderer = cogl_display_get_renderer (cogl_display);
|
|
||||||
|
|
||||||
manager_kms->fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_monitor_manager_kms_finalize (GObject *object)
|
|
||||||
{
|
|
||||||
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (object);
|
|
||||||
unsigned i;
|
|
||||||
|
|
||||||
for (i = 0; i < manager_kms->n_encoders; i++)
|
|
||||||
drmModeFreeEncoder (manager_kms->encoders[i]);
|
|
||||||
for (i = 0; i < manager_kms->n_connectors; i++)
|
|
||||||
drmModeFreeConnector (manager_kms->connectors[i]);
|
|
||||||
|
|
||||||
g_free (manager_kms->encoders);
|
|
||||||
g_free (manager_kms->connectors);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (meta_monitor_manager_kms_parent_class)->finalize (object);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_monitor_manager_kms_class_init (MetaMonitorManagerKmsClass *klass)
|
|
||||||
{
|
|
||||||
MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass);
|
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
||||||
|
|
||||||
object_class->finalize = meta_monitor_manager_kms_finalize;
|
|
||||||
|
|
||||||
manager_class->read_current = meta_monitor_manager_kms_read_current;
|
|
||||||
manager_class->apply_configuration = meta_monitor_manager_kms_apply_configuration;
|
|
||||||
manager_class->set_power_save_mode = meta_monitor_manager_kms_set_power_save_mode;
|
|
||||||
manager_class->get_crtc_gamma = meta_monitor_manager_kms_get_crtc_gamma;
|
|
||||||
manager_class->set_crtc_gamma = meta_monitor_manager_kms_set_crtc_gamma;
|
|
||||||
}
|
|
||||||
|
|
@@ -38,6 +38,7 @@
|
|||||||
#define META_MONITOR_PRIVATE_H
|
#define META_MONITOR_PRIVATE_H
|
||||||
|
|
||||||
#include <cogl/cogl.h>
|
#include <cogl/cogl.h>
|
||||||
|
#include <libgnome-desktop/gnome-pnp-ids.h>
|
||||||
|
|
||||||
#include "display-private.h"
|
#include "display-private.h"
|
||||||
#include <meta/screen.h>
|
#include <meta/screen.h>
|
||||||
@@ -104,7 +105,7 @@ struct _MetaOutput
|
|||||||
int backlight_max;
|
int backlight_max;
|
||||||
|
|
||||||
/* Used when changing configuration */
|
/* Used when changing configuration */
|
||||||
gboolean dirty;
|
gboolean is_dirty;
|
||||||
|
|
||||||
/* The low-level bits used to build the high-level info
|
/* The low-level bits used to build the high-level info
|
||||||
in MetaMonitorInfo
|
in MetaMonitorInfo
|
||||||
@@ -115,9 +116,6 @@ struct _MetaOutput
|
|||||||
*/
|
*/
|
||||||
gboolean is_primary;
|
gboolean is_primary;
|
||||||
gboolean is_presentation;
|
gboolean is_presentation;
|
||||||
|
|
||||||
gpointer driver_private;
|
|
||||||
GDestroyNotify driver_notify;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _MetaCRTC
|
struct _MetaCRTC
|
||||||
@@ -134,21 +132,17 @@ struct _MetaCRTC
|
|||||||
MetaMonitorInfo *logical_monitor;
|
MetaMonitorInfo *logical_monitor;
|
||||||
|
|
||||||
/* Used when changing configuration */
|
/* Used when changing configuration */
|
||||||
gboolean dirty;
|
gboolean is_dirty;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _MetaMonitorMode
|
struct _MetaMonitorMode
|
||||||
{
|
{
|
||||||
/* The low-level ID of this mode, used to apply back configuration */
|
/* The low-level ID of this mode, used to apply back configuration */
|
||||||
glong mode_id;
|
glong mode_id;
|
||||||
char *name;
|
|
||||||
|
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
float refresh_rate;
|
float refresh_rate;
|
||||||
|
|
||||||
gpointer driver_private;
|
|
||||||
GDestroyNotify driver_notify;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -171,8 +165,7 @@ struct _MetaMonitorInfo
|
|||||||
gboolean in_fullscreen;
|
gboolean in_fullscreen;
|
||||||
|
|
||||||
/* The primary or first output for this monitor, 0 if we can't figure out.
|
/* The primary or first output for this monitor, 0 if we can't figure out.
|
||||||
This is a XID when using XRandR, otherwise a KMS id (not implemented).
|
It can be matched to an output_id of a MetaOutput.
|
||||||
In any case, it can be matched to an output_id of a MetaOutput.
|
|
||||||
|
|
||||||
This is used as an opaque token on reconfiguration when switching from
|
This is used as an opaque token on reconfiguration when switching from
|
||||||
clone to extened, to decide on what output the windows should go next
|
clone to extened, to decide on what output the windows should go next
|
||||||
@@ -258,6 +251,8 @@ struct _MetaMonitorManager
|
|||||||
|
|
||||||
int persistent_timeout_id;
|
int persistent_timeout_id;
|
||||||
MetaMonitorConfig *config;
|
MetaMonitorConfig *config;
|
||||||
|
|
||||||
|
GnomePnpIds *pnp_ids;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _MetaMonitorManagerClass
|
struct _MetaMonitorManagerClass
|
||||||
@@ -306,15 +301,6 @@ GType meta_monitor_manager_get_type (void);
|
|||||||
void meta_monitor_manager_initialize (void);
|
void meta_monitor_manager_initialize (void);
|
||||||
MetaMonitorManager *meta_monitor_manager_get (void);
|
MetaMonitorManager *meta_monitor_manager_get (void);
|
||||||
|
|
||||||
void meta_monitor_manager_init_dbus (MetaMonitorManager *manager,
|
|
||||||
GAsyncReadyCallback callback,
|
|
||||||
gpointer user_data);
|
|
||||||
gboolean meta_monitor_manager_init_dbus_finish (MetaMonitorManager *manager,
|
|
||||||
GAsyncResult *result,
|
|
||||||
GError **error);
|
|
||||||
|
|
||||||
void meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager);
|
|
||||||
|
|
||||||
MetaMonitorInfo *meta_monitor_manager_get_monitor_infos (MetaMonitorManager *manager,
|
MetaMonitorInfo *meta_monitor_manager_get_monitor_infos (MetaMonitorManager *manager,
|
||||||
unsigned int *n_infos);
|
unsigned int *n_infos);
|
||||||
|
|
||||||
@@ -363,18 +349,6 @@ typedef struct _MetaMonitorManagerXrandr MetaMonitorManagerXrandr;
|
|||||||
|
|
||||||
GType meta_monitor_manager_xrandr_get_type (void);
|
GType meta_monitor_manager_xrandr_get_type (void);
|
||||||
|
|
||||||
#define META_TYPE_MONITOR_MANAGER_KMS (meta_monitor_manager_kms_get_type ())
|
|
||||||
#define META_MONITOR_MANAGER_KMS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKms))
|
|
||||||
#define META_MONITOR_MANAGER_KMS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKmsClass))
|
|
||||||
#define META_IS_MONITOR_MANAGER_KMS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_MANAGER_KMS))
|
|
||||||
#define META_IS_MONITOR_MANAGER_KMS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MONITOR_MANAGER_KMS))
|
|
||||||
#define META_MONITOR_MANAGER_KMS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKmsClass))
|
|
||||||
|
|
||||||
typedef struct _MetaMonitorManagerKmsClass MetaMonitorManagerKmsClass;
|
|
||||||
typedef struct _MetaMonitorManagerKms MetaMonitorManagerKms;
|
|
||||||
|
|
||||||
GType meta_monitor_manager_kms_get_type (void);
|
|
||||||
|
|
||||||
#define META_TYPE_MONITOR_CONFIG (meta_monitor_config_get_type ())
|
#define META_TYPE_MONITOR_CONFIG (meta_monitor_config_get_type ())
|
||||||
#define META_MONITOR_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_CONFIG, MetaMonitorConfig))
|
#define META_MONITOR_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_CONFIG, MetaMonitorConfig))
|
||||||
#define META_MONITOR_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_CONFIG, MetaMonitorConfigClass))
|
#define META_MONITOR_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_CONFIG, MetaMonitorConfigClass))
|
||||||
@@ -405,4 +379,12 @@ void meta_monitor_config_restore_previous (MetaMonitorConfig *con
|
|||||||
void meta_crtc_info_free (MetaCRTCInfo *info);
|
void meta_crtc_info_free (MetaCRTCInfo *info);
|
||||||
void meta_output_info_free (MetaOutputInfo *info);
|
void meta_output_info_free (MetaOutputInfo *info);
|
||||||
|
|
||||||
|
/* Returns true if transform causes width and height to be inverted
|
||||||
|
This is true for the odd transforms in the enum */
|
||||||
|
static inline gboolean
|
||||||
|
meta_monitor_transform_is_rotated (enum wl_output_transform transform)
|
||||||
|
{
|
||||||
|
return (transform % 2);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
|
|
||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
@@ -39,8 +40,15 @@
|
|||||||
#include <meta/errors.h>
|
#include <meta/errors.h>
|
||||||
#include "monitor-private.h"
|
#include "monitor-private.h"
|
||||||
|
|
||||||
|
#include "edid.h"
|
||||||
|
|
||||||
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
|
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
|
||||||
|
|
||||||
|
/* Look for DPI_FALLBACK in:
|
||||||
|
* http://git.gnome.org/browse/gnome-settings-daemon/tree/plugins/xsettings/gsd-xsettings-manager.c
|
||||||
|
* for the reasoning */
|
||||||
|
#define DPI_FALLBACK 96.0
|
||||||
|
|
||||||
struct _MetaMonitorManagerXrandr
|
struct _MetaMonitorManagerXrandr
|
||||||
{
|
{
|
||||||
MetaMonitorManager parent_instance;
|
MetaMonitorManager parent_instance;
|
||||||
@@ -162,8 +170,8 @@ static int
|
|||||||
normalize_backlight (MetaOutput *output,
|
normalize_backlight (MetaOutput *output,
|
||||||
int hw_value)
|
int hw_value)
|
||||||
{
|
{
|
||||||
return round((double)(hw_value - output->backlight_min) /
|
return round ((double)(hw_value - output->backlight_min) /
|
||||||
(output->backlight_max - output->backlight_min) * 100.0);
|
(output->backlight_max - output->backlight_min) * 100.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -235,6 +243,74 @@ compare_outputs (const void *one,
|
|||||||
return strcmp (o_one->name, o_two->name);
|
return strcmp (o_one->name, o_two->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static guint8 *
|
||||||
|
get_edid_property (Display *dpy,
|
||||||
|
RROutput output,
|
||||||
|
Atom atom,
|
||||||
|
gsize *len)
|
||||||
|
{
|
||||||
|
unsigned char *prop;
|
||||||
|
int actual_format;
|
||||||
|
unsigned long nitems, bytes_after;
|
||||||
|
Atom actual_type;
|
||||||
|
guint8 *result;
|
||||||
|
|
||||||
|
XRRGetOutputProperty (dpy, output, atom,
|
||||||
|
0, 100, False, False,
|
||||||
|
AnyPropertyType,
|
||||||
|
&actual_type, &actual_format,
|
||||||
|
&nitems, &bytes_after, &prop);
|
||||||
|
|
||||||
|
if (actual_type == XA_INTEGER && actual_format == 8)
|
||||||
|
{
|
||||||
|
result = g_memdup (prop, nitems);
|
||||||
|
if (len)
|
||||||
|
*len = nitems;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
XFree (prop);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GBytes *
|
||||||
|
read_output_edid (MetaMonitorManagerXrandr *manager_xrandr,
|
||||||
|
XID output_id)
|
||||||
|
{
|
||||||
|
Atom edid_atom;
|
||||||
|
guint8 *result;
|
||||||
|
gsize len;
|
||||||
|
|
||||||
|
edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID", FALSE);
|
||||||
|
result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len);
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID_DATA", FALSE);
|
||||||
|
result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
edid_atom = XInternAtom (manager_xrandr->xdisplay, "XFree86_DDC_EDID1_RAWDATA", FALSE);
|
||||||
|
result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
if (len > 0 && len % 128 == 0)
|
||||||
|
return g_bytes_new_take (result, len);
|
||||||
|
else
|
||||||
|
g_free (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
||||||
{
|
{
|
||||||
@@ -261,18 +337,23 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
|||||||
dpms_enabled)
|
dpms_enabled)
|
||||||
{
|
{
|
||||||
switch (dpms_state)
|
switch (dpms_state)
|
||||||
{
|
{
|
||||||
case DPMSModeOn:
|
case DPMSModeOn:
|
||||||
manager->power_save_mode = META_POWER_SAVE_ON;
|
manager->power_save_mode = META_POWER_SAVE_ON;
|
||||||
case DPMSModeStandby:
|
break;
|
||||||
manager->power_save_mode = META_POWER_SAVE_STANDBY;
|
case DPMSModeStandby:
|
||||||
case DPMSModeSuspend:
|
manager->power_save_mode = META_POWER_SAVE_STANDBY;
|
||||||
manager->power_save_mode = META_POWER_SAVE_SUSPEND;
|
break;
|
||||||
case DPMSModeOff:
|
case DPMSModeSuspend:
|
||||||
manager->power_save_mode = META_POWER_SAVE_OFF;
|
manager->power_save_mode = META_POWER_SAVE_SUSPEND;
|
||||||
default:
|
break;
|
||||||
manager->power_save_mode = META_POWER_SAVE_UNKNOWN;
|
case DPMSModeOff:
|
||||||
}
|
manager->power_save_mode = META_POWER_SAVE_OFF;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
manager->power_save_mode = META_POWER_SAVE_UNKNOWN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -333,7 +414,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
|||||||
meta_crtc->rect.y = crtc->y;
|
meta_crtc->rect.y = crtc->y;
|
||||||
meta_crtc->rect.width = crtc->width;
|
meta_crtc->rect.width = crtc->width;
|
||||||
meta_crtc->rect.height = crtc->height;
|
meta_crtc->rect.height = crtc->height;
|
||||||
meta_crtc->dirty = FALSE;
|
meta_crtc->is_dirty = FALSE;
|
||||||
meta_crtc->transform = wl_transform_from_xrandr (crtc->rotation);
|
meta_crtc->transform = wl_transform_from_xrandr (crtc->rotation);
|
||||||
meta_crtc->all_transforms = wl_transform_from_xrandr_all (crtc->rotations);
|
meta_crtc->all_transforms = wl_transform_from_xrandr_all (crtc->rotations);
|
||||||
|
|
||||||
@@ -364,11 +445,42 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
|||||||
|
|
||||||
if (output->connection != RR_Disconnected)
|
if (output->connection != RR_Disconnected)
|
||||||
{
|
{
|
||||||
|
GBytes *edid;
|
||||||
|
MonitorInfo *parsed_edid;
|
||||||
|
|
||||||
meta_output->output_id = resources->outputs[i];
|
meta_output->output_id = resources->outputs[i];
|
||||||
meta_output->name = g_strdup (output->name);
|
meta_output->name = g_strdup (output->name);
|
||||||
meta_output->vendor = g_strdup ("unknown");
|
|
||||||
meta_output->product = g_strdup ("unknown");
|
edid = read_output_edid (manager_xrandr, meta_output->output_id);
|
||||||
meta_output->serial = g_strdup ("");
|
if (edid)
|
||||||
|
{
|
||||||
|
gsize len;
|
||||||
|
|
||||||
|
parsed_edid = decode_edid (g_bytes_get_data (edid, &len));
|
||||||
|
if (parsed_edid)
|
||||||
|
{
|
||||||
|
meta_output->vendor = g_strndup (parsed_edid->manufacturer_code, 4);
|
||||||
|
if (parsed_edid->dsc_product_name[0])
|
||||||
|
meta_output->product = g_strndup (parsed_edid->dsc_product_name, 14);
|
||||||
|
else
|
||||||
|
meta_output->product = g_strdup_printf ("0x%04x", (unsigned)parsed_edid->product_code);
|
||||||
|
if (parsed_edid->dsc_serial_number[0])
|
||||||
|
meta_output->serial = g_strndup (parsed_edid->dsc_serial_number, 14);
|
||||||
|
else
|
||||||
|
meta_output->serial = g_strdup_printf ("0x%08x", parsed_edid->serial_number);
|
||||||
|
|
||||||
|
g_free (parsed_edid);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_bytes_unref (edid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!meta_output->vendor)
|
||||||
|
{
|
||||||
|
meta_output->vendor = g_strdup ("unknown");
|
||||||
|
meta_output->product = g_strdup ("unknown");
|
||||||
|
meta_output->serial = g_strdup ("unknown");
|
||||||
|
}
|
||||||
meta_output->width_mm = output->mm_width;
|
meta_output->width_mm = output->mm_width;
|
||||||
meta_output->height_mm = output->mm_height;
|
meta_output->height_mm = output->mm_height;
|
||||||
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
|
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
|
||||||
@@ -420,7 +532,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
|||||||
*/
|
*/
|
||||||
for (j = 0; j < (unsigned)output->nclone; j++)
|
for (j = 0; j < (unsigned)output->nclone; j++)
|
||||||
{
|
{
|
||||||
meta_output->possible_clones = GINT_TO_POINTER (output->clones[j]);
|
meta_output->possible_clones[j] = GINT_TO_POINTER (output->clones[j]);
|
||||||
}
|
}
|
||||||
|
|
||||||
meta_output->is_primary = ((XID)meta_output->output_id == primary_output);
|
meta_output->is_primary = ((XID)meta_output->output_id == primary_output);
|
||||||
@@ -466,73 +578,13 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static guint8 *
|
|
||||||
get_edid_property (Display *dpy,
|
|
||||||
RROutput output,
|
|
||||||
Atom atom,
|
|
||||||
gsize *len)
|
|
||||||
{
|
|
||||||
unsigned char *prop;
|
|
||||||
int actual_format;
|
|
||||||
unsigned long nitems, bytes_after;
|
|
||||||
Atom actual_type;
|
|
||||||
guint8 *result;
|
|
||||||
|
|
||||||
XRRGetOutputProperty (dpy, output, atom,
|
|
||||||
0, 100, False, False,
|
|
||||||
AnyPropertyType,
|
|
||||||
&actual_type, &actual_format,
|
|
||||||
&nitems, &bytes_after, &prop);
|
|
||||||
|
|
||||||
if (actual_type == XA_INTEGER && actual_format == 8)
|
|
||||||
{
|
|
||||||
result = g_memdup (prop, nitems);
|
|
||||||
if (len)
|
|
||||||
*len = nitems;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
XFree (prop);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GBytes *
|
static GBytes *
|
||||||
meta_monitor_manager_xrandr_read_edid (MetaMonitorManager *manager,
|
meta_monitor_manager_xrandr_read_edid (MetaMonitorManager *manager,
|
||||||
MetaOutput *output)
|
MetaOutput *output)
|
||||||
{
|
{
|
||||||
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
|
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
|
||||||
Atom edid_atom;
|
|
||||||
guint8 *result;
|
|
||||||
gsize len;
|
|
||||||
|
|
||||||
edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID", FALSE);
|
return read_output_edid (manager_xrandr, output->output_id);
|
||||||
result = get_edid_property (manager_xrandr->xdisplay, output->output_id, edid_atom, &len);
|
|
||||||
|
|
||||||
if (!result)
|
|
||||||
{
|
|
||||||
edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID_DATA", FALSE);
|
|
||||||
result = get_edid_property (manager_xrandr->xdisplay, output->output_id, edid_atom, &len);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!result)
|
|
||||||
{
|
|
||||||
edid_atom = XInternAtom (manager_xrandr->xdisplay, "XFree86_DDC_EDID1_RAWDATA", FALSE);
|
|
||||||
result = get_edid_property (manager_xrandr->xdisplay, output->output_id, edid_atom, &len);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
if (len > 0 && len % 128 == 0)
|
|
||||||
return g_bytes_new_take (result, len);
|
|
||||||
else
|
|
||||||
g_free (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -615,16 +667,46 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
|||||||
{
|
{
|
||||||
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
|
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
int width, height, width_mm, height_mm;
|
||||||
|
|
||||||
meta_display_grab (meta_get_display ());
|
meta_display_grab (meta_get_display ());
|
||||||
|
|
||||||
|
/* First compute the new size of the screen (framebuffer) */
|
||||||
|
width = 0; height = 0;
|
||||||
for (i = 0; i < n_crtcs; i++)
|
for (i = 0; i < n_crtcs; i++)
|
||||||
{
|
{
|
||||||
MetaCRTCInfo *crtc_info = crtcs[i];
|
MetaCRTCInfo *crtc_info = crtcs[i];
|
||||||
MetaCRTC *crtc = crtc_info->crtc;
|
MetaCRTC *crtc = crtc_info->crtc;
|
||||||
crtc->dirty = TRUE;
|
crtc->is_dirty = TRUE;
|
||||||
|
|
||||||
if (crtc_info->mode == NULL)
|
if (crtc_info->mode == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (meta_monitor_transform_is_rotated (crtc_info->transform))
|
||||||
|
{
|
||||||
|
width = MAX (width, crtc_info->x + crtc_info->mode->height);
|
||||||
|
height = MAX (height, crtc_info->y + crtc_info->mode->width);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
width = MAX (width, crtc_info->x + crtc_info->mode->width);
|
||||||
|
height = MAX (height, crtc_info->y + crtc_info->mode->height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Second disable all newly disabled CRTCs, or CRTCs that in the previous
|
||||||
|
configuration would be outside the new framebuffer (otherwise X complains
|
||||||
|
loudly when resizing)
|
||||||
|
CRTC will be enabled again after resizing the FB
|
||||||
|
*/
|
||||||
|
for (i = 0; i < n_crtcs; i++)
|
||||||
|
{
|
||||||
|
MetaCRTCInfo *crtc_info = crtcs[i];
|
||||||
|
MetaCRTC *crtc = crtc_info->crtc;
|
||||||
|
|
||||||
|
if (crtc_info->mode == NULL ||
|
||||||
|
crtc->rect.x + crtc->rect.width > width ||
|
||||||
|
crtc->rect.y + crtc->rect.height > height)
|
||||||
{
|
{
|
||||||
XRRSetCrtcConfig (manager_xrandr->xdisplay,
|
XRRSetCrtcConfig (manager_xrandr->xdisplay,
|
||||||
manager_xrandr->resources,
|
manager_xrandr->resources,
|
||||||
@@ -634,57 +716,13 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
|||||||
None,
|
None,
|
||||||
RR_Rotate_0,
|
RR_Rotate_0,
|
||||||
NULL, 0);
|
NULL, 0);
|
||||||
|
|
||||||
|
crtc->rect.x = 0;
|
||||||
|
crtc->rect.y = 0;
|
||||||
|
crtc->rect.width = 0;
|
||||||
|
crtc->rect.height = 0;
|
||||||
|
crtc->current_mode = NULL;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
MetaMonitorMode *mode;
|
|
||||||
XID *outputs;
|
|
||||||
int j, n_outputs;
|
|
||||||
Status ok;
|
|
||||||
|
|
||||||
mode = crtc_info->mode;
|
|
||||||
|
|
||||||
n_outputs = crtc_info->outputs->len;
|
|
||||||
outputs = g_new (XID, n_outputs);
|
|
||||||
|
|
||||||
for (j = 0; j < n_outputs; j++)
|
|
||||||
outputs[j] = ((MetaOutput**)crtc_info->outputs->pdata)[j]->output_id;
|
|
||||||
|
|
||||||
meta_error_trap_push (meta_get_display ());
|
|
||||||
ok = XRRSetCrtcConfig (manager_xrandr->xdisplay,
|
|
||||||
manager_xrandr->resources,
|
|
||||||
(XID)crtc->crtc_id,
|
|
||||||
manager_xrandr->time,
|
|
||||||
crtc_info->x, crtc_info->y,
|
|
||||||
(XID)mode->mode_id,
|
|
||||||
wl_transform_to_xrandr (crtc_info->transform),
|
|
||||||
outputs, n_outputs);
|
|
||||||
meta_error_trap_pop (meta_get_display ());
|
|
||||||
|
|
||||||
if (ok != Success)
|
|
||||||
meta_warning ("Configuring CRTC %d with mode %d (%d x %d @ %f) at position %d, %d and transfrom %u failed\n",
|
|
||||||
(unsigned)(crtc - manager->crtcs), (unsigned)(mode - manager->modes),
|
|
||||||
mode->width, mode->height, (float)mode->refresh_rate,
|
|
||||||
crtc_info->x, crtc_info->y, crtc_info->transform);
|
|
||||||
|
|
||||||
g_free (outputs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < n_outputs; i++)
|
|
||||||
{
|
|
||||||
MetaOutputInfo *output_info = outputs[i];
|
|
||||||
|
|
||||||
if (output_info->is_primary)
|
|
||||||
{
|
|
||||||
XRRSetOutputPrimary (manager_xrandr->xdisplay,
|
|
||||||
DefaultRootWindow (manager_xrandr->xdisplay),
|
|
||||||
(XID)output_info->output->output_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
output_set_presentation_xrandr (manager_xrandr,
|
|
||||||
output_info->output,
|
|
||||||
output_info->is_presentation);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disable CRTCs not mentioned in the list */
|
/* Disable CRTCs not mentioned in the list */
|
||||||
@@ -692,9 +730,9 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
|||||||
{
|
{
|
||||||
MetaCRTC *crtc = &manager->crtcs[i];
|
MetaCRTC *crtc = &manager->crtcs[i];
|
||||||
|
|
||||||
if (crtc->dirty)
|
if (crtc->is_dirty)
|
||||||
{
|
{
|
||||||
crtc->dirty = FALSE;
|
crtc->is_dirty = FALSE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (crtc->current_mode == NULL)
|
if (crtc->current_mode == NULL)
|
||||||
@@ -708,6 +746,159 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
|||||||
None,
|
None,
|
||||||
RR_Rotate_0,
|
RR_Rotate_0,
|
||||||
NULL, 0);
|
NULL, 0);
|
||||||
|
|
||||||
|
crtc->rect.x = 0;
|
||||||
|
crtc->rect.y = 0;
|
||||||
|
crtc->rect.width = 0;
|
||||||
|
crtc->rect.height = 0;
|
||||||
|
crtc->current_mode = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_assert (width > 0 && height > 0);
|
||||||
|
/* The 'physical size' of an X screen is meaningless if that screen
|
||||||
|
* can consist of many monitors. So just pick a size that make the
|
||||||
|
* dpi 96.
|
||||||
|
*
|
||||||
|
* Firefox and Evince apparently believe what X tells them.
|
||||||
|
*/
|
||||||
|
width_mm = (width / DPI_FALLBACK) * 25.4 + 0.5;
|
||||||
|
height_mm = (height / DPI_FALLBACK) * 25.4 + 0.5;
|
||||||
|
meta_error_trap_push (meta_get_display ());
|
||||||
|
XRRSetScreenSize (manager_xrandr->xdisplay, DefaultRootWindow (manager_xrandr->xdisplay),
|
||||||
|
width, height, width_mm, height_mm);
|
||||||
|
meta_error_trap_pop (meta_get_display ());
|
||||||
|
|
||||||
|
for (i = 0; i < n_crtcs; i++)
|
||||||
|
{
|
||||||
|
MetaCRTCInfo *crtc_info = crtcs[i];
|
||||||
|
MetaCRTC *crtc = crtc_info->crtc;
|
||||||
|
|
||||||
|
if (crtc_info->mode != NULL)
|
||||||
|
{
|
||||||
|
MetaMonitorMode *mode;
|
||||||
|
XID *outputs;
|
||||||
|
unsigned int j, n_outputs;
|
||||||
|
int width, height;
|
||||||
|
Status ok;
|
||||||
|
unsigned long old_controlled_mask;
|
||||||
|
unsigned long new_controlled_mask;
|
||||||
|
|
||||||
|
mode = crtc_info->mode;
|
||||||
|
|
||||||
|
n_outputs = crtc_info->outputs->len;
|
||||||
|
outputs = g_new (XID, n_outputs);
|
||||||
|
|
||||||
|
old_controlled_mask = 0;
|
||||||
|
for (j = 0; j < manager->n_outputs; j++)
|
||||||
|
{
|
||||||
|
MetaOutput *output;
|
||||||
|
|
||||||
|
output = &manager->outputs[j];
|
||||||
|
|
||||||
|
if (output->crtc == crtc)
|
||||||
|
old_controlled_mask |= 1UL << j;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_controlled_mask = 0;
|
||||||
|
for (j = 0; j < n_outputs; j++)
|
||||||
|
{
|
||||||
|
MetaOutput *output;
|
||||||
|
|
||||||
|
output = ((MetaOutput**)crtc_info->outputs->pdata)[j];
|
||||||
|
|
||||||
|
output->is_dirty = TRUE;
|
||||||
|
output->crtc = crtc;
|
||||||
|
new_controlled_mask |= 1UL << j;
|
||||||
|
|
||||||
|
outputs[j] = output->output_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (crtc->current_mode == mode &&
|
||||||
|
crtc->rect.x == crtc_info->x &&
|
||||||
|
crtc->rect.y == crtc_info->y &&
|
||||||
|
crtc->transform == crtc_info->transform &&
|
||||||
|
old_controlled_mask == new_controlled_mask)
|
||||||
|
{
|
||||||
|
/* No change */
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
|
||||||
|
meta_error_trap_push (meta_get_display ());
|
||||||
|
ok = XRRSetCrtcConfig (manager_xrandr->xdisplay,
|
||||||
|
manager_xrandr->resources,
|
||||||
|
(XID)crtc->crtc_id,
|
||||||
|
manager_xrandr->time,
|
||||||
|
crtc_info->x, crtc_info->y,
|
||||||
|
(XID)mode->mode_id,
|
||||||
|
wl_transform_to_xrandr (crtc_info->transform),
|
||||||
|
outputs, n_outputs);
|
||||||
|
meta_error_trap_pop (meta_get_display ());
|
||||||
|
|
||||||
|
if (ok != Success)
|
||||||
|
{
|
||||||
|
meta_warning ("Configuring CRTC %d with mode %d (%d x %d @ %f) at position %d, %d and transfrom %u failed\n",
|
||||||
|
(unsigned)(crtc->crtc_id), (unsigned)(mode->mode_id),
|
||||||
|
mode->width, mode->height, (float)mode->refresh_rate,
|
||||||
|
crtc_info->x, crtc_info->y, crtc_info->transform);
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (meta_monitor_transform_is_rotated (crtc_info->transform))
|
||||||
|
{
|
||||||
|
width = mode->height;
|
||||||
|
height = mode->width;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
width = mode->width;
|
||||||
|
height = mode->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
crtc->rect.x = crtc_info->x;
|
||||||
|
crtc->rect.y = crtc_info->y;
|
||||||
|
crtc->rect.width = width;
|
||||||
|
crtc->rect.height = height;
|
||||||
|
crtc->current_mode = mode;
|
||||||
|
crtc->transform = crtc_info->transform;
|
||||||
|
|
||||||
|
next:
|
||||||
|
g_free (outputs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < n_outputs; i++)
|
||||||
|
{
|
||||||
|
MetaOutputInfo *output_info = outputs[i];
|
||||||
|
MetaOutput *output = output_info->output;
|
||||||
|
|
||||||
|
if (output_info->is_primary)
|
||||||
|
{
|
||||||
|
XRRSetOutputPrimary (manager_xrandr->xdisplay,
|
||||||
|
DefaultRootWindow (manager_xrandr->xdisplay),
|
||||||
|
(XID)output_info->output->output_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
output_set_presentation_xrandr (manager_xrandr,
|
||||||
|
output_info->output,
|
||||||
|
output_info->is_presentation);
|
||||||
|
|
||||||
|
output->is_primary = output_info->is_primary;
|
||||||
|
output->is_presentation = output_info->is_presentation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable outputs not mentioned in the list */
|
||||||
|
for (i = 0; i < manager->n_outputs; i++)
|
||||||
|
{
|
||||||
|
MetaOutput *output = &manager->outputs[i];
|
||||||
|
|
||||||
|
if (output->is_dirty)
|
||||||
|
{
|
||||||
|
output->is_dirty = FALSE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
output->crtc = NULL;
|
||||||
|
output->is_primary = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
meta_display_ungrab (meta_get_display ());
|
meta_display_ungrab (meta_get_display ());
|
||||||
@@ -722,7 +913,7 @@ meta_monitor_manager_xrandr_change_backlight (MetaMonitorManager *manager,
|
|||||||
MetaDisplay *display = meta_get_display ();
|
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);
|
||||||
|
|
||||||
meta_error_trap_push (display);
|
meta_error_trap_push (display);
|
||||||
XRRChangeOutputProperty (manager_xrandr->xdisplay,
|
XRRChangeOutputProperty (manager_xrandr->xdisplay,
|
||||||
@@ -766,14 +957,16 @@ meta_monitor_manager_xrandr_set_crtc_gamma (MetaMonitorManager *manager,
|
|||||||
unsigned short *blue)
|
unsigned short *blue)
|
||||||
{
|
{
|
||||||
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
|
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
|
||||||
XRRCrtcGamma gamma;
|
XRRCrtcGamma *gamma;
|
||||||
|
|
||||||
gamma.size = size;
|
gamma = XRRAllocGamma (size);
|
||||||
gamma.red = red;
|
memcpy (gamma->red, red, sizeof (unsigned short) * size);
|
||||||
gamma.green = green;
|
memcpy (gamma->green, green, sizeof (unsigned short) * size);
|
||||||
gamma.blue = blue;
|
memcpy (gamma->blue, blue, sizeof (unsigned short) * size);
|
||||||
|
|
||||||
XRRSetCrtcGamma (manager_xrandr->xdisplay, (XID)crtc->crtc_id, &gamma);
|
XRRSetCrtcGamma (manager_xrandr->xdisplay, (XID)crtc->crtc_id, gamma);
|
||||||
|
|
||||||
|
XRRFreeGamma (gamma);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2001, 2002 Havoc Pennington
|
* Copyright (C) 2001, 2002 Havoc Pennington
|
||||||
@@ -28,20 +28,20 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
|
|
||||||
#include <meta/main.h>
|
#include <meta/main.h>
|
||||||
|
#include <meta/util.h>
|
||||||
#include <meta/errors.h>
|
#include <meta/errors.h>
|
||||||
#include "monitor-private.h"
|
#include "monitor-private.h"
|
||||||
#include "meta-wayland-private.h"
|
|
||||||
|
|
||||||
#include "meta-dbus-xrandr.h"
|
#include "meta-dbus-xrandr.h"
|
||||||
|
|
||||||
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
|
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
MONITORS_CHANGED,
|
|
||||||
CONFIRM_DISPLAY_CHANGE,
|
CONFIRM_DISPLAY_CHANGE,
|
||||||
SIGNALS_LAST
|
SIGNALS_LAST
|
||||||
};
|
};
|
||||||
@@ -61,8 +61,8 @@ G_DEFINE_TYPE_WITH_CODE (MetaMonitorManager, meta_monitor_manager, META_DBUS_TYP
|
|||||||
|
|
||||||
static void free_output_array (MetaOutput *old_outputs,
|
static void free_output_array (MetaOutput *old_outputs,
|
||||||
int n_old_outputs);
|
int n_old_outputs);
|
||||||
static void free_mode_array (MetaMonitorMode *old_modes,
|
static void invalidate_logical_config (MetaMonitorManager *manager);
|
||||||
int n_old_modes);
|
static void initialize_dbus_interface (MetaMonitorManager *manager);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
read_current_dummy (MetaMonitorManager *manager)
|
read_current_dummy (MetaMonitorManager *manager)
|
||||||
@@ -127,7 +127,7 @@ read_current_dummy (MetaMonitorManager *manager)
|
|||||||
manager->crtcs[0].current_mode = &manager->modes[0];
|
manager->crtcs[0].current_mode = &manager->modes[0];
|
||||||
manager->crtcs[0].transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
manager->crtcs[0].transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||||
manager->crtcs[0].all_transforms = ALL_WL_TRANSFORMS;
|
manager->crtcs[0].all_transforms = ALL_WL_TRANSFORMS;
|
||||||
manager->crtcs[0].dirty = FALSE;
|
manager->crtcs[0].is_dirty = FALSE;
|
||||||
manager->crtcs[0].logical_monitor = NULL;
|
manager->crtcs[0].logical_monitor = NULL;
|
||||||
|
|
||||||
manager->crtcs[1].crtc_id = 5;
|
manager->crtcs[1].crtc_id = 5;
|
||||||
@@ -138,7 +138,7 @@ read_current_dummy (MetaMonitorManager *manager)
|
|||||||
manager->crtcs[1].current_mode = NULL;
|
manager->crtcs[1].current_mode = NULL;
|
||||||
manager->crtcs[1].transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
manager->crtcs[1].transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||||
manager->crtcs[1].all_transforms = ALL_WL_TRANSFORMS;
|
manager->crtcs[1].all_transforms = ALL_WL_TRANSFORMS;
|
||||||
manager->crtcs[1].dirty = FALSE;
|
manager->crtcs[1].is_dirty = FALSE;
|
||||||
manager->crtcs[1].logical_monitor = NULL;
|
manager->crtcs[1].logical_monitor = NULL;
|
||||||
|
|
||||||
manager->crtcs[2].crtc_id = 5;
|
manager->crtcs[2].crtc_id = 5;
|
||||||
@@ -149,7 +149,7 @@ read_current_dummy (MetaMonitorManager *manager)
|
|||||||
manager->crtcs[2].current_mode = NULL;
|
manager->crtcs[2].current_mode = NULL;
|
||||||
manager->crtcs[2].transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
manager->crtcs[2].transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||||
manager->crtcs[2].all_transforms = ALL_WL_TRANSFORMS;
|
manager->crtcs[2].all_transforms = ALL_WL_TRANSFORMS;
|
||||||
manager->crtcs[2].dirty = FALSE;
|
manager->crtcs[2].is_dirty = FALSE;
|
||||||
manager->crtcs[2].logical_monitor = NULL;
|
manager->crtcs[2].logical_monitor = NULL;
|
||||||
|
|
||||||
manager->outputs = g_new0 (MetaOutput, 3);
|
manager->outputs = g_new0 (MetaOutput, 3);
|
||||||
@@ -251,7 +251,7 @@ apply_config_dummy (MetaMonitorManager *manager,
|
|||||||
{
|
{
|
||||||
MetaCRTCInfo *crtc_info = crtcs[i];
|
MetaCRTCInfo *crtc_info = crtcs[i];
|
||||||
MetaCRTC *crtc = crtc_info->crtc;
|
MetaCRTC *crtc = crtc_info->crtc;
|
||||||
crtc->dirty = TRUE;
|
crtc->is_dirty = TRUE;
|
||||||
|
|
||||||
if (crtc_info->mode == NULL)
|
if (crtc_info->mode == NULL)
|
||||||
{
|
{
|
||||||
@@ -266,25 +266,37 @@ apply_config_dummy (MetaMonitorManager *manager,
|
|||||||
MetaMonitorMode *mode;
|
MetaMonitorMode *mode;
|
||||||
MetaOutput *output;
|
MetaOutput *output;
|
||||||
int i, n_outputs;
|
int i, n_outputs;
|
||||||
|
int width, height;
|
||||||
|
|
||||||
mode = crtc_info->mode;
|
mode = crtc_info->mode;
|
||||||
|
|
||||||
|
if (meta_monitor_transform_is_rotated (crtc_info->transform))
|
||||||
|
{
|
||||||
|
width = mode->height;
|
||||||
|
height = mode->width;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
width = mode->width;
|
||||||
|
height = mode->height;
|
||||||
|
}
|
||||||
|
|
||||||
crtc->rect.x = crtc_info->x;
|
crtc->rect.x = crtc_info->x;
|
||||||
crtc->rect.y = crtc_info->y;
|
crtc->rect.y = crtc_info->y;
|
||||||
crtc->rect.width = mode->width;
|
crtc->rect.width = width;
|
||||||
crtc->rect.height = mode->height;
|
crtc->rect.height = height;
|
||||||
crtc->current_mode = mode;
|
crtc->current_mode = mode;
|
||||||
crtc->transform = crtc_info->transform;
|
crtc->transform = crtc_info->transform;
|
||||||
|
|
||||||
screen_width = MAX (screen_width, crtc_info->x + mode->width);
|
screen_width = MAX (screen_width, crtc_info->x + width);
|
||||||
screen_height = MAX (screen_height, crtc_info->y + mode->height);
|
screen_height = MAX (screen_height, crtc_info->y + height);
|
||||||
|
|
||||||
n_outputs = crtc_info->outputs->len;
|
n_outputs = crtc_info->outputs->len;
|
||||||
for (i = 0; i < n_outputs; i++)
|
for (i = 0; i < n_outputs; i++)
|
||||||
{
|
{
|
||||||
output = ((MetaOutput**)crtc_info->outputs->pdata)[i];
|
output = ((MetaOutput**)crtc_info->outputs->pdata)[i];
|
||||||
|
|
||||||
output->dirty = TRUE;
|
output->is_dirty = TRUE;
|
||||||
output->crtc = crtc;
|
output->crtc = crtc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -306,9 +318,9 @@ apply_config_dummy (MetaMonitorManager *manager,
|
|||||||
|
|
||||||
crtc->logical_monitor = NULL;
|
crtc->logical_monitor = NULL;
|
||||||
|
|
||||||
if (crtc->dirty)
|
if (crtc->is_dirty)
|
||||||
{
|
{
|
||||||
crtc->dirty = FALSE;
|
crtc->is_dirty = FALSE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,9 +336,9 @@ apply_config_dummy (MetaMonitorManager *manager,
|
|||||||
{
|
{
|
||||||
MetaOutput *output = &manager->outputs[i];
|
MetaOutput *output = &manager->outputs[i];
|
||||||
|
|
||||||
if (output->dirty)
|
if (output->is_dirty)
|
||||||
{
|
{
|
||||||
output->dirty = FALSE;
|
output->is_dirty = FALSE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,7 +349,7 @@ apply_config_dummy (MetaMonitorManager *manager,
|
|||||||
manager->screen_width = screen_width;
|
manager->screen_width = screen_width;
|
||||||
manager->screen_height = screen_height;
|
manager->screen_height = screen_height;
|
||||||
|
|
||||||
meta_monitor_manager_rebuild_derived (manager);
|
invalidate_logical_config (manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GBytes *
|
static GBytes *
|
||||||
@@ -462,6 +474,15 @@ 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 (meta_is_wayland_compositor ())
|
||||||
|
return META_TYPE_MONITOR_MANAGER; /* FIXME: KMS */
|
||||||
|
else
|
||||||
|
return META_TYPE_MONITOR_MANAGER_XRANDR;
|
||||||
|
}
|
||||||
|
|
||||||
static MetaMonitorManager *
|
static MetaMonitorManager *
|
||||||
meta_monitor_manager_new (void)
|
meta_monitor_manager_new (void)
|
||||||
{
|
{
|
||||||
@@ -471,21 +492,7 @@ meta_monitor_manager_new (void)
|
|||||||
env = g_getenv ("META_DEBUG_MULTIMONITOR");
|
env = g_getenv ("META_DEBUG_MULTIMONITOR");
|
||||||
|
|
||||||
if (env == NULL)
|
if (env == NULL)
|
||||||
{
|
type = get_default_backend ();
|
||||||
if (meta_is_wayland_compositor ())
|
|
||||||
{
|
|
||||||
MetaWaylandCompositor *compositor;
|
|
||||||
|
|
||||||
compositor = meta_wayland_compositor_get_default ();
|
|
||||||
|
|
||||||
if (meta_wayland_compositor_is_native (compositor))
|
|
||||||
type = META_TYPE_MONITOR_MANAGER_KMS;
|
|
||||||
else
|
|
||||||
type = META_TYPE_MONITOR_MANAGER;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
type = META_TYPE_MONITOR_MANAGER_XRANDR;
|
|
||||||
}
|
|
||||||
else if (strcmp (env, "xrandr") == 0)
|
else if (strcmp (env, "xrandr") == 0)
|
||||||
type = META_TYPE_MONITOR_MANAGER_XRANDR;
|
type = META_TYPE_MONITOR_MANAGER_XRANDR;
|
||||||
else
|
else
|
||||||
@@ -520,22 +527,22 @@ meta_monitor_manager_constructed (GObject *object)
|
|||||||
MetaOutput *old_outputs;
|
MetaOutput *old_outputs;
|
||||||
MetaCRTC *old_crtcs;
|
MetaCRTC *old_crtcs;
|
||||||
MetaMonitorMode *old_modes;
|
MetaMonitorMode *old_modes;
|
||||||
unsigned int n_old_outputs, n_old_modes;
|
int n_old_outputs;
|
||||||
|
|
||||||
old_outputs = manager->outputs;
|
old_outputs = manager->outputs;
|
||||||
n_old_outputs = manager->n_outputs;
|
n_old_outputs = manager->n_outputs;
|
||||||
old_modes = manager->modes;
|
old_modes = manager->modes;
|
||||||
n_old_modes = manager->n_modes;
|
|
||||||
old_crtcs = manager->crtcs;
|
old_crtcs = manager->crtcs;
|
||||||
|
|
||||||
read_current_config (manager);
|
read_current_config (manager);
|
||||||
|
|
||||||
free_output_array (old_outputs, n_old_outputs);
|
free_output_array (old_outputs, n_old_outputs);
|
||||||
free_mode_array (old_modes, n_old_modes);
|
g_free (old_modes);
|
||||||
g_free (old_crtcs);
|
g_free (old_crtcs);
|
||||||
}
|
}
|
||||||
|
|
||||||
make_logical_config (manager);
|
make_logical_config (manager);
|
||||||
|
initialize_dbus_interface (manager);
|
||||||
|
|
||||||
manager->in_init = FALSE;
|
manager->in_init = FALSE;
|
||||||
}
|
}
|
||||||
@@ -575,39 +582,19 @@ free_output_array (MetaOutput *old_outputs,
|
|||||||
g_free (old_outputs[i].modes);
|
g_free (old_outputs[i].modes);
|
||||||
g_free (old_outputs[i].possible_crtcs);
|
g_free (old_outputs[i].possible_crtcs);
|
||||||
g_free (old_outputs[i].possible_clones);
|
g_free (old_outputs[i].possible_clones);
|
||||||
|
|
||||||
if (old_outputs[i].driver_notify)
|
|
||||||
old_outputs[i].driver_notify (&old_outputs[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free (old_outputs);
|
g_free (old_outputs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
free_mode_array (MetaMonitorMode *old_modes,
|
|
||||||
int n_old_modes)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < n_old_modes; i++)
|
|
||||||
{
|
|
||||||
g_free (old_modes[i].name);
|
|
||||||
|
|
||||||
if (old_modes[i].driver_notify)
|
|
||||||
old_modes[i].driver_notify (&old_modes[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_free (old_modes);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_monitor_manager_finalize (GObject *object)
|
meta_monitor_manager_finalize (GObject *object)
|
||||||
{
|
{
|
||||||
MetaMonitorManager *manager = META_MONITOR_MANAGER (object);
|
MetaMonitorManager *manager = META_MONITOR_MANAGER (object);
|
||||||
|
|
||||||
free_output_array (manager->outputs, manager->n_outputs);
|
free_output_array (manager->outputs, manager->n_outputs);
|
||||||
free_mode_array (manager->modes, manager->n_modes);
|
|
||||||
g_free (manager->monitor_infos);
|
g_free (manager->monitor_infos);
|
||||||
|
g_free (manager->modes);
|
||||||
g_free (manager->crtcs);
|
g_free (manager->crtcs);
|
||||||
|
|
||||||
G_OBJECT_CLASS (meta_monitor_manager_parent_class)->finalize (object);
|
G_OBJECT_CLASS (meta_monitor_manager_parent_class)->finalize (object);
|
||||||
@@ -677,17 +664,9 @@ meta_monitor_manager_class_init (MetaMonitorManagerClass *klass)
|
|||||||
object_class->finalize = meta_monitor_manager_finalize;
|
object_class->finalize = meta_monitor_manager_finalize;
|
||||||
|
|
||||||
klass->read_current = read_current_dummy;
|
klass->read_current = read_current_dummy;
|
||||||
klass->read_edid = read_edid_dummy;
|
|
||||||
klass->get_edid_file = get_edid_file_dummy;
|
|
||||||
klass->apply_configuration = apply_config_dummy;
|
klass->apply_configuration = apply_config_dummy;
|
||||||
|
klass->get_edid_file = get_edid_file_dummy;
|
||||||
signals[MONITORS_CHANGED] =
|
klass->read_edid = read_edid_dummy;
|
||||||
g_signal_new ("monitors-changed",
|
|
||||||
G_TYPE_FROM_CLASS (object_class),
|
|
||||||
G_SIGNAL_RUN_LAST,
|
|
||||||
0,
|
|
||||||
NULL, NULL, NULL,
|
|
||||||
G_TYPE_NONE, 0);
|
|
||||||
|
|
||||||
signals[CONFIRM_DISPLAY_CHANGE] =
|
signals[CONFIRM_DISPLAY_CHANGE] =
|
||||||
g_signal_new ("confirm-display-change",
|
g_signal_new ("confirm-display-change",
|
||||||
@@ -724,16 +703,41 @@ diagonal_to_str (double d)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
make_display_name (MetaOutput *output)
|
make_display_name (MetaMonitorManager *manager,
|
||||||
|
MetaOutput *output)
|
||||||
{
|
{
|
||||||
|
if (g_str_has_prefix (output->name, "LVDS") ||
|
||||||
|
g_str_has_prefix (output->name, "eDP"))
|
||||||
|
return g_strdup (_("Built-in display"));
|
||||||
|
|
||||||
if (output->width_mm != -1 && output->height_mm != -1)
|
if (output->width_mm != -1 && output->height_mm != -1)
|
||||||
{
|
{
|
||||||
double d = sqrt (output->width_mm * output->width_mm +
|
double d = sqrt (output->width_mm * output->width_mm +
|
||||||
output->height_mm * output->height_mm);
|
output->height_mm * output->height_mm);
|
||||||
char *inches = diagonal_to_str (d / 25.4);
|
char *inches = diagonal_to_str (d / 25.4);
|
||||||
|
char *vendor_name;
|
||||||
char *ret;
|
char *ret;
|
||||||
|
|
||||||
ret = g_strdup_printf ("%s %s", output->vendor, inches);
|
if (g_strcmp0 (output->vendor, "unknown") != 0)
|
||||||
|
{
|
||||||
|
if (!manager->pnp_ids)
|
||||||
|
manager->pnp_ids = gnome_pnp_ids_new ();
|
||||||
|
|
||||||
|
vendor_name = gnome_pnp_ids_get_pnp_id (manager->pnp_ids,
|
||||||
|
output->vendor);
|
||||||
|
|
||||||
|
ret = g_strdup_printf ("%s %s", vendor_name, inches);
|
||||||
|
|
||||||
|
g_free (vendor_name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* 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"'
|
||||||
|
*/
|
||||||
|
ret = g_strdup_printf (_("Unknown %s"), inches);
|
||||||
|
}
|
||||||
|
|
||||||
g_free (inches);
|
g_free (inches);
|
||||||
return ret;
|
return ret;
|
||||||
@@ -809,8 +813,12 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
|
|||||||
g_variant_new_string (output->product));
|
g_variant_new_string (output->product));
|
||||||
g_variant_builder_add (&properties, "{sv}", "serial",
|
g_variant_builder_add (&properties, "{sv}", "serial",
|
||||||
g_variant_new_string (output->serial));
|
g_variant_new_string (output->serial));
|
||||||
|
g_variant_builder_add (&properties, "{sv}", "width-mm",
|
||||||
|
g_variant_new_int32 (output->width_mm));
|
||||||
|
g_variant_builder_add (&properties, "{sv}", "height-mm",
|
||||||
|
g_variant_new_int32 (output->height_mm));
|
||||||
g_variant_builder_add (&properties, "{sv}", "display-name",
|
g_variant_builder_add (&properties, "{sv}", "display-name",
|
||||||
g_variant_new_take_string (make_display_name (output)));
|
g_variant_new_take_string (make_display_name (manager, output)));
|
||||||
g_variant_builder_add (&properties, "{sv}", "backlight",
|
g_variant_builder_add (&properties, "{sv}", "backlight",
|
||||||
g_variant_new_int32 (output->backlight));
|
g_variant_new_int32 (output->backlight));
|
||||||
g_variant_builder_add (&properties, "{sv}", "primary",
|
g_variant_builder_add (&properties, "{sv}", "primary",
|
||||||
@@ -978,7 +986,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
|||||||
crtc_info = g_slice_new (MetaCRTCInfo);
|
crtc_info = g_slice_new (MetaCRTCInfo);
|
||||||
crtc_info->outputs = g_ptr_array_new ();
|
crtc_info->outputs = g_ptr_array_new ();
|
||||||
|
|
||||||
if (crtc_id < 0 || crtc_id >= manager->n_crtcs)
|
if (crtc_id >= manager->n_crtcs)
|
||||||
{
|
{
|
||||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||||
G_DBUS_ERROR_INVALID_ARGS,
|
G_DBUS_ERROR_INVALID_ARGS,
|
||||||
@@ -1000,10 +1008,23 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
|||||||
|
|
||||||
if (mode)
|
if (mode)
|
||||||
{
|
{
|
||||||
|
int width, height;
|
||||||
|
|
||||||
|
if (meta_monitor_transform_is_rotated (transform))
|
||||||
|
{
|
||||||
|
width = mode->height;
|
||||||
|
height = mode->width;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
width = mode->width;
|
||||||
|
height = mode->height;
|
||||||
|
}
|
||||||
|
|
||||||
if (x < 0 ||
|
if (x < 0 ||
|
||||||
x + mode->width > manager->max_screen_width ||
|
x + width > manager->max_screen_width ||
|
||||||
y < 0 ||
|
y < 0 ||
|
||||||
y + mode->height > manager->max_screen_height)
|
y + height > manager->max_screen_height)
|
||||||
{
|
{
|
||||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||||
G_DBUS_ERROR_INVALID_ARGS,
|
G_DBUS_ERROR_INVALID_ARGS,
|
||||||
@@ -1011,8 +1032,8 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_screen_width = MAX (new_screen_width, x + mode->width);
|
new_screen_width = MAX (new_screen_width, x + width);
|
||||||
new_screen_height = MAX (new_screen_height, y + mode->height);
|
new_screen_height = MAX (new_screen_height, y + height);
|
||||||
crtc_info->x = x;
|
crtc_info->x = x;
|
||||||
crtc_info->y = y;
|
crtc_info->y = y;
|
||||||
}
|
}
|
||||||
@@ -1023,7 +1044,8 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (transform < WL_OUTPUT_TRANSFORM_NORMAL ||
|
if (transform < WL_OUTPUT_TRANSFORM_NORMAL ||
|
||||||
transform > WL_OUTPUT_TRANSFORM_FLIPPED_270)
|
transform > WL_OUTPUT_TRANSFORM_FLIPPED_270 ||
|
||||||
|
((crtc->all_transforms & (1 << transform)) == 0))
|
||||||
{
|
{
|
||||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||||
G_DBUS_ERROR_INVALID_ARGS,
|
G_DBUS_ERROR_INVALID_ARGS,
|
||||||
@@ -1037,7 +1059,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
|||||||
{
|
{
|
||||||
MetaOutput *output;
|
MetaOutput *output;
|
||||||
|
|
||||||
if (output_id < 0 || output_id >= manager->n_outputs)
|
if (output_id >= manager->n_outputs)
|
||||||
{
|
{
|
||||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||||
G_DBUS_ERROR_INVALID_ARGS,
|
G_DBUS_ERROR_INVALID_ARGS,
|
||||||
@@ -1094,7 +1116,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
|||||||
MetaOutputInfo *output_info;
|
MetaOutputInfo *output_info;
|
||||||
gboolean primary, presentation;
|
gboolean primary, presentation;
|
||||||
|
|
||||||
if (output_id < 0 || output_id >= manager->n_outputs)
|
if (output_id >= manager->n_outputs)
|
||||||
{
|
{
|
||||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||||
G_DBUS_ERROR_INVALID_ARGS,
|
G_DBUS_ERROR_INVALID_ARGS,
|
||||||
@@ -1187,7 +1209,7 @@ meta_monitor_manager_handle_change_backlight (MetaDBusDisplayConfig *skeleton,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (output_id < 0 || output_id >= manager->n_outputs)
|
if (output_id >= manager->n_outputs)
|
||||||
{
|
{
|
||||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||||
G_DBUS_ERROR_INVALID_ARGS,
|
G_DBUS_ERROR_INVALID_ARGS,
|
||||||
@@ -1215,7 +1237,7 @@ meta_monitor_manager_handle_change_backlight (MetaDBusDisplayConfig *skeleton,
|
|||||||
|
|
||||||
META_MONITOR_MANAGER_GET_CLASS (manager)->change_backlight (manager, output, value);
|
META_MONITOR_MANAGER_GET_CLASS (manager)->change_backlight (manager, output, value);
|
||||||
|
|
||||||
meta_dbus_display_config_complete_change_backlight (skeleton, invocation);
|
meta_dbus_display_config_complete_change_backlight (skeleton, invocation, output->backlight);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1243,7 +1265,7 @@ meta_monitor_manager_handle_get_crtc_gamma (MetaDBusDisplayConfig *skeleton,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (crtc_id < 0 || crtc_id >= manager->n_crtcs)
|
if (crtc_id >= manager->n_crtcs)
|
||||||
{
|
{
|
||||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||||
G_DBUS_ERROR_INVALID_ARGS,
|
G_DBUS_ERROR_INVALID_ARGS,
|
||||||
@@ -1305,7 +1327,7 @@ meta_monitor_manager_handle_set_crtc_gamma (MetaDBusDisplayConfig *skeleton,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (crtc_id < 0 || crtc_id >= manager->n_crtcs)
|
if (crtc_id >= manager->n_crtcs)
|
||||||
{
|
{
|
||||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||||
G_DBUS_ERROR_INVALID_ARGS,
|
G_DBUS_ERROR_INVALID_ARGS,
|
||||||
@@ -1351,8 +1373,7 @@ on_bus_acquired (GDBusConnection *connection,
|
|||||||
const char *name,
|
const char *name,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GTask *task = user_data;
|
MetaMonitorManager *manager = user_data;
|
||||||
MetaMonitorManager *manager = g_task_get_task_data (task);
|
|
||||||
|
|
||||||
g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (manager),
|
g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (manager),
|
||||||
connection,
|
connection,
|
||||||
@@ -1365,11 +1386,7 @@ on_name_acquired (GDBusConnection *connection,
|
|||||||
const char *name,
|
const char *name,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GTask *task = user_data;
|
|
||||||
|
|
||||||
meta_topic (META_DEBUG_DBUS, "Acquired name %s\n", name);
|
meta_topic (META_DEBUG_DBUS, "Acquired name %s\n", name);
|
||||||
|
|
||||||
g_task_return_boolean (task, TRUE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1380,14 +1397,9 @@ on_name_lost (GDBusConnection *connection,
|
|||||||
meta_topic (META_DEBUG_DBUS, "Lost or failed to acquire name %s\n", name);
|
meta_topic (META_DEBUG_DBUS, "Lost or failed to acquire name %s\n", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
meta_monitor_manager_init_dbus (MetaMonitorManager *manager,
|
initialize_dbus_interface (MetaMonitorManager *manager)
|
||||||
GAsyncReadyCallback callback,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
{
|
||||||
GTask *task = g_task_new (manager, NULL, callback, user_data);
|
|
||||||
g_task_set_task_data (task, g_object_ref (manager), g_object_unref);
|
|
||||||
|
|
||||||
manager->dbus_name_id = g_bus_own_name (G_BUS_TYPE_SESSION,
|
manager->dbus_name_id = g_bus_own_name (G_BUS_TYPE_SESSION,
|
||||||
"org.gnome.Mutter.DisplayConfig",
|
"org.gnome.Mutter.DisplayConfig",
|
||||||
G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
|
G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
|
||||||
@@ -1396,32 +1408,24 @@ meta_monitor_manager_init_dbus (MetaMonitorManager *manager,
|
|||||||
on_bus_acquired,
|
on_bus_acquired,
|
||||||
on_name_acquired,
|
on_name_acquired,
|
||||||
on_name_lost,
|
on_name_lost,
|
||||||
task,
|
g_object_ref (manager),
|
||||||
g_object_unref);
|
g_object_unref);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
static MetaMonitorManager *global_monitor_manager;
|
||||||
meta_monitor_manager_init_dbus_finish (MetaMonitorManager *manager,
|
|
||||||
GAsyncResult *result,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
return g_task_propagate_boolean (G_TASK (result), error);
|
|
||||||
}
|
|
||||||
|
|
||||||
static MetaMonitorManager *global_manager;
|
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_monitor_manager_initialize (void)
|
meta_monitor_manager_initialize (void)
|
||||||
{
|
{
|
||||||
global_manager = meta_monitor_manager_new ();
|
global_monitor_manager = meta_monitor_manager_new ();
|
||||||
}
|
}
|
||||||
|
|
||||||
MetaMonitorManager *
|
MetaMonitorManager *
|
||||||
meta_monitor_manager_get (void)
|
meta_monitor_manager_get (void)
|
||||||
{
|
{
|
||||||
g_assert (global_manager != NULL);
|
g_assert (global_monitor_manager != NULL);
|
||||||
|
|
||||||
return global_manager;
|
return global_monitor_manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
MetaMonitorInfo *
|
MetaMonitorInfo *
|
||||||
@@ -1481,8 +1485,8 @@ meta_monitor_manager_get_screen_limits (MetaMonitorManager *manager,
|
|||||||
*height = manager->max_screen_height;
|
*height = manager->max_screen_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager)
|
invalidate_logical_config (MetaMonitorManager *manager)
|
||||||
{
|
{
|
||||||
MetaMonitorInfo *old_monitor_infos;
|
MetaMonitorInfo *old_monitor_infos;
|
||||||
|
|
||||||
@@ -1493,7 +1497,7 @@ meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager)
|
|||||||
|
|
||||||
make_logical_config (manager);
|
make_logical_config (manager);
|
||||||
|
|
||||||
g_signal_emit (manager, signals[MONITORS_CHANGED], 0);
|
g_signal_emit_by_name (manager, "monitors-changed");
|
||||||
|
|
||||||
g_free (old_monitor_infos);
|
g_free (old_monitor_infos);
|
||||||
}
|
}
|
||||||
@@ -1506,7 +1510,7 @@ meta_monitor_manager_handle_xevent (MetaMonitorManager *manager,
|
|||||||
MetaOutput *old_outputs;
|
MetaOutput *old_outputs;
|
||||||
MetaCRTC *old_crtcs;
|
MetaCRTC *old_crtcs;
|
||||||
MetaMonitorMode *old_modes;
|
MetaMonitorMode *old_modes;
|
||||||
unsigned int n_old_outputs, n_old_modes;
|
int n_old_outputs;
|
||||||
gboolean changed;
|
gboolean changed;
|
||||||
|
|
||||||
klass = META_MONITOR_MANAGER_GET_CLASS (manager);
|
klass = META_MONITOR_MANAGER_GET_CLASS (manager);
|
||||||
@@ -1522,7 +1526,6 @@ meta_monitor_manager_handle_xevent (MetaMonitorManager *manager,
|
|||||||
old_outputs = manager->outputs;
|
old_outputs = manager->outputs;
|
||||||
n_old_outputs = manager->n_outputs;
|
n_old_outputs = manager->n_outputs;
|
||||||
old_modes = manager->modes;
|
old_modes = manager->modes;
|
||||||
n_old_modes = manager->n_modes;
|
|
||||||
old_crtcs = manager->crtcs;
|
old_crtcs = manager->crtcs;
|
||||||
|
|
||||||
read_current_config (manager);
|
read_current_config (manager);
|
||||||
@@ -1537,7 +1540,7 @@ meta_monitor_manager_handle_xevent (MetaMonitorManager *manager,
|
|||||||
*/
|
*/
|
||||||
if (meta_monitor_config_match_current (manager->config, manager))
|
if (meta_monitor_config_match_current (manager->config, manager))
|
||||||
{
|
{
|
||||||
meta_monitor_manager_rebuild_derived (manager);
|
invalidate_logical_config (manager);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1546,7 +1549,7 @@ meta_monitor_manager_handle_xevent (MetaMonitorManager *manager,
|
|||||||
}
|
}
|
||||||
|
|
||||||
free_output_array (old_outputs, n_old_outputs);
|
free_output_array (old_outputs, n_old_outputs);
|
||||||
free_mode_array (old_modes, n_old_modes);
|
g_free (old_modes);
|
||||||
g_free (old_crtcs);
|
g_free (old_crtcs);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@@ -247,12 +247,12 @@ void meta_screen_set_active_workspace_hint (MetaScreen *screen);
|
|||||||
|
|
||||||
Window meta_screen_create_guard_window (Display *xdisplay, MetaScreen *screen);
|
Window meta_screen_create_guard_window (Display *xdisplay, MetaScreen *screen);
|
||||||
|
|
||||||
|
gboolean meta_screen_handle_xevent (MetaScreen *screen,
|
||||||
|
XEvent *xevent);
|
||||||
|
|
||||||
int meta_screen_xinerama_index_to_monitor_index (MetaScreen *screen,
|
int meta_screen_xinerama_index_to_monitor_index (MetaScreen *screen,
|
||||||
int index);
|
int index);
|
||||||
int meta_screen_monitor_index_to_xinerama_index (MetaScreen *screen,
|
int meta_screen_monitor_index_to_xinerama_index (MetaScreen *screen,
|
||||||
int index);
|
int index);
|
||||||
|
|
||||||
gboolean meta_screen_handle_xevent (MetaScreen *screen,
|
|
||||||
XEvent *xevent);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -45,11 +45,8 @@
|
|||||||
#include <meta/compositor.h>
|
#include <meta/compositor.h>
|
||||||
#include "mutter-enum-types.h"
|
#include "mutter-enum-types.h"
|
||||||
#include "core.h"
|
#include "core.h"
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
#include "meta-wayland-private.h"
|
#include "meta-wayland-private.h"
|
||||||
#endif
|
|
||||||
#include "meta-cursor-tracker-private.h"
|
#include "meta-cursor-tracker-private.h"
|
||||||
#include "meta-idle-monitor-private.h"
|
|
||||||
|
|
||||||
#include <X11/extensions/Xinerama.h>
|
#include <X11/extensions/Xinerama.h>
|
||||||
|
|
||||||
@@ -677,10 +674,8 @@ meta_screen_new (MetaDisplay *display,
|
|||||||
screen->xscreen = ScreenOfDisplay (xdisplay, number);
|
screen->xscreen = ScreenOfDisplay (xdisplay, number);
|
||||||
screen->xroot = xroot;
|
screen->xroot = xroot;
|
||||||
screen->rect.x = screen->rect.y = 0;
|
screen->rect.x = screen->rect.y = 0;
|
||||||
|
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
if (!meta_is_wayland_compositor ())
|
if (!meta_is_wayland_compositor ())
|
||||||
#endif
|
|
||||||
meta_monitor_manager_initialize ();
|
meta_monitor_manager_initialize ();
|
||||||
|
|
||||||
manager = meta_monitor_manager_get ();
|
manager = meta_monitor_manager_get ();
|
||||||
@@ -691,12 +686,6 @@ meta_screen_new (MetaDisplay *display,
|
|||||||
&screen->rect.width,
|
&screen->rect.width,
|
||||||
&screen->rect.height);
|
&screen->rect.height);
|
||||||
|
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
if (!meta_is_wayland_compositor ())
|
|
||||||
#endif
|
|
||||||
meta_monitor_manager_init_dbus (manager, NULL, NULL);
|
|
||||||
meta_idle_monitor_init_dbus ();
|
|
||||||
|
|
||||||
screen->current_cursor = -1; /* invalid/unset */
|
screen->current_cursor = -1; /* invalid/unset */
|
||||||
screen->default_xvisual = DefaultVisualOfScreen (screen->xscreen);
|
screen->default_xvisual = DefaultVisualOfScreen (screen->xscreen);
|
||||||
screen->default_depth = DefaultDepthOfScreen (screen->xscreen);
|
screen->default_depth = DefaultDepthOfScreen (screen->xscreen);
|
||||||
@@ -722,8 +711,8 @@ meta_screen_new (MetaDisplay *display,
|
|||||||
screen->guard_window = None;
|
screen->guard_window = None;
|
||||||
|
|
||||||
reload_monitor_infos (screen);
|
reload_monitor_infos (screen);
|
||||||
|
|
||||||
meta_cursor_tracker_get_for_screen (screen);
|
meta_cursor_tracker_get_for_screen (screen);
|
||||||
meta_screen_set_cursor (screen, META_CURSOR_DEFAULT);
|
meta_screen_set_cursor (screen, META_CURSOR_DEFAULT);
|
||||||
|
|
||||||
/* Handle creating a no_focus_window for this screen */
|
/* Handle creating a no_focus_window for this screen */
|
||||||
@@ -2884,9 +2873,10 @@ on_monitors_changed (MetaMonitorManager *manager,
|
|||||||
&changes);
|
&changes);
|
||||||
}
|
}
|
||||||
|
|
||||||
meta_compositor_sync_screen_size (screen->display->compositor,
|
if (screen->display->compositor)
|
||||||
screen,
|
meta_compositor_sync_screen_size (screen->display->compositor,
|
||||||
screen->rect.width, screen->rect.height);
|
screen,
|
||||||
|
screen->rect.width, screen->rect.height);
|
||||||
|
|
||||||
/* Queue a resize on all the windows */
|
/* Queue a resize on all the windows */
|
||||||
meta_screen_foreach_window (screen, meta_screen_resize_func, 0);
|
meta_screen_foreach_window (screen, meta_screen_resize_func, 0);
|
||||||
|
@@ -44,9 +44,7 @@
|
|||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
#include "meta-wayland-private.h"
|
#include "meta-wayland-private.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
/* XXX: We should find a nicer approach to deal with the
|
/* XXX: We should find a nicer approach to deal with the
|
||||||
* circular dependency we have with the current headers
|
* circular dependency we have with the current headers
|
||||||
@@ -341,11 +339,6 @@ struct _MetaWindow
|
|||||||
guint using_net_wm_icon_name : 1; /* vs. plain wm_icon_name */
|
guint using_net_wm_icon_name : 1; /* vs. plain wm_icon_name */
|
||||||
guint using_net_wm_visible_icon_name : 1; /* tracked so we can clear it */
|
guint using_net_wm_visible_icon_name : 1; /* tracked so we can clear it */
|
||||||
|
|
||||||
/* has a bounding shape mask */
|
|
||||||
guint has_shape : 1;
|
|
||||||
/* has an input shape mask */
|
|
||||||
guint has_input_shape : 1;
|
|
||||||
|
|
||||||
/* icon props have changed */
|
/* icon props have changed */
|
||||||
guint need_reread_icon : 1;
|
guint need_reread_icon : 1;
|
||||||
|
|
||||||
@@ -367,9 +360,15 @@ struct _MetaWindow
|
|||||||
/* if non-NULL, the bounds of the window frame */
|
/* if non-NULL, the bounds of the window frame */
|
||||||
cairo_region_t *frame_bounds;
|
cairo_region_t *frame_bounds;
|
||||||
|
|
||||||
|
/* if non-NULL, the bounding shape region of the window */
|
||||||
|
cairo_region_t *shape_region;
|
||||||
|
|
||||||
/* if non-NULL, the opaque region _NET_WM_OPAQUE_REGION */
|
/* if non-NULL, the opaque region _NET_WM_OPAQUE_REGION */
|
||||||
cairo_region_t *opaque_region;
|
cairo_region_t *opaque_region;
|
||||||
|
|
||||||
|
/* the input shape region for picking */
|
||||||
|
cairo_region_t *input_region;
|
||||||
|
|
||||||
/* if TRUE, the we have the new form of sync request counter which
|
/* if TRUE, the we have the new form of sync request counter which
|
||||||
* also handles application frames */
|
* also handles application frames */
|
||||||
guint extended_sync_request_counter : 1;
|
guint extended_sync_request_counter : 1;
|
||||||
@@ -687,7 +686,6 @@ void meta_window_update_icon_now (MetaWindow *window);
|
|||||||
|
|
||||||
void meta_window_update_role (MetaWindow *window);
|
void meta_window_update_role (MetaWindow *window);
|
||||||
void meta_window_update_net_wm_type (MetaWindow *window);
|
void meta_window_update_net_wm_type (MetaWindow *window);
|
||||||
void meta_window_update_opaque_region (MetaWindow *window);
|
|
||||||
void meta_window_update_for_monitors_changed (MetaWindow *window);
|
void meta_window_update_for_monitors_changed (MetaWindow *window);
|
||||||
void meta_window_update_on_all_workspaces (MetaWindow *window);
|
void meta_window_update_on_all_workspaces (MetaWindow *window);
|
||||||
|
|
||||||
@@ -701,4 +699,16 @@ void meta_window_compute_tile_match (MetaWindow *window);
|
|||||||
|
|
||||||
gboolean meta_window_updates_are_frozen (MetaWindow *window);
|
gboolean meta_window_updates_are_frozen (MetaWindow *window);
|
||||||
|
|
||||||
|
void meta_window_set_opaque_region (MetaWindow *window,
|
||||||
|
cairo_region_t *region);
|
||||||
|
void meta_window_update_opaque_region_x11 (MetaWindow *window);
|
||||||
|
|
||||||
|
void meta_window_set_input_region (MetaWindow *window,
|
||||||
|
cairo_region_t *region);
|
||||||
|
void meta_window_update_input_region_x11 (MetaWindow *window);
|
||||||
|
|
||||||
|
void meta_window_set_shape_region (MetaWindow *window,
|
||||||
|
cairo_region_t *region);
|
||||||
|
void meta_window_update_shape_region_x11 (MetaWindow *window);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -565,7 +565,7 @@ reload_opaque_region (MetaWindow *window,
|
|||||||
MetaPropValue *value,
|
MetaPropValue *value,
|
||||||
gboolean initial)
|
gboolean initial)
|
||||||
{
|
{
|
||||||
meta_window_update_opaque_region (window);
|
meta_window_update_opaque_region_x11 (window);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@@ -62,9 +62,7 @@
|
|||||||
|
|
||||||
#include <X11/extensions/Xcomposite.h>
|
#include <X11/extensions/Xcomposite.h>
|
||||||
|
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
#include "meta-wayland-private.h"
|
#include "meta-wayland-private.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Windows that unmaximize to a size bigger than that fraction of the workarea
|
/* Windows that unmaximize to a size bigger than that fraction of the workarea
|
||||||
* will be scaled down to that size (while maintaining aspect ratio).
|
* will be scaled down to that size (while maintaining aspect ratio).
|
||||||
@@ -824,8 +822,6 @@ meta_window_new_shared (MetaDisplay *display,
|
|||||||
Window xwindow,
|
Window xwindow,
|
||||||
gboolean must_be_viewable,
|
gboolean must_be_viewable,
|
||||||
gulong existing_wm_state,
|
gulong existing_wm_state,
|
||||||
gboolean has_shape,
|
|
||||||
gboolean has_input_shape,
|
|
||||||
MetaCompEffect effect,
|
MetaCompEffect effect,
|
||||||
XWindowAttributes *attrs)
|
XWindowAttributes *attrs)
|
||||||
{
|
{
|
||||||
@@ -853,9 +849,7 @@ meta_window_new_shared (MetaDisplay *display,
|
|||||||
window->dialog_pid = -1;
|
window->dialog_pid = -1;
|
||||||
|
|
||||||
window->client_type = client_type;
|
window->client_type = client_type;
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
window->surface = surface;
|
window->surface = surface;
|
||||||
#endif
|
|
||||||
window->xwindow = xwindow;
|
window->xwindow = xwindow;
|
||||||
|
|
||||||
/* this is in window->screen->display, but that's too annoying to
|
/* this is in window->screen->display, but that's too annoying to
|
||||||
@@ -880,9 +874,6 @@ meta_window_new_shared (MetaDisplay *display,
|
|||||||
/* avoid tons of stack updates */
|
/* avoid tons of stack updates */
|
||||||
meta_stack_freeze (window->screen->stack);
|
meta_stack_freeze (window->screen->stack);
|
||||||
|
|
||||||
window->has_shape = has_shape;
|
|
||||||
window->has_input_shape = has_input_shape;
|
|
||||||
|
|
||||||
window->rect.x = attrs->x;
|
window->rect.x = attrs->x;
|
||||||
window->rect.y = attrs->y;
|
window->rect.y = attrs->y;
|
||||||
window->rect.width = attrs->width;
|
window->rect.width = attrs->width;
|
||||||
@@ -1063,6 +1054,8 @@ meta_window_new_shared (MetaDisplay *display,
|
|||||||
}
|
}
|
||||||
|
|
||||||
meta_display_register_x_window (display, &window->xwindow, window);
|
meta_display_register_x_window (display, &window->xwindow, window);
|
||||||
|
meta_window_update_shape_region_x11 (window);
|
||||||
|
meta_window_update_input_region_x11 (window);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* assign the window to its group, or create a new group if needed
|
/* assign the window to its group, or create a new group if needed
|
||||||
@@ -1375,7 +1368,6 @@ display_notify_window (MetaDisplay *display, MetaWindow *window)
|
|||||||
g_signal_emit_by_name (window->display, "window-marked-urgent", window);
|
g_signal_emit_by_name (window->display, "window-marked-urgent", window);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
MetaWindow *
|
MetaWindow *
|
||||||
meta_window_new_for_wayland (MetaDisplay *display,
|
meta_window_new_for_wayland (MetaDisplay *display,
|
||||||
int width,
|
int width,
|
||||||
@@ -1430,8 +1422,6 @@ meta_window_new_for_wayland (MetaDisplay *display,
|
|||||||
None,
|
None,
|
||||||
TRUE,
|
TRUE,
|
||||||
WithdrawnState,
|
WithdrawnState,
|
||||||
FALSE, /* has shape */
|
|
||||||
FALSE, /* has input shape */
|
|
||||||
META_COMP_EFFECT_NONE,
|
META_COMP_EFFECT_NONE,
|
||||||
&attrs);
|
&attrs);
|
||||||
|
|
||||||
@@ -1447,7 +1437,6 @@ meta_window_new_for_wayland (MetaDisplay *display,
|
|||||||
|
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
MetaWindow*
|
MetaWindow*
|
||||||
meta_window_new_with_attrs (MetaDisplay *display,
|
meta_window_new_with_attrs (MetaDisplay *display,
|
||||||
@@ -1461,8 +1450,6 @@ meta_window_new_with_attrs (MetaDisplay *display,
|
|||||||
gulong existing_wm_state;
|
gulong existing_wm_state;
|
||||||
MetaWindow *window;
|
MetaWindow *window;
|
||||||
gulong event_mask;
|
gulong event_mask;
|
||||||
gboolean has_shape = FALSE;
|
|
||||||
gboolean has_input_shape = FALSE;
|
|
||||||
|
|
||||||
meta_verbose ("Attempting to manage 0x%lx\n", xwindow);
|
meta_verbose ("Attempting to manage 0x%lx\n", xwindow);
|
||||||
|
|
||||||
@@ -1582,53 +1569,6 @@ meta_window_new_with_attrs (MetaDisplay *display,
|
|||||||
XISelectEvents (display->xdisplay, xwindow, &mask, 1);
|
XISelectEvents (display->xdisplay, xwindow, &mask, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_SHAPE
|
|
||||||
if (META_DISPLAY_HAS_SHAPE (display))
|
|
||||||
{
|
|
||||||
int x_bounding, y_bounding, x_clip, y_clip;
|
|
||||||
unsigned w_bounding, h_bounding, w_clip, h_clip;
|
|
||||||
int bounding_shaped, clip_shaped;
|
|
||||||
XRectangle *input_rectangles;
|
|
||||||
int n_rects, ordering;
|
|
||||||
|
|
||||||
XShapeSelectInput (display->xdisplay, xwindow, ShapeNotifyMask);
|
|
||||||
|
|
||||||
XShapeQueryExtents (display->xdisplay, xwindow,
|
|
||||||
&bounding_shaped, &x_bounding, &y_bounding,
|
|
||||||
&w_bounding, &h_bounding,
|
|
||||||
&clip_shaped, &x_clip, &y_clip,
|
|
||||||
&w_clip, &h_clip);
|
|
||||||
|
|
||||||
has_shape = bounding_shaped != FALSE;
|
|
||||||
|
|
||||||
/* XXX: The x shape extension doesn't provide a way to only test if an
|
|
||||||
* input shape has been specified, so we have to query and throw away the
|
|
||||||
* rectangles. */
|
|
||||||
meta_error_trap_push (display);
|
|
||||||
input_rectangles = XShapeGetRectangles (display->xdisplay, xwindow,
|
|
||||||
ShapeInput, &n_rects, &ordering);
|
|
||||||
meta_error_trap_pop (display);
|
|
||||||
if (input_rectangles)
|
|
||||||
{
|
|
||||||
if (n_rects > 1 ||
|
|
||||||
(n_rects == 1 &&
|
|
||||||
(input_rectangles[0].x != x_bounding ||
|
|
||||||
input_rectangles[1].y != y_bounding ||
|
|
||||||
input_rectangles[2].width != w_bounding ||
|
|
||||||
input_rectangles[3].height != h_bounding)))
|
|
||||||
{
|
|
||||||
has_input_shape = TRUE;
|
|
||||||
}
|
|
||||||
XFree (input_rectangles);
|
|
||||||
}
|
|
||||||
|
|
||||||
meta_topic (META_DEBUG_SHAPES,
|
|
||||||
"Window has_shape = %d extents %d,%d %u x %u\n",
|
|
||||||
has_shape, x_bounding, y_bounding,
|
|
||||||
w_bounding, h_bounding);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Get rid of any borders */
|
/* Get rid of any borders */
|
||||||
if (attrs->border_width != 0)
|
if (attrs->border_width != 0)
|
||||||
XSetWindowBorderWidth (display->xdisplay, xwindow, 0);
|
XSetWindowBorderWidth (display->xdisplay, xwindow, 0);
|
||||||
@@ -1662,8 +1602,6 @@ meta_window_new_with_attrs (MetaDisplay *display,
|
|||||||
xwindow,
|
xwindow,
|
||||||
must_be_viewable,
|
must_be_viewable,
|
||||||
existing_wm_state,
|
existing_wm_state,
|
||||||
has_shape,
|
|
||||||
has_input_shape,
|
|
||||||
effect,
|
effect,
|
||||||
attrs);
|
attrs);
|
||||||
|
|
||||||
@@ -2107,10 +2045,8 @@ meta_window_unmanage (MetaWindow *window,
|
|||||||
meta_error_trap_pop (window->display);
|
meta_error_trap_pop (window->display);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
if (window->surface)
|
if (window->surface)
|
||||||
meta_wayland_surface_free (window->surface);
|
meta_wayland_surface_free (window->surface);
|
||||||
#endif
|
|
||||||
|
|
||||||
meta_prefs_remove_listener (prefs_changed_callback, window);
|
meta_prefs_remove_listener (prefs_changed_callback, window);
|
||||||
|
|
||||||
@@ -6012,7 +5948,7 @@ meta_window_get_outer_rect (const MetaWindow *window,
|
|||||||
|
|
||||||
if (window->has_custom_frame_extents)
|
if (window->has_custom_frame_extents)
|
||||||
{
|
{
|
||||||
GtkBorder *extents = &window->custom_frame_extents;
|
const GtkBorder *extents = &window->custom_frame_extents;
|
||||||
rect->x += extents->left;
|
rect->x += extents->left;
|
||||||
rect->y += extents->top;
|
rect->y += extents->top;
|
||||||
rect->width -= extents->left + extents->right;
|
rect->width -= extents->left + extents->right;
|
||||||
@@ -7399,9 +7335,6 @@ void
|
|||||||
meta_window_set_focused_internal (MetaWindow *window,
|
meta_window_set_focused_internal (MetaWindow *window,
|
||||||
gboolean focused)
|
gboolean focused)
|
||||||
{
|
{
|
||||||
if (window->unmanaging)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (focused)
|
if (focused)
|
||||||
{
|
{
|
||||||
window->has_focus = TRUE;
|
window->has_focus = TRUE;
|
||||||
@@ -7821,14 +7754,25 @@ meta_window_update_net_wm_type (MetaWindow *window)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_window_update_opaque_region (MetaWindow *window)
|
meta_window_set_opaque_region (MetaWindow *window,
|
||||||
|
cairo_region_t *region)
|
||||||
|
{
|
||||||
|
g_clear_pointer (&window->opaque_region, cairo_region_destroy);
|
||||||
|
|
||||||
|
if (region != NULL)
|
||||||
|
window->opaque_region = cairo_region_reference (region);
|
||||||
|
|
||||||
|
if (window->display->compositor)
|
||||||
|
meta_compositor_window_shape_changed (window->display->compositor, window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_window_update_opaque_region_x11 (MetaWindow *window)
|
||||||
{
|
{
|
||||||
cairo_region_t *opaque_region = NULL;
|
cairo_region_t *opaque_region = NULL;
|
||||||
gulong *region = NULL;
|
gulong *region = NULL;
|
||||||
int nitems;
|
int nitems;
|
||||||
|
|
||||||
g_clear_pointer (&window->opaque_region, cairo_region_destroy);
|
|
||||||
|
|
||||||
if (meta_prop_get_cardinal_list (window->display,
|
if (meta_prop_get_cardinal_list (window->display,
|
||||||
window->xwindow,
|
window->xwindow,
|
||||||
window->display->atom__NET_WM_OPAQUE_REGION,
|
window->display->atom__NET_WM_OPAQUE_REGION,
|
||||||
@@ -7871,11 +7815,191 @@ meta_window_update_opaque_region (MetaWindow *window)
|
|||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
window->opaque_region = opaque_region;
|
|
||||||
meta_XFree (region);
|
meta_XFree (region);
|
||||||
|
|
||||||
|
meta_window_set_opaque_region (window, opaque_region);
|
||||||
|
cairo_region_destroy (opaque_region);
|
||||||
|
}
|
||||||
|
|
||||||
|
static cairo_region_t *
|
||||||
|
region_create_from_x_rectangles (const XRectangle *rects,
|
||||||
|
int n_rects)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
cairo_rectangle_int_t *cairo_rects = g_newa (cairo_rectangle_int_t, n_rects);
|
||||||
|
|
||||||
|
for (i = 0; i < n_rects; i ++)
|
||||||
|
{
|
||||||
|
cairo_rects[i].x = rects[i].x;
|
||||||
|
cairo_rects[i].y = rects[i].y;
|
||||||
|
cairo_rects[i].width = rects[i].width;
|
||||||
|
cairo_rects[i].height = rects[i].height;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cairo_region_create_rectangles (cairo_rects, n_rects);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_window_set_input_region (MetaWindow *window,
|
||||||
|
cairo_region_t *region)
|
||||||
|
{
|
||||||
|
g_clear_pointer (&window->input_region, cairo_region_destroy);
|
||||||
|
|
||||||
|
if (region != NULL)
|
||||||
|
window->input_region = cairo_region_reference (region);
|
||||||
|
|
||||||
if (window->display->compositor)
|
if (window->display->compositor)
|
||||||
meta_compositor_window_x11_shape_changed (window->display->compositor, window);
|
meta_compositor_window_shape_changed (window->display->compositor, window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_window_update_input_region_x11 (MetaWindow *window)
|
||||||
|
{
|
||||||
|
cairo_region_t *region = NULL;
|
||||||
|
|
||||||
|
#ifdef HAVE_SHAPE
|
||||||
|
if (META_DISPLAY_HAS_SHAPE (window->display))
|
||||||
|
{
|
||||||
|
/* Translate the set of XShape rectangles that we
|
||||||
|
* get from the X server to a cairo_region. */
|
||||||
|
XRectangle *rects = NULL;
|
||||||
|
int n_rects, ordering;
|
||||||
|
|
||||||
|
int x_bounding, y_bounding, x_clip, y_clip;
|
||||||
|
unsigned w_bounding, h_bounding, w_clip, h_clip;
|
||||||
|
int bounding_shaped, clip_shaped;
|
||||||
|
|
||||||
|
meta_error_trap_push (window->display);
|
||||||
|
XShapeQueryExtents (window->display->xdisplay, window->xwindow,
|
||||||
|
&bounding_shaped, &x_bounding, &y_bounding,
|
||||||
|
&w_bounding, &h_bounding,
|
||||||
|
&clip_shaped, &x_clip, &y_clip,
|
||||||
|
&w_clip, &h_clip);
|
||||||
|
|
||||||
|
rects = XShapeGetRectangles (window->display->xdisplay,
|
||||||
|
window->xwindow,
|
||||||
|
ShapeInput,
|
||||||
|
&n_rects,
|
||||||
|
&ordering);
|
||||||
|
meta_error_trap_pop (window->display);
|
||||||
|
|
||||||
|
/* XXX: The x shape extension doesn't provide a way to only test if an
|
||||||
|
* input shape has been specified, so we have to query and throw away the
|
||||||
|
* rectangles. */
|
||||||
|
if (rects)
|
||||||
|
{
|
||||||
|
if (n_rects > 1 ||
|
||||||
|
(n_rects == 1 &&
|
||||||
|
(rects[0].x != x_bounding ||
|
||||||
|
rects[1].y != y_bounding ||
|
||||||
|
rects[2].width != w_bounding ||
|
||||||
|
rects[3].height != h_bounding)))
|
||||||
|
region = region_create_from_x_rectangles (rects, n_rects);
|
||||||
|
|
||||||
|
XFree (rects);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* HAVE_SHAPE */
|
||||||
|
|
||||||
|
if (region != NULL)
|
||||||
|
{
|
||||||
|
cairo_rectangle_int_t client_area;
|
||||||
|
|
||||||
|
client_area.x = 0;
|
||||||
|
client_area.y = 0;
|
||||||
|
client_area.width = window->rect.width;
|
||||||
|
client_area.height = window->rect.height;
|
||||||
|
|
||||||
|
/* The shape we get back from the client may have coordinates
|
||||||
|
* outside of the frame. The X SHAPE Extension requires that
|
||||||
|
* the overall shape the client provides never exceeds the
|
||||||
|
* "bounding rectangle" of the window -- the shape that the
|
||||||
|
* window would have gotten if it was unshaped. In our case,
|
||||||
|
* this is simply the client area.
|
||||||
|
*/
|
||||||
|
cairo_region_intersect_rectangle (region, &client_area);
|
||||||
|
}
|
||||||
|
|
||||||
|
meta_window_set_input_region (window, region);
|
||||||
|
cairo_region_destroy (region);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_window_set_shape_region (MetaWindow *window,
|
||||||
|
cairo_region_t *region)
|
||||||
|
{
|
||||||
|
g_clear_pointer (&window->shape_region, cairo_region_destroy);
|
||||||
|
|
||||||
|
if (region != NULL)
|
||||||
|
window->shape_region = cairo_region_reference (region);
|
||||||
|
|
||||||
|
if (window->display->compositor)
|
||||||
|
meta_compositor_window_shape_changed (window->display->compositor, window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_window_update_shape_region_x11 (MetaWindow *window)
|
||||||
|
{
|
||||||
|
cairo_region_t *region = NULL;
|
||||||
|
|
||||||
|
#ifdef HAVE_SHAPE
|
||||||
|
if (META_DISPLAY_HAS_SHAPE (window->display))
|
||||||
|
{
|
||||||
|
/* Translate the set of XShape rectangles that we
|
||||||
|
* get from the X server to a cairo_region. */
|
||||||
|
XRectangle *rects = NULL;
|
||||||
|
int n_rects, ordering;
|
||||||
|
|
||||||
|
int x_bounding, y_bounding, x_clip, y_clip;
|
||||||
|
unsigned w_bounding, h_bounding, w_clip, h_clip;
|
||||||
|
int bounding_shaped, clip_shaped;
|
||||||
|
|
||||||
|
meta_error_trap_push (window->display);
|
||||||
|
XShapeQueryExtents (window->display->xdisplay, window->xwindow,
|
||||||
|
&bounding_shaped, &x_bounding, &y_bounding,
|
||||||
|
&w_bounding, &h_bounding,
|
||||||
|
&clip_shaped, &x_clip, &y_clip,
|
||||||
|
&w_clip, &h_clip);
|
||||||
|
|
||||||
|
if (bounding_shaped)
|
||||||
|
{
|
||||||
|
rects = XShapeGetRectangles (window->display->xdisplay,
|
||||||
|
window->xwindow,
|
||||||
|
ShapeBounding,
|
||||||
|
&n_rects,
|
||||||
|
&ordering);
|
||||||
|
}
|
||||||
|
meta_error_trap_pop (window->display);
|
||||||
|
|
||||||
|
if (rects)
|
||||||
|
{
|
||||||
|
region = region_create_from_x_rectangles (rects, n_rects);
|
||||||
|
XFree (rects);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* HAVE_SHAPE */
|
||||||
|
|
||||||
|
if (region != NULL)
|
||||||
|
{
|
||||||
|
cairo_rectangle_int_t client_area;
|
||||||
|
|
||||||
|
client_area.x = 0;
|
||||||
|
client_area.y = 0;
|
||||||
|
client_area.width = window->rect.width;
|
||||||
|
client_area.height = window->rect.height;
|
||||||
|
|
||||||
|
/* The shape we get back from the client may have coordinates
|
||||||
|
* outside of the frame. The X SHAPE Extension requires that
|
||||||
|
* the overall shape the client provides never exceeds the
|
||||||
|
* "bounding rectangle" of the window -- the shape that the
|
||||||
|
* window would have gotten if it was unshaped. In our case,
|
||||||
|
* this is simply the client area.
|
||||||
|
*/
|
||||||
|
cairo_region_intersect_rectangle (region, &client_area);
|
||||||
|
}
|
||||||
|
|
||||||
|
meta_window_set_shape_region (window, region);
|
||||||
|
cairo_region_destroy (region);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -8579,10 +8703,13 @@ recalc_window_features (MetaWindow *window)
|
|||||||
|
|
||||||
case META_WINDOW_DIALOG:
|
case META_WINDOW_DIALOG:
|
||||||
case META_WINDOW_MODAL_DIALOG:
|
case META_WINDOW_MODAL_DIALOG:
|
||||||
/* only skip taskbar if we have a real transient parent */
|
/* only skip taskbar if we have a real transient parent
|
||||||
|
(and ignore the application hints) */
|
||||||
if (window->xtransient_for != None &&
|
if (window->xtransient_for != None &&
|
||||||
window->xtransient_for != window->screen->xroot)
|
window->xtransient_for != window->screen->xroot)
|
||||||
window->skip_taskbar = TRUE;
|
window->skip_taskbar = TRUE;
|
||||||
|
else
|
||||||
|
window->skip_taskbar = FALSE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case META_WINDOW_NORMAL:
|
case META_WINDOW_NORMAL:
|
||||||
|
35
src/idle-monitor.xml
Normal file
35
src/idle-monitor.xml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<!DOCTYPE node PUBLIC
|
||||||
|
'-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'
|
||||||
|
'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>
|
||||||
|
<node>
|
||||||
|
<!--
|
||||||
|
org.gnome.Mutter.IdleMonitor:
|
||||||
|
@short_description: idle monitor interface
|
||||||
|
|
||||||
|
This interface is used by gnome-desktop to implement
|
||||||
|
user activity monitoring.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<interface name="org.gnome.Mutter.IdleMonitor">
|
||||||
|
<method name="GetIdletime">
|
||||||
|
<arg name="idletime" direction="out" type="t"/>
|
||||||
|
</method>
|
||||||
|
|
||||||
|
<method name="AddIdleWatch">
|
||||||
|
<arg name="interval" direction="in" type="t" />
|
||||||
|
<arg name="id" direction="out" type="u" />
|
||||||
|
</method>
|
||||||
|
|
||||||
|
<method name="AddUserActiveWatch">
|
||||||
|
<arg name="id" direction="out" type="u" />
|
||||||
|
</method>
|
||||||
|
|
||||||
|
<method name="RemoveWatch">
|
||||||
|
<arg name="id" direction="in" type="u" />
|
||||||
|
</method>
|
||||||
|
|
||||||
|
<signal name="WatchFired">
|
||||||
|
<arg name="id" direction="out" type="u" />
|
||||||
|
</signal>
|
||||||
|
</interface>
|
||||||
|
</node>
|
18
src/libmutter-wayland.pc.in
Normal file
18
src/libmutter-wayland.pc.in
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
prefix=@prefix@
|
||||||
|
exec_prefix=@exec_prefix@
|
||||||
|
libdir=@libdir@
|
||||||
|
includedir=@includedir@
|
||||||
|
girdir=@libdir@/mutter-wayland
|
||||||
|
typelibdir=@libdir@/mutter-wayland
|
||||||
|
|
||||||
|
mutter_major_version=@MUTTER_MAJOR_VERSION@
|
||||||
|
mutter_minor_version=@MUTTER_MINOR_VERSION@
|
||||||
|
mutter_micro_version=@MUTTER_MICRO_VERSION@
|
||||||
|
mutter_plugin_api_version=@MUTTER_PLUGIN_API_VERSION@
|
||||||
|
|
||||||
|
Name: libmutter-wayland
|
||||||
|
Description: Mutter window manager library (Wayland branch)
|
||||||
|
Requires: gsettings-desktop-schemas gtk+-3.0 @CLUTTER_PACKAGE@ x11 wayland-server
|
||||||
|
Version: @VERSION@
|
||||||
|
Libs: -L${libdir} -lmutter-wayland
|
||||||
|
Cflags: -I${includedir}/mutter-wayland -DMUTTER_MAJOR_VERSION=${mutter_major_version} -DMUTTER_MINOR_VERSION=${mutter_minor_version} -DMUTTER_MICRO_VERSION=${mutter_micro_version} -DMUTTER_PLUGIN_API_VERSION=${mutter_plugin_api_version}
|
@@ -1,18 +0,0 @@
|
|||||||
prefix=@prefix@
|
|
||||||
exec_prefix=@exec_prefix@
|
|
||||||
libdir=@libdir@
|
|
||||||
includedir=@includedir@
|
|
||||||
girdir=@libdir@/mutter
|
|
||||||
typelibdir=@libdir@/mutter
|
|
||||||
|
|
||||||
mutter_major_version=@MUTTER_MAJOR_VERSION@
|
|
||||||
mutter_minor_version=@MUTTER_MINOR_VERSION@
|
|
||||||
mutter_micro_version=@MUTTER_MICRO_VERSION@
|
|
||||||
mutter_plugin_api_version=@MUTTER_PLUGIN_API_VERSION@
|
|
||||||
|
|
||||||
Name: libmutter
|
|
||||||
Description: Mutter window manager library
|
|
||||||
Requires: gsettings-desktop-schemas gtk+-3.0 @CLUTTER_PACKAGE@ x11
|
|
||||||
Version: @VERSION@
|
|
||||||
Libs: -L${libdir} -lmutter
|
|
||||||
Cflags: -I${includedir}/mutter -DMUTTER_MAJOR_VERSION=${mutter_major_version} -DMUTTER_MINOR_VERSION=${mutter_minor_version} -DMUTTER_MICRO_VERSION=${mutter_micro_version} -DMUTTER_PLUGIN_API_VERSION=${mutter_plugin_api_version}
|
|
@@ -64,8 +64,8 @@ void meta_compositor_manage_screen (MetaCompositor *compositor,
|
|||||||
void meta_compositor_unmanage_screen (MetaCompositor *compositor,
|
void meta_compositor_unmanage_screen (MetaCompositor *compositor,
|
||||||
MetaScreen *screen);
|
MetaScreen *screen);
|
||||||
|
|
||||||
void meta_compositor_window_x11_shape_changed (MetaCompositor *compositor,
|
void meta_compositor_window_shape_changed (MetaCompositor *compositor,
|
||||||
MetaWindow *window);
|
MetaWindow *window);
|
||||||
|
|
||||||
gboolean meta_compositor_process_event (MetaCompositor *compositor,
|
gboolean meta_compositor_process_event (MetaCompositor *compositor,
|
||||||
XEvent *event,
|
XEvent *event,
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
#include <meta/types.h>
|
#include <meta/types.h>
|
||||||
#include <meta/workspace.h>
|
#include <meta/workspace.h>
|
||||||
|
#include <cogl/cogl.h>
|
||||||
|
|
||||||
#define META_TYPE_CURSOR_TRACKER (meta_cursor_tracker_get_type ())
|
#define META_TYPE_CURSOR_TRACKER (meta_cursor_tracker_get_type ())
|
||||||
#define META_CURSOR_TRACKER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CURSOR_TRACKER, MetaCursorTracker))
|
#define META_CURSOR_TRACKER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CURSOR_TRACKER, MetaCursorTracker))
|
||||||
|
@@ -57,6 +57,6 @@ guint meta_idle_monitor_add_user_active_watch (MetaIdleMonitor
|
|||||||
|
|
||||||
void meta_idle_monitor_remove_watch (MetaIdleMonitor *monitor,
|
void meta_idle_monitor_remove_watch (MetaIdleMonitor *monitor,
|
||||||
guint id);
|
guint id);
|
||||||
guint64 meta_idle_monitor_get_idletime (MetaIdleMonitor *monitor);
|
gint64 meta_idle_monitor_get_idletime (MetaIdleMonitor *monitor);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -29,11 +29,6 @@
|
|||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
|
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
#include <wayland-server.h>
|
|
||||||
#include "meta-wayland-private.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
#define META_TYPE_SHAPED_TEXTURE (meta_shaped_texture_get_type())
|
#define META_TYPE_SHAPED_TEXTURE (meta_shaped_texture_get_type())
|
||||||
@@ -69,14 +64,6 @@ struct _MetaShapedTexture
|
|||||||
|
|
||||||
GType meta_shaped_texture_get_type (void) G_GNUC_CONST;
|
GType meta_shaped_texture_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
ClutterActor *meta_shaped_texture_new_with_xwindow (Window xwindow);
|
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
ClutterActor *meta_shaped_texture_new_with_wayland_surface (MetaWaylandSurface *surface);
|
|
||||||
void meta_shaped_texture_set_wayland_surface (MetaShapedTexture *stex,
|
|
||||||
MetaWaylandSurface *surface);
|
|
||||||
MetaWaylandSurface *meta_shaped_texture_get_wayland_surface (MetaShapedTexture *stex);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
|
void meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
|
||||||
gboolean create_mipmaps);
|
gboolean create_mipmaps);
|
||||||
|
|
||||||
@@ -86,13 +73,6 @@ void meta_shaped_texture_update_area (MetaShapedTexture *stex,
|
|||||||
int width,
|
int width,
|
||||||
int height);
|
int height);
|
||||||
|
|
||||||
void meta_shaped_texture_set_pixmap (MetaShapedTexture *stex,
|
|
||||||
Pixmap pixmap);
|
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
void meta_shaped_texture_attach_wayland_buffer (MetaShapedTexture *stex,
|
|
||||||
MetaWaylandBuffer *buffer);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CoglTexture * meta_shaped_texture_get_texture (MetaShapedTexture *stex);
|
CoglTexture * meta_shaped_texture_get_texture (MetaShapedTexture *stex);
|
||||||
|
|
||||||
void meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex,
|
void meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex,
|
||||||
@@ -104,6 +84,9 @@ void meta_shaped_texture_set_input_shape_region (MetaShapedTexture *stex,
|
|||||||
void meta_shaped_texture_set_clip_region (MetaShapedTexture *stex,
|
void meta_shaped_texture_set_clip_region (MetaShapedTexture *stex,
|
||||||
cairo_region_t *clip_region);
|
cairo_region_t *clip_region);
|
||||||
|
|
||||||
|
void meta_shaped_texture_set_opaque_region (MetaShapedTexture *stex,
|
||||||
|
cairo_region_t *opaque_region);
|
||||||
|
|
||||||
cairo_surface_t * meta_shaped_texture_get_image (MetaShapedTexture *stex,
|
cairo_surface_t * meta_shaped_texture_get_image (MetaShapedTexture *stex,
|
||||||
cairo_rectangle_int_t *clip);
|
cairo_rectangle_int_t *clip);
|
||||||
|
|
||||||
|
@@ -1,17 +0,0 @@
|
|||||||
prefix=@prefix@
|
|
||||||
exec_prefix=@exec_prefix@
|
|
||||||
libdir=@libdir@
|
|
||||||
includedir=@includedir@
|
|
||||||
plugindir=@MUTTER_PLUGIN_DIR@
|
|
||||||
libgnome_serverdir=@libexecdir@
|
|
||||||
mutter_major_version=@MUTTER_MAJOR_VERSION@
|
|
||||||
mutter_minor_version=@MUTTER_MINOR_VERSION@
|
|
||||||
mutter_micro_version=@MUTTER_MICRO_VERSION@
|
|
||||||
mutter_plugin_api_version=@MUTTER_PLUGIN_API_VERSION@
|
|
||||||
|
|
||||||
Name: mutter-plugins
|
|
||||||
Description: Dev parameters for mutter plugins
|
|
||||||
Requires: @CLUTTER_PACKAGE@
|
|
||||||
Version: @VERSION@
|
|
||||||
Libs: @CLUTTER_LIBS@
|
|
||||||
Cflags: @CLUTTER_CFLAGS@ -DWITH_CLUTTER -I${includedir}/mutter/mutter-private -DMUTTER_MAJOR_VERSION=${mutter_major_version} -DMUTTER_MINOR_VERSION=${mutter_minor_version} -DMUTTER_MICRO_VERSION=${mutter_micro_version} -DMUTTER_PLUGIN_API_VERSION=${mutter_plugin_api_version} -DMUTTER_PLUGIN_DIR=\"${plugindir}\"
|
|
@@ -1,7 +1,7 @@
|
|||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
Type=Application
|
Type=Application
|
||||||
_Name=Mutter
|
_Name=Mutter (wayland compositor)
|
||||||
Exec=mutter
|
Exec=mutter-launch -- mutter --nested
|
||||||
NoDisplay=true
|
NoDisplay=true
|
||||||
# name of loadable control center module
|
# name of loadable control center module
|
||||||
X-GNOME-WMSettingsModule=metacity
|
X-GNOME-WMSettingsModule=metacity
|
||||||
@@ -12,6 +12,5 @@ X-GnomeWMSettingsLibrary=metacity
|
|||||||
X-GNOME-Bugzilla-Bugzilla=GNOME
|
X-GNOME-Bugzilla-Bugzilla=GNOME
|
||||||
X-GNOME-Bugzilla-Product=mutter
|
X-GNOME-Bugzilla-Product=mutter
|
||||||
X-GNOME-Bugzilla-Component=general
|
X-GNOME-Bugzilla-Component=general
|
||||||
X-GNOME-Autostart-Phase=WindowManager
|
X-GNOME-Autostart-Phase=DisplayServer
|
||||||
X-GNOME-Provides=windowmanager
|
|
||||||
X-GNOME-Autostart-Notify=true
|
X-GNOME-Autostart-Notify=true
|
@@ -1,20 +0,0 @@
|
|||||||
[Desktop Entry]
|
|
||||||
Type=Application
|
|
||||||
_Name=Mutter
|
|
||||||
Exec=mutter
|
|
||||||
# name of loadable control center module
|
|
||||||
X-GNOME-WMSettingsModule=metacity
|
|
||||||
# name we put on the WM spec check window
|
|
||||||
X-GNOME-WMName=Mutter
|
|
||||||
# back compat only
|
|
||||||
X-GnomeWMSettingsLibrary=metacity
|
|
||||||
X-GNOME-Bugzilla-Bugzilla=GNOME
|
|
||||||
X-GNOME-Bugzilla-Product=mutter
|
|
||||||
X-GNOME-Bugzilla-Component=general
|
|
||||||
X-GNOME-Autostart-Phase=WindowManager
|
|
||||||
X-GNOME-Provides=windowmanager
|
|
||||||
X-GNOME-Autostart-Notify=true
|
|
||||||
|
|
||||||
[Window Manager]
|
|
||||||
SessionManaged=true
|
|
||||||
|
|
@@ -116,34 +116,5 @@
|
|||||||
<_summary>Cancel tab popup</_summary>
|
<_summary>Cancel tab popup</_summary>
|
||||||
</key>
|
</key>
|
||||||
|
|
||||||
<key name="switch-to-session-1" type="as">
|
|
||||||
<default><![CDATA[['<Primary><Alt>F1']]]></default>
|
|
||||||
<_summary>Switch to VT 1</_summary>
|
|
||||||
</key>
|
|
||||||
<key name="switch-to-session-2" type="as">
|
|
||||||
<default><![CDATA[['<Primary><Alt>F2']]]></default>
|
|
||||||
<_summary>Switch to VT 2</_summary>
|
|
||||||
</key>
|
|
||||||
<key name="switch-to-session-3" type="as">
|
|
||||||
<default><![CDATA[['<Primary><Alt>F3']]]></default>
|
|
||||||
<_summary>Switch to VT 3</_summary>
|
|
||||||
</key>
|
|
||||||
<key name="switch-to-session-4" type="as">
|
|
||||||
<default><![CDATA[['<Primary><Alt>F4']]]></default>
|
|
||||||
<_summary>Switch to VT 4</_summary>
|
|
||||||
</key>
|
|
||||||
<key name="switch-to-session-5" type="as">
|
|
||||||
<default><![CDATA[['<Primary><Alt>F5']]]></default>
|
|
||||||
<_summary>Switch to VT 5</_summary>
|
|
||||||
</key>
|
|
||||||
<key name="switch-to-session-6" type="as">
|
|
||||||
<default><![CDATA[['<Primary><Alt>F6']]]></default>
|
|
||||||
<_summary>Switch to VT 6</_summary>
|
|
||||||
</key>
|
|
||||||
<key name="switch-to-session-7" type="as">
|
|
||||||
<default><![CDATA[['<Primary><Alt>F7']]]></default>
|
|
||||||
<_summary>Switch to VT 7</_summary>
|
|
||||||
</key>
|
|
||||||
|
|
||||||
</schema>
|
</schema>
|
||||||
</schemalist>
|
</schemalist>
|
||||||
|
@@ -56,6 +56,8 @@ struct _MetaUI
|
|||||||
void
|
void
|
||||||
meta_ui_init (void)
|
meta_ui_init (void)
|
||||||
{
|
{
|
||||||
|
gdk_set_allowed_backends ("x11");
|
||||||
|
|
||||||
if (!gtk_init_check (NULL, NULL))
|
if (!gtk_init_check (NULL, NULL))
|
||||||
meta_fatal ("Unable to open X display %s\n", XDisplayName (NULL));
|
meta_fatal ("Unable to open X display %s\n", XDisplayName (NULL));
|
||||||
}
|
}
|
||||||
|
@@ -1,436 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2010 Intel Corporation
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <termios.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <linux/kd.h>
|
|
||||||
#include <linux/vt.h>
|
|
||||||
#include <linux/major.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
#include "meta-tty.h"
|
|
||||||
#include <gio/gio.h>
|
|
||||||
#include <glib-unix.h>
|
|
||||||
|
|
||||||
/* Introduced in 2.6.38 */
|
|
||||||
#ifndef K_OFF
|
|
||||||
#define K_OFF 0x04
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct _MetaTTYClass
|
|
||||||
{
|
|
||||||
GObjectClass parent_class;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _MetaTTY
|
|
||||||
{
|
|
||||||
GObject parent;
|
|
||||||
|
|
||||||
int fd;
|
|
||||||
struct termios terminal_attributes;
|
|
||||||
|
|
||||||
GMainContext *nested_context;
|
|
||||||
GMainLoop *nested_loop;
|
|
||||||
|
|
||||||
int input_source;
|
|
||||||
GSource *vt_enter_source, *vt_leave_source;
|
|
||||||
GSource *nested_term;
|
|
||||||
int vt, starting_vt;
|
|
||||||
int kb_mode;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
|
||||||
SIGNAL_ENTER,
|
|
||||||
SIGNAL_LEAVE,
|
|
||||||
SIGNAL_LAST
|
|
||||||
};
|
|
||||||
|
|
||||||
static int signals[SIGNAL_LAST];
|
|
||||||
|
|
||||||
static void meta_tty_initable_iface_init (GInitableIface *);
|
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_CODE (MetaTTY, meta_tty, G_TYPE_OBJECT,
|
|
||||||
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
|
|
||||||
meta_tty_initable_iface_init));
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
quit_nested_loop (gpointer user_data)
|
|
||||||
{
|
|
||||||
MetaTTY *tty = user_data;
|
|
||||||
|
|
||||||
g_main_loop_quit (tty->nested_loop);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
vt_release_handler (gpointer user_data)
|
|
||||||
{
|
|
||||||
MetaTTY *tty = user_data;
|
|
||||||
|
|
||||||
g_signal_emit (tty, signals[SIGNAL_LEAVE], 0);
|
|
||||||
|
|
||||||
ioctl (tty->fd, VT_RELDISP, 1);
|
|
||||||
|
|
||||||
/* 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 (tty->nested_loop);
|
|
||||||
|
|
||||||
ioctl (tty->fd, VT_RELDISP, VT_ACKACQ);
|
|
||||||
|
|
||||||
g_signal_emit (tty, signals[SIGNAL_ENTER], 0);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
on_tty_input (int fd,
|
|
||||||
GIOCondition mask,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
MetaTTY *tty = user_data;
|
|
||||||
|
|
||||||
/* Ignore input to tty. We get keyboard events from evdev */
|
|
||||||
tcflush(tty->fd, TCIFLUSH);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
try_open_vt (MetaTTY *tty,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
int tty0, fd;
|
|
||||||
char filename[16];
|
|
||||||
|
|
||||||
tty0 = open ("/dev/tty0", O_WRONLY | O_CLOEXEC);
|
|
||||||
if (tty0 < 0)
|
|
||||||
{
|
|
||||||
g_set_error (error, G_IO_ERROR,
|
|
||||||
g_io_error_from_errno (errno),
|
|
||||||
"Could not open tty0: %s", strerror (errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ioctl (tty0, VT_OPENQRY, &tty->vt) < 0 || tty->vt == -1) {
|
|
||||||
g_set_error (error, G_IO_ERROR,
|
|
||||||
g_io_error_from_errno (errno),
|
|
||||||
"Could not open tty0: %s", strerror (errno));
|
|
||||||
close (tty0);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
close (tty0);
|
|
||||||
snprintf (filename, sizeof filename, "/dev/tty%d", tty->vt);
|
|
||||||
g_debug("compositor: using new vt %s\n", filename);
|
|
||||||
fd = open (filename, O_RDWR | O_NOCTTY | O_CLOEXEC);
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
gboolean
|
|
||||||
meta_tty_activate_vt (MetaTTY *tty,
|
|
||||||
int vt,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
if (ioctl(tty->fd, VT_ACTIVATE, vt) < 0)
|
|
||||||
{
|
|
||||||
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno),
|
|
||||||
strerror (errno));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
meta_tty_initable_init(GInitable *initable,
|
|
||||||
GCancellable *cancellable,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
MetaTTY *tty = META_TTY (initable);
|
|
||||||
struct termios raw_attributes;
|
|
||||||
struct vt_mode mode = { 0 };
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
struct stat buf;
|
|
||||||
struct vt_stat vts;
|
|
||||||
|
|
||||||
tty->fd = env_get_fd ("WESTON_TTY_FD");
|
|
||||||
if (tty->fd < 0)
|
|
||||||
tty->fd = STDIN_FILENO;
|
|
||||||
|
|
||||||
if (fstat(tty->fd, &buf) == 0 &&
|
|
||||||
major(buf.st_rdev) == TTY_MAJOR &&
|
|
||||||
minor(buf.st_rdev) > 0)
|
|
||||||
{
|
|
||||||
if (tty->fd == STDIN_FILENO)
|
|
||||||
tty->fd = fcntl(STDIN_FILENO, F_DUPFD_CLOEXEC, 0);
|
|
||||||
tty->vt = minor(buf.st_rdev);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Fall back to try opening a new VT. This typically
|
|
||||||
* requires root. */
|
|
||||||
tty->fd = try_open_vt(tty, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tty->fd <= 0 && (!error || !*error))
|
|
||||||
{
|
|
||||||
g_set_error (error, G_IO_ERROR,
|
|
||||||
g_io_error_from_errno (errno),
|
|
||||||
"Could not open tty0: %s", strerror (errno));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ioctl(tty->fd, VT_GETSTATE, &vts) == 0)
|
|
||||||
tty->starting_vt = vts.v_active;
|
|
||||||
else
|
|
||||||
tty->starting_vt = tty->vt;
|
|
||||||
|
|
||||||
if (tty->starting_vt != tty->vt)
|
|
||||||
{
|
|
||||||
if (ioctl(tty->fd, VT_ACTIVATE, tty->vt) < 0 ||
|
|
||||||
ioctl(tty->fd, VT_WAITACTIVE, tty->vt) < 0)
|
|
||||||
{
|
|
||||||
g_set_error (error, G_IO_ERROR,
|
|
||||||
g_io_error_from_errno (errno),
|
|
||||||
"Failed to switch to new vt: %s", strerror (errno));
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tcgetattr(tty->fd, &tty->terminal_attributes) < 0)
|
|
||||||
{
|
|
||||||
g_set_error (error, G_IO_ERROR,
|
|
||||||
g_io_error_from_errno (errno),
|
|
||||||
"Could not get terminal attributes: %s", strerror (errno));
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ignore control characters and disable echo */
|
|
||||||
raw_attributes = tty->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(tty->fd, TCSANOW, &raw_attributes) < 0)
|
|
||||||
g_warning("Could not put terminal into raw mode: %s", strerror (errno));
|
|
||||||
|
|
||||||
ioctl(tty->fd, KDGKBMODE, &tty->kb_mode);
|
|
||||||
ret = ioctl(tty->fd, KDSKBMODE, K_OFF);
|
|
||||||
if (ret)
|
|
||||||
{
|
|
||||||
ret = ioctl(tty->fd, KDSKBMODE, K_RAW);
|
|
||||||
if (ret)
|
|
||||||
{
|
|
||||||
g_set_error (error, G_IO_ERROR,
|
|
||||||
g_io_error_from_errno (errno),
|
|
||||||
"Failed to set keyboard mode: %s", strerror (errno));
|
|
||||||
goto err_attr;
|
|
||||||
}
|
|
||||||
|
|
||||||
tty->input_source = g_unix_fd_add (tty->fd,
|
|
||||||
G_IO_IN,
|
|
||||||
on_tty_input, tty);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = ioctl(tty->fd, KDSETMODE, KD_GRAPHICS);
|
|
||||||
if (ret)
|
|
||||||
{
|
|
||||||
g_set_error (error, G_IO_ERROR,
|
|
||||||
g_io_error_from_errno (errno),
|
|
||||||
"Failed to set KD_GRAPHICS mode: %s", strerror (errno));
|
|
||||||
goto err_kdkbmode;
|
|
||||||
}
|
|
||||||
|
|
||||||
mode.mode = VT_PROCESS;
|
|
||||||
mode.relsig = SIGUSR1;
|
|
||||||
mode.acqsig = SIGUSR2;
|
|
||||||
if (ioctl(tty->fd, VT_SETMODE, &mode) < 0)
|
|
||||||
{
|
|
||||||
g_set_error (error, G_IO_ERROR,
|
|
||||||
g_io_error_from_errno (errno),
|
|
||||||
"Failed to take control of vt handling: %s", strerror (errno));
|
|
||||||
goto err_kdmode;
|
|
||||||
}
|
|
||||||
|
|
||||||
tty->vt_leave_source = g_unix_signal_source_new (SIGUSR1);
|
|
||||||
g_source_set_callback (tty->vt_leave_source, vt_release_handler, tty, NULL);
|
|
||||||
|
|
||||||
tty->vt_enter_source = g_unix_signal_source_new (SIGUSR2);
|
|
||||||
g_source_set_callback (tty->vt_enter_source, quit_nested_loop, tty, NULL);
|
|
||||||
tty->nested_term = g_unix_signal_source_new (SIGTERM);
|
|
||||||
g_source_set_callback (tty->nested_term, quit_nested_loop, tty, NULL);
|
|
||||||
|
|
||||||
tty->nested_context = g_main_context_new ();
|
|
||||||
tty->nested_loop = g_main_loop_new (tty->nested_context, FALSE);
|
|
||||||
|
|
||||||
g_source_attach (tty->vt_leave_source, NULL);
|
|
||||||
g_source_attach (tty->vt_enter_source, tty->nested_context);
|
|
||||||
g_source_attach (tty->nested_term, tty->nested_context);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
err_kdmode:
|
|
||||||
ioctl (tty->fd, KDSETMODE, KD_TEXT);
|
|
||||||
|
|
||||||
err_kdkbmode:
|
|
||||||
if (tty->input_source)
|
|
||||||
g_source_remove (tty->input_source);
|
|
||||||
ioctl (tty->fd, KDSKBMODE, tty->kb_mode);
|
|
||||||
|
|
||||||
err_attr:
|
|
||||||
tcsetattr (tty->fd, TCSANOW, &tty->terminal_attributes);
|
|
||||||
|
|
||||||
err:
|
|
||||||
close (tty->fd);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
meta_tty_reset (MetaTTY *tty,
|
|
||||||
gboolean warn_if_fail)
|
|
||||||
{
|
|
||||||
struct vt_mode mode = { 0 };
|
|
||||||
|
|
||||||
if (ioctl (tty->fd, KDSKBMODE, tty->kb_mode) && warn_if_fail)
|
|
||||||
g_warning ("failed to restore keyboard mode: %s", strerror (errno));
|
|
||||||
|
|
||||||
if (ioctl (tty->fd, KDSETMODE, KD_TEXT) && warn_if_fail)
|
|
||||||
g_warning ("failed to set KD_TEXT mode on tty: %s", strerror (errno));
|
|
||||||
|
|
||||||
if (tcsetattr (tty->fd, TCSANOW, &tty->terminal_attributes) < 0 && warn_if_fail)
|
|
||||||
g_warning ("could not restore terminal to canonical mode");
|
|
||||||
|
|
||||||
mode.mode = VT_AUTO;
|
|
||||||
if (ioctl (tty->fd, VT_SETMODE, &mode) < 0 && warn_if_fail)
|
|
||||||
g_warning ("could not reset vt handling\n");
|
|
||||||
|
|
||||||
if (tty->vt != tty->starting_vt)
|
|
||||||
{
|
|
||||||
ioctl(tty->fd, VT_ACTIVATE, tty->starting_vt);
|
|
||||||
ioctl(tty->fd, VT_WAITACTIVE, tty->starting_vt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_tty_finalize (GObject *object)
|
|
||||||
{
|
|
||||||
MetaTTY *tty = META_TTY (object);
|
|
||||||
|
|
||||||
if (tty->input_source)
|
|
||||||
g_source_remove (tty->input_source);
|
|
||||||
|
|
||||||
g_source_destroy (tty->vt_enter_source);
|
|
||||||
g_source_destroy (tty->vt_leave_source);
|
|
||||||
g_source_destroy (tty->nested_term);
|
|
||||||
|
|
||||||
g_main_loop_unref (tty->nested_loop);
|
|
||||||
g_main_context_unref (tty->nested_context);
|
|
||||||
|
|
||||||
meta_tty_reset (tty, TRUE);
|
|
||||||
|
|
||||||
close (tty->fd);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (meta_tty_parent_class)->finalize (object);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_tty_init (MetaTTY *self)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_tty_class_init (MetaTTYClass *klass)
|
|
||||||
{
|
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
||||||
|
|
||||||
object_class->finalize = meta_tty_finalize;
|
|
||||||
|
|
||||||
signals[SIGNAL_ENTER] = g_signal_new ("enter",
|
|
||||||
G_TYPE_FROM_CLASS (klass),
|
|
||||||
G_SIGNAL_RUN_FIRST,
|
|
||||||
0, /* class offset */
|
|
||||||
NULL, NULL, /* accumulator */
|
|
||||||
g_cclosure_marshal_VOID__VOID,
|
|
||||||
G_TYPE_NONE, 0);
|
|
||||||
|
|
||||||
signals[SIGNAL_LEAVE] = g_signal_new ("leave",
|
|
||||||
G_TYPE_FROM_CLASS (klass),
|
|
||||||
G_SIGNAL_RUN_FIRST,
|
|
||||||
0, /* class offset */
|
|
||||||
NULL, NULL, /* accumulator */
|
|
||||||
g_cclosure_marshal_VOID__VOID,
|
|
||||||
G_TYPE_NONE, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_tty_initable_iface_init (GInitableIface *iface)
|
|
||||||
{
|
|
||||||
iface->init = meta_tty_initable_init;
|
|
||||||
}
|
|
||||||
|
|
||||||
MetaTTY *
|
|
||||||
meta_tty_new (void)
|
|
||||||
{
|
|
||||||
GError *error;
|
|
||||||
MetaTTY *tty;
|
|
||||||
|
|
||||||
error = NULL;
|
|
||||||
tty = g_initable_new (META_TYPE_TTY, NULL, &error, NULL);
|
|
||||||
|
|
||||||
if (tty == NULL)
|
|
||||||
{
|
|
||||||
g_warning ("Failed to initalize TTY handling: %s", error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
return tty;
|
|
||||||
}
|
|
@@ -1,50 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef META_TTY_H
|
|
||||||
#define META_TTY_H
|
|
||||||
|
|
||||||
#include <glib-object.h>
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
|
||||||
|
|
||||||
#define META_TYPE_TTY (meta_tty_get_type())
|
|
||||||
#define META_TTY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_TTY, MetaTTY))
|
|
||||||
#define META_TTY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_TTY, MetaTTYClass))
|
|
||||||
#define META_IS_TTY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_TTY))
|
|
||||||
#define META_IS_TTY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_TTY))
|
|
||||||
#define META_TTY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TTY, MetaTTYClass))
|
|
||||||
|
|
||||||
typedef struct _MetaTTY MetaTTY;
|
|
||||||
typedef struct _MetaTTYClass MetaTTYClass;
|
|
||||||
|
|
||||||
GType meta_tty_get_type (void) G_GNUC_CONST;
|
|
||||||
|
|
||||||
MetaTTY *meta_tty_new (void);
|
|
||||||
|
|
||||||
gboolean meta_tty_activate_vt (MetaTTY *self,
|
|
||||||
int number,
|
|
||||||
GError **error);
|
|
||||||
|
|
||||||
void meta_tty_reset (MetaTTY *self,
|
|
||||||
gboolean warn_if_fail);
|
|
||||||
|
|
||||||
G_END_DECLS
|
|
||||||
|
|
||||||
#endif /* META_TTY_H */
|
|
@@ -56,7 +56,6 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <clutter/evdev/clutter-evdev.h>
|
|
||||||
|
|
||||||
#include "meta-wayland-keyboard.h"
|
#include "meta-wayland-keyboard.h"
|
||||||
|
|
||||||
@@ -259,11 +258,12 @@ default_grab_modifiers (MetaWaylandKeyboardGrab *grab, uint32_t serial,
|
|||||||
pointer->focus);
|
pointer->focus);
|
||||||
if (pr)
|
if (pr)
|
||||||
{
|
{
|
||||||
wl_keyboard_send_modifiers (pr, serial,
|
wl_keyboard_send_modifiers (pr,
|
||||||
mods_depressed,
|
serial,
|
||||||
mods_latched,
|
keyboard->modifiers.mods_depressed,
|
||||||
mods_locked,
|
keyboard->modifiers.mods_latched,
|
||||||
group);
|
keyboard->modifiers.mods_locked,
|
||||||
|
keyboard->modifiers.group);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -276,11 +276,8 @@ static const MetaWaylandKeyboardGrabInterface
|
|||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
|
meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
|
||||||
struct wl_display *display,
|
struct wl_display *display)
|
||||||
gboolean is_evdev)
|
|
||||||
{
|
{
|
||||||
ClutterDeviceManager *manager;
|
|
||||||
|
|
||||||
memset (keyboard, 0, sizeof *keyboard);
|
memset (keyboard, 0, sizeof *keyboard);
|
||||||
|
|
||||||
wl_list_init (&keyboard->resource_list);
|
wl_list_init (&keyboard->resource_list);
|
||||||
@@ -296,22 +293,8 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
|
|||||||
keyboard->xkb_context = xkb_context_new (0 /* flags */);
|
keyboard->xkb_context = xkb_context_new (0 /* flags */);
|
||||||
|
|
||||||
meta_wayland_keyboard_build_global_keymap (keyboard->xkb_context,
|
meta_wayland_keyboard_build_global_keymap (keyboard->xkb_context,
|
||||||
&keyboard->xkb_names,
|
&keyboard->xkb_names,
|
||||||
&keyboard->xkb_info);
|
&keyboard->xkb_info);
|
||||||
|
|
||||||
keyboard->is_evdev = is_evdev;
|
|
||||||
if (is_evdev)
|
|
||||||
{
|
|
||||||
manager = clutter_device_manager_get_default ();
|
|
||||||
|
|
||||||
clutter_evdev_set_keyboard_map (manager, keyboard->xkb_info.keymap);
|
|
||||||
keyboard->xkb_state = clutter_evdev_get_keyboard_state (manager);
|
|
||||||
xkb_state_ref (keyboard->xkb_state);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
keyboard->xkb_state = xkb_state_new (keyboard->xkb_info.keymap);
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -329,12 +312,17 @@ meta_wayland_xkb_info_destroy (MetaWaylandXkbInfo *xkb_info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_state_from_clutter (MetaWaylandKeyboard *keyboard,
|
set_modifiers (MetaWaylandKeyboard *keyboard,
|
||||||
ClutterModifierType modifier_state)
|
guint32 serial,
|
||||||
|
ClutterModifierType modifier_state)
|
||||||
{
|
{
|
||||||
|
MetaWaylandKeyboardGrab *grab = keyboard->grab;
|
||||||
uint32_t depressed_mods = 0;
|
uint32_t depressed_mods = 0;
|
||||||
uint32_t locked_mods = 0;
|
uint32_t locked_mods = 0;
|
||||||
|
|
||||||
|
if (keyboard->last_modifier_state == modifier_state)
|
||||||
|
return;
|
||||||
|
|
||||||
if ((modifier_state & CLUTTER_SHIFT_MASK) &&
|
if ((modifier_state & CLUTTER_SHIFT_MASK) &&
|
||||||
keyboard->xkb_info.shift_mod != XKB_MOD_INVALID)
|
keyboard->xkb_info.shift_mod != XKB_MOD_INVALID)
|
||||||
depressed_mods |= (1 << keyboard->xkb_info.shift_mod);
|
depressed_mods |= (1 << keyboard->xkb_info.shift_mod);
|
||||||
@@ -367,56 +355,14 @@ update_state_from_clutter (MetaWaylandKeyboard *keyboard,
|
|||||||
keyboard->xkb_info.mod5_mod != XKB_MOD_INVALID)
|
keyboard->xkb_info.mod5_mod != XKB_MOD_INVALID)
|
||||||
depressed_mods |= (1 << keyboard->xkb_info.mod5_mod);
|
depressed_mods |= (1 << keyboard->xkb_info.mod5_mod);
|
||||||
|
|
||||||
xkb_state_update_mask (keyboard->xkb_state,
|
keyboard->last_modifier_state = modifier_state;
|
||||||
depressed_mods,
|
|
||||||
0,
|
|
||||||
locked_mods,
|
|
||||||
0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
state_equal (MetaWaylandXkbState *one,
|
|
||||||
MetaWaylandXkbState *two)
|
|
||||||
{
|
|
||||||
return one->mods_depressed == two->mods_depressed &&
|
|
||||||
one->mods_latched == two->mods_latched &&
|
|
||||||
one->mods_locked == two->mods_locked &&
|
|
||||||
one->group == two->group;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
set_modifiers (MetaWaylandKeyboard *keyboard,
|
|
||||||
guint32 serial,
|
|
||||||
ClutterModifierType modifier_state)
|
|
||||||
{
|
|
||||||
MetaWaylandKeyboardGrab *grab = keyboard->grab;
|
|
||||||
MetaWaylandXkbState new_state;
|
|
||||||
|
|
||||||
/* In the evdev case, the state is shared with the clutter backend, so
|
|
||||||
we don't need to update it */
|
|
||||||
if (!keyboard->is_evdev)
|
|
||||||
update_state_from_clutter (keyboard, modifier_state);
|
|
||||||
|
|
||||||
new_state.mods_depressed = xkb_state_serialize_mods (keyboard->xkb_state,
|
|
||||||
XKB_STATE_MODS_DEPRESSED);
|
|
||||||
new_state.mods_latched = xkb_state_serialize_mods (keyboard->xkb_state,
|
|
||||||
XKB_STATE_MODS_LATCHED);
|
|
||||||
new_state.mods_locked = xkb_state_serialize_mods (keyboard->xkb_state,
|
|
||||||
XKB_STATE_MODS_LOCKED);
|
|
||||||
new_state.group = xkb_state_serialize_layout (keyboard->xkb_state,
|
|
||||||
XKB_STATE_LAYOUT_EFFECTIVE);
|
|
||||||
|
|
||||||
if (state_equal (&keyboard->modifier_state, &new_state))
|
|
||||||
return;
|
|
||||||
|
|
||||||
keyboard->modifier_state = new_state;
|
|
||||||
|
|
||||||
grab->interface->modifiers (grab,
|
grab->interface->modifiers (grab,
|
||||||
serial,
|
serial,
|
||||||
new_state.mods_depressed,
|
depressed_mods,
|
||||||
new_state.mods_latched,
|
0, /* latched_modes */
|
||||||
new_state.mods_locked,
|
locked_mods,
|
||||||
new_state.group);
|
0 /* group */);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -470,7 +416,7 @@ meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard,
|
|||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_warning ("unexpected key release event for key 0x%x (%d)", evdev_code, event->keyval);
|
g_warning ("unexpected key release event for key 0x%x", evdev_code);
|
||||||
|
|
||||||
found:
|
found:
|
||||||
(void) 0;
|
(void) 0;
|
||||||
@@ -516,10 +462,10 @@ meta_wayland_keyboard_set_focus (MetaWaylandKeyboard *keyboard,
|
|||||||
display = wl_client_get_display (client);
|
display = wl_client_get_display (client);
|
||||||
serial = wl_display_next_serial (display);
|
serial = wl_display_next_serial (display);
|
||||||
wl_keyboard_send_modifiers (resource, serial,
|
wl_keyboard_send_modifiers (resource, serial,
|
||||||
keyboard->modifier_state.mods_depressed,
|
keyboard->modifiers.mods_depressed,
|
||||||
keyboard->modifier_state.mods_latched,
|
keyboard->modifiers.mods_latched,
|
||||||
keyboard->modifier_state.mods_locked,
|
keyboard->modifiers.mods_locked,
|
||||||
keyboard->modifier_state.group);
|
keyboard->modifiers.group);
|
||||||
wl_keyboard_send_enter (resource, serial, surface->resource,
|
wl_keyboard_send_enter (resource, serial, surface->resource,
|
||||||
&keyboard->keys);
|
&keyboard->keys);
|
||||||
wl_resource_add_destroy_listener (resource, &keyboard->focus_listener);
|
wl_resource_add_destroy_listener (resource, &keyboard->focus_listener);
|
||||||
@@ -558,61 +504,9 @@ meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard)
|
|||||||
|
|
||||||
meta_wayland_xkb_info_destroy (&keyboard->xkb_info);
|
meta_wayland_xkb_info_destroy (&keyboard->xkb_info);
|
||||||
xkb_context_unref (keyboard->xkb_context);
|
xkb_context_unref (keyboard->xkb_context);
|
||||||
xkb_state_unref (keyboard->xkb_state);
|
|
||||||
|
|
||||||
/* XXX: What about keyboard->resource_list? */
|
/* XXX: What about keyboard->resource_list? */
|
||||||
if (keyboard->focus_resource)
|
if (keyboard->focus_resource)
|
||||||
wl_list_remove (&keyboard->focus_listener.link);
|
wl_list_remove (&keyboard->focus_listener.link);
|
||||||
wl_array_release (&keyboard->keys);
|
wl_array_release (&keyboard->keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
modal_key (MetaWaylandKeyboardGrab *grab,
|
|
||||||
uint32_t time,
|
|
||||||
uint32_t key,
|
|
||||||
uint32_t state)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
modal_modifiers (MetaWaylandKeyboardGrab *grab,
|
|
||||||
uint32_t serial,
|
|
||||||
uint32_t mods_depressed,
|
|
||||||
uint32_t mods_latched,
|
|
||||||
uint32_t mods_locked,
|
|
||||||
uint32_t group)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static MetaWaylandKeyboardGrabInterface modal_grab = {
|
|
||||||
modal_key,
|
|
||||||
modal_modifiers,
|
|
||||||
};
|
|
||||||
|
|
||||||
gboolean
|
|
||||||
meta_wayland_keyboard_begin_modal (MetaWaylandKeyboard *keyboard)
|
|
||||||
{
|
|
||||||
MetaWaylandKeyboardGrab *grab;
|
|
||||||
|
|
||||||
if (keyboard->grab != &keyboard->default_grab)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
grab = g_slice_new0 (MetaWaylandKeyboardGrab);
|
|
||||||
grab->interface = &modal_grab;
|
|
||||||
meta_wayland_keyboard_start_grab (keyboard, grab);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
meta_wayland_keyboard_end_modal (MetaWaylandKeyboard *keyboard)
|
|
||||||
{
|
|
||||||
MetaWaylandKeyboardGrab *grab;
|
|
||||||
|
|
||||||
grab = keyboard->grab;
|
|
||||||
|
|
||||||
g_assert (grab->interface == &modal_grab);
|
|
||||||
|
|
||||||
meta_wayland_keyboard_end_grab (keyboard);
|
|
||||||
g_slice_free (MetaWaylandKeyboardGrab, grab);
|
|
||||||
}
|
|
||||||
|
@@ -52,8 +52,7 @@
|
|||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
|
meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
|
||||||
struct wl_display *display,
|
struct wl_display *display);
|
||||||
gboolean is_evdev);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard,
|
meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard,
|
||||||
@@ -70,11 +69,6 @@ meta_wayland_keyboard_start_grab (MetaWaylandKeyboard *device,
|
|||||||
void
|
void
|
||||||
meta_wayland_keyboard_end_grab (MetaWaylandKeyboard *keyboard);
|
meta_wayland_keyboard_end_grab (MetaWaylandKeyboard *keyboard);
|
||||||
|
|
||||||
gboolean
|
|
||||||
meta_wayland_keyboard_begin_modal (MetaWaylandKeyboard *keyboard);
|
|
||||||
void
|
|
||||||
meta_wayland_keyboard_end_modal (MetaWaylandKeyboard *keyboard);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard);
|
meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard);
|
||||||
|
|
||||||
|
@@ -194,10 +194,10 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
|
|||||||
{
|
{
|
||||||
wl_keyboard_send_modifiers (kr,
|
wl_keyboard_send_modifiers (kr,
|
||||||
serial,
|
serial,
|
||||||
kbd->modifier_state.mods_depressed,
|
kbd->modifiers.mods_depressed,
|
||||||
kbd->modifier_state.mods_latched,
|
kbd->modifiers.mods_latched,
|
||||||
kbd->modifier_state.mods_locked,
|
kbd->modifiers.mods_locked,
|
||||||
kbd->modifier_state.group);
|
kbd->modifiers.group);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wl_pointer_send_enter (resource, serial, surface->resource, sx, sy);
|
wl_pointer_send_enter (resource, serial, surface->resource, sx, sy);
|
||||||
@@ -262,65 +262,3 @@ meta_wayland_pointer_set_current (MetaWaylandPointer *pointer,
|
|||||||
&pointer->current_listener);
|
&pointer->current_listener);
|
||||||
pointer->current_listener.notify = current_surface_destroy;
|
pointer->current_listener.notify = current_surface_destroy;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
modal_focus (MetaWaylandPointerGrab *grab,
|
|
||||||
MetaWaylandSurface *surface,
|
|
||||||
wl_fixed_t x,
|
|
||||||
wl_fixed_t y)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
modal_motion (MetaWaylandPointerGrab *grab,
|
|
||||||
uint32_t time,
|
|
||||||
wl_fixed_t x,
|
|
||||||
wl_fixed_t y)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
modal_button (MetaWaylandPointerGrab *grab,
|
|
||||||
uint32_t time,
|
|
||||||
uint32_t button,
|
|
||||||
uint32_t state)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static MetaWaylandPointerGrabInterface modal_grab = {
|
|
||||||
modal_focus,
|
|
||||||
modal_motion,
|
|
||||||
modal_button
|
|
||||||
};
|
|
||||||
|
|
||||||
gboolean
|
|
||||||
meta_wayland_pointer_begin_modal (MetaWaylandPointer *pointer)
|
|
||||||
{
|
|
||||||
MetaWaylandPointerGrab *grab;
|
|
||||||
|
|
||||||
if (pointer->grab != &pointer->default_grab)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
meta_wayland_pointer_set_focus (pointer, NULL,
|
|
||||||
wl_fixed_from_int (0),
|
|
||||||
wl_fixed_from_int (0));
|
|
||||||
|
|
||||||
grab = g_slice_new0 (MetaWaylandPointerGrab);
|
|
||||||
grab->interface = &modal_grab;
|
|
||||||
meta_wayland_pointer_start_grab (pointer, grab);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
meta_wayland_pointer_end_modal (MetaWaylandPointer *pointer)
|
|
||||||
{
|
|
||||||
MetaWaylandPointerGrab *grab;
|
|
||||||
|
|
||||||
grab = pointer->grab;
|
|
||||||
|
|
||||||
g_assert (grab->interface == &modal_grab);
|
|
||||||
|
|
||||||
meta_wayland_pointer_end_grab (pointer);
|
|
||||||
g_slice_free (MetaWaylandPointerGrab, grab);
|
|
||||||
}
|
|
||||||
|
@@ -42,11 +42,6 @@ meta_wayland_pointer_start_grab (MetaWaylandPointer *pointer,
|
|||||||
void
|
void
|
||||||
meta_wayland_pointer_end_grab (MetaWaylandPointer *pointer);
|
meta_wayland_pointer_end_grab (MetaWaylandPointer *pointer);
|
||||||
|
|
||||||
gboolean
|
|
||||||
meta_wayland_pointer_begin_modal (MetaWaylandPointer *pointer);
|
|
||||||
void
|
|
||||||
meta_wayland_pointer_end_modal (MetaWaylandPointer *pointer);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_wayland_pointer_set_current (MetaWaylandPointer *pointer,
|
meta_wayland_pointer_set_current (MetaWaylandPointer *pointer,
|
||||||
MetaWaylandSurface *surface);
|
MetaWaylandSurface *surface);
|
||||||
|
@@ -28,7 +28,6 @@
|
|||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
|
|
||||||
#include "window-private.h"
|
#include "window-private.h"
|
||||||
#include "meta-tty.h"
|
|
||||||
#include <meta/meta-cursor-tracker.h>
|
#include <meta/meta-cursor-tracker.h>
|
||||||
|
|
||||||
typedef struct _MetaWaylandCompositor MetaWaylandCompositor;
|
typedef struct _MetaWaylandCompositor MetaWaylandCompositor;
|
||||||
@@ -52,7 +51,9 @@ typedef struct
|
|||||||
union
|
union
|
||||||
{
|
{
|
||||||
struct wl_shm_buffer *shm_buffer;
|
struct wl_shm_buffer *shm_buffer;
|
||||||
|
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
|
||||||
struct wl_buffer *legacy_buffer;
|
struct wl_buffer *legacy_buffer;
|
||||||
|
G_GNUC_END_IGNORE_DEPRECATIONS;
|
||||||
};
|
};
|
||||||
|
|
||||||
int32_t width, height;
|
int32_t width, height;
|
||||||
@@ -130,12 +131,11 @@ typedef struct
|
|||||||
|
|
||||||
struct _MetaWaylandCompositor
|
struct _MetaWaylandCompositor
|
||||||
{
|
{
|
||||||
GHashTable *outputs;
|
|
||||||
|
|
||||||
struct wl_display *wayland_display;
|
struct wl_display *wayland_display;
|
||||||
struct wl_event_loop *wayland_loop;
|
struct wl_event_loop *wayland_loop;
|
||||||
GMainLoop *init_loop;
|
GMainLoop *init_loop;
|
||||||
ClutterActor *stage;
|
ClutterActor *stage;
|
||||||
|
GHashTable *outputs;
|
||||||
GSource *wayland_event_source;
|
GSource *wayland_event_source;
|
||||||
GList *surfaces;
|
GList *surfaces;
|
||||||
struct wl_list frame_callbacks;
|
struct wl_list frame_callbacks;
|
||||||
@@ -148,10 +148,6 @@ struct _MetaWaylandCompositor
|
|||||||
struct wl_client *xwayland_client;
|
struct wl_client *xwayland_client;
|
||||||
struct wl_resource *xserver_resource;
|
struct wl_resource *xserver_resource;
|
||||||
|
|
||||||
MetaTTY *tty;
|
|
||||||
int drm_fd;
|
|
||||||
GSocket *weston_launch;
|
|
||||||
|
|
||||||
MetaWaylandSeat *seat;
|
MetaWaylandSeat *seat;
|
||||||
|
|
||||||
/* This surface is only used to keep drag of the implicit grab when
|
/* This surface is only used to keep drag of the implicit grab when
|
||||||
@@ -238,14 +234,6 @@ typedef struct
|
|||||||
xkb_mod_index_t mod5_mod;
|
xkb_mod_index_t mod5_mod;
|
||||||
} MetaWaylandXkbInfo;
|
} MetaWaylandXkbInfo;
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
uint32_t mods_depressed;
|
|
||||||
uint32_t mods_latched;
|
|
||||||
uint32_t mods_locked;
|
|
||||||
uint32_t group;
|
|
||||||
} MetaWaylandXkbState;
|
|
||||||
|
|
||||||
struct _MetaWaylandKeyboard
|
struct _MetaWaylandKeyboard
|
||||||
{
|
{
|
||||||
struct wl_list resource_list;
|
struct wl_list resource_list;
|
||||||
@@ -263,19 +251,25 @@ struct _MetaWaylandKeyboard
|
|||||||
|
|
||||||
struct wl_array keys;
|
struct wl_array keys;
|
||||||
|
|
||||||
MetaWaylandXkbState modifier_state;
|
struct
|
||||||
|
{
|
||||||
|
uint32_t mods_depressed;
|
||||||
|
uint32_t mods_latched;
|
||||||
|
uint32_t mods_locked;
|
||||||
|
uint32_t group;
|
||||||
|
} modifiers;
|
||||||
|
|
||||||
struct wl_display *display;
|
struct wl_display *display;
|
||||||
|
|
||||||
struct xkb_context *xkb_context;
|
struct xkb_context *xkb_context;
|
||||||
struct xkb_state *xkb_state;
|
|
||||||
gboolean is_evdev;
|
|
||||||
|
|
||||||
MetaWaylandXkbInfo xkb_info;
|
MetaWaylandXkbInfo xkb_info;
|
||||||
struct xkb_rule_names xkb_names;
|
struct xkb_rule_names xkb_names;
|
||||||
|
|
||||||
MetaWaylandKeyboardGrab input_method_grab;
|
MetaWaylandKeyboardGrab input_method_grab;
|
||||||
struct wl_resource *input_method_resource;
|
struct wl_resource *input_method_resource;
|
||||||
|
|
||||||
|
ClutterModifierType last_modifier_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _MetaWaylandDataOffer
|
struct _MetaWaylandDataOffer
|
||||||
@@ -344,9 +338,6 @@ void meta_wayland_compositor_repick (MetaWaylandComp
|
|||||||
void meta_wayland_compositor_set_input_focus (MetaWaylandCompositor *compositor,
|
void meta_wayland_compositor_set_input_focus (MetaWaylandCompositor *compositor,
|
||||||
MetaWindow *window);
|
MetaWindow *window);
|
||||||
|
|
||||||
MetaTTY *meta_wayland_compositor_get_tty (MetaWaylandCompositor *compositor);
|
|
||||||
gboolean meta_wayland_compositor_is_native (MetaWaylandCompositor *compositor);
|
|
||||||
|
|
||||||
void meta_wayland_surface_free (MetaWaylandSurface *surface);
|
void meta_wayland_surface_free (MetaWaylandSurface *surface);
|
||||||
|
|
||||||
#endif /* META_WAYLAND_PRIVATE_H */
|
#endif /* META_WAYLAND_PRIVATE_H */
|
||||||
|
@@ -35,6 +35,7 @@
|
|||||||
#include "meta-wayland-data-device.h"
|
#include "meta-wayland-data-device.h"
|
||||||
#include "meta-window-actor-private.h"
|
#include "meta-window-actor-private.h"
|
||||||
#include "meta/meta-shaped-texture.h"
|
#include "meta/meta-shaped-texture.h"
|
||||||
|
#include "meta-shaped-texture-private.h"
|
||||||
#include "meta-wayland-stage.h"
|
#include "meta-wayland-stage.h"
|
||||||
#include "meta-cursor-tracker-private.h"
|
#include "meta-cursor-tracker-private.h"
|
||||||
|
|
||||||
@@ -270,8 +271,7 @@ pointer_handle_sprite_destroy (struct wl_listener *listener, void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
MetaWaylandSeat *
|
MetaWaylandSeat *
|
||||||
meta_wayland_seat_new (struct wl_display *display,
|
meta_wayland_seat_new (struct wl_display *display)
|
||||||
gboolean is_native)
|
|
||||||
{
|
{
|
||||||
MetaWaylandSeat *seat = g_new0 (MetaWaylandSeat, 1);
|
MetaWaylandSeat *seat = g_new0 (MetaWaylandSeat, 1);
|
||||||
|
|
||||||
@@ -285,7 +285,7 @@ meta_wayland_seat_new (struct wl_display *display,
|
|||||||
|
|
||||||
meta_wayland_pointer_init (&seat->pointer);
|
meta_wayland_pointer_init (&seat->pointer);
|
||||||
|
|
||||||
meta_wayland_keyboard_init (&seat->keyboard, display, is_native);
|
meta_wayland_keyboard_init (&seat->keyboard, display);
|
||||||
|
|
||||||
seat->display = display;
|
seat->display = display;
|
||||||
|
|
||||||
|
@@ -30,8 +30,7 @@
|
|||||||
#include "meta-wayland-private.h"
|
#include "meta-wayland-private.h"
|
||||||
|
|
||||||
MetaWaylandSeat *
|
MetaWaylandSeat *
|
||||||
meta_wayland_seat_new (struct wl_display *display,
|
meta_wayland_seat_new (struct wl_display *display);
|
||||||
gboolean is_native);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
|
meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
|
||||||
|
@@ -65,4 +65,3 @@ meta_wayland_stage_new (void)
|
|||||||
"cursor-visible", FALSE,
|
"cursor-visible", FALSE,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -24,7 +24,6 @@
|
|||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
#include <clutter/wayland/clutter-wayland-compositor.h>
|
#include <clutter/wayland/clutter-wayland-compositor.h>
|
||||||
#include <clutter/wayland/clutter-wayland-surface.h>
|
#include <clutter/wayland/clutter-wayland-surface.h>
|
||||||
#include <clutter/evdev/clutter-evdev.h>
|
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
@@ -32,8 +31,6 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
||||||
#include <wayland-server.h>
|
#include <wayland-server.h>
|
||||||
@@ -52,8 +49,8 @@
|
|||||||
#include <meta/types.h>
|
#include <meta/types.h>
|
||||||
#include <meta/main.h>
|
#include <meta/main.h>
|
||||||
#include "frame.h"
|
#include "frame.h"
|
||||||
#include "meta-weston-launch.h"
|
|
||||||
#include "meta-idle-monitor-private.h"
|
#include "meta-idle-monitor-private.h"
|
||||||
|
#include "monitor-private.h"
|
||||||
|
|
||||||
static MetaWaylandCompositor _meta_wayland_compositor;
|
static MetaWaylandCompositor _meta_wayland_compositor;
|
||||||
|
|
||||||
@@ -214,20 +211,6 @@ surface_process_damage (MetaWaylandSurface *surface,
|
|||||||
MetaWindowActor *window_actor =
|
MetaWindowActor *window_actor =
|
||||||
META_WINDOW_ACTOR (meta_window_get_compositor_private (surface->window));
|
META_WINDOW_ACTOR (meta_window_get_compositor_private (surface->window));
|
||||||
|
|
||||||
if (!surface->window->override_redirect)
|
|
||||||
{
|
|
||||||
MetaRectangle rect;
|
|
||||||
cairo_rectangle_int_t cairo_rect;
|
|
||||||
|
|
||||||
meta_window_get_input_rect (surface->window, &rect);
|
|
||||||
cairo_rect.x = 0;
|
|
||||||
cairo_rect.y = 0;
|
|
||||||
cairo_rect.width = rect.width;
|
|
||||||
cairo_rect.height = rect.height;
|
|
||||||
|
|
||||||
cairo_region_intersect_rectangle (region, &cairo_rect);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window_actor)
|
if (window_actor)
|
||||||
{
|
{
|
||||||
int i, n_rectangles = cairo_region_num_rectangles (region);
|
int i, n_rectangles = cairo_region_num_rectangles (region);
|
||||||
@@ -341,18 +324,34 @@ meta_wayland_surface_frame (struct wl_client *client,
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
meta_wayland_surface_set_opaque_region (struct wl_client *client,
|
meta_wayland_surface_set_opaque_region (struct wl_client *client,
|
||||||
struct wl_resource *resource,
|
struct wl_resource *surface_resource,
|
||||||
struct wl_resource *region)
|
struct wl_resource *region_resource)
|
||||||
{
|
{
|
||||||
g_warning ("TODO: support set_opaque_region request");
|
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
||||||
|
MetaWaylandRegion *region = wl_resource_get_user_data (region_resource);
|
||||||
|
|
||||||
|
/* X11 unmanaged window */
|
||||||
|
if (!surface)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (surface->window)
|
||||||
|
meta_window_set_opaque_region (surface->window, cairo_region_copy (region->region));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_wayland_surface_set_input_region (struct wl_client *client,
|
meta_wayland_surface_set_input_region (struct wl_client *client,
|
||||||
struct wl_resource *resource,
|
struct wl_resource *surface_resource,
|
||||||
struct wl_resource *region)
|
struct wl_resource *region_resource)
|
||||||
{
|
{
|
||||||
g_warning ("TODO: support set_input_region request");
|
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
||||||
|
MetaWaylandRegion *region = wl_resource_get_user_data (region_resource);
|
||||||
|
|
||||||
|
/* X11 unmanaged window */
|
||||||
|
if (!surface)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (surface->window)
|
||||||
|
meta_window_set_input_region (surface->window, cairo_region_copy (region->region));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -683,38 +682,40 @@ bind_output (struct wl_client *client,
|
|||||||
wl_resource_set_destructor (resource, output_resource_destroy);
|
wl_resource_set_destructor (resource, output_resource_destroy);
|
||||||
|
|
||||||
meta_verbose ("Binding output %p/%s (%u, %u, %u, %u) x %f\n",
|
meta_verbose ("Binding output %p/%s (%u, %u, %u, %u) x %f\n",
|
||||||
output, output->name,
|
output, output->name,
|
||||||
output->crtc->rect.x, output->crtc->rect.y,
|
output->crtc->rect.x, output->crtc->rect.y,
|
||||||
output->crtc->rect.width, output->crtc->rect.height,
|
output->crtc->rect.width, output->crtc->rect.height,
|
||||||
output->crtc->current_mode->refresh_rate);
|
output->crtc->current_mode->refresh_rate);
|
||||||
|
|
||||||
wl_resource_post_event (resource,
|
wl_resource_post_event (resource,
|
||||||
WL_OUTPUT_GEOMETRY,
|
WL_OUTPUT_GEOMETRY,
|
||||||
(int)output->crtc->rect.x,
|
(int)output->crtc->rect.x,
|
||||||
(int)output->crtc->rect.y,
|
(int)output->crtc->rect.y,
|
||||||
output->width_mm,
|
output->width_mm,
|
||||||
output->height_mm,
|
output->height_mm,
|
||||||
/* Cogl values reflect XRandR values,
|
/* Cogl values reflect XRandR values,
|
||||||
and so does wayland */
|
and so does wayland */
|
||||||
output->subpixel_order,
|
output->subpixel_order,
|
||||||
output->vendor,
|
output->vendor,
|
||||||
output->product,
|
output->product,
|
||||||
output->crtc->transform);
|
output->crtc->transform);
|
||||||
|
|
||||||
|
g_assert (output->crtc->current_mode != NULL);
|
||||||
|
|
||||||
mode_flags = WL_OUTPUT_MODE_CURRENT;
|
mode_flags = WL_OUTPUT_MODE_CURRENT;
|
||||||
if (output->crtc->current_mode == output->preferred_mode)
|
if (output->crtc->current_mode == output->preferred_mode)
|
||||||
mode_flags |= WL_OUTPUT_MODE_PREFERRED;
|
mode_flags |= WL_OUTPUT_MODE_PREFERRED;
|
||||||
|
|
||||||
wl_resource_post_event (resource,
|
wl_resource_post_event (resource,
|
||||||
WL_OUTPUT_MODE,
|
WL_OUTPUT_MODE,
|
||||||
mode_flags,
|
mode_flags,
|
||||||
(int)output->crtc->rect.width,
|
(int)output->crtc->current_mode->width,
|
||||||
(int)output->crtc->rect.height,
|
(int)output->crtc->current_mode->height,
|
||||||
(int)output->crtc->current_mode->refresh_rate);
|
(int)output->crtc->current_mode->refresh_rate);
|
||||||
|
|
||||||
if (version >= 2)
|
if (version >= 2)
|
||||||
wl_resource_post_event (resource,
|
wl_resource_post_event (resource,
|
||||||
WL_OUTPUT_DONE);
|
WL_OUTPUT_DONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -735,11 +736,13 @@ wayland_output_destroy_notify (gpointer data)
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
wayland_output_update_for_output (MetaWaylandOutput *wayland_output,
|
wayland_output_update_for_output (MetaWaylandOutput *wayland_output,
|
||||||
MetaOutput *output)
|
MetaOutput *output)
|
||||||
{
|
{
|
||||||
GList *iter;
|
GList *iter;
|
||||||
guint mode_flags;
|
guint mode_flags;
|
||||||
|
|
||||||
|
g_assert (output->crtc->current_mode != NULL);
|
||||||
|
|
||||||
mode_flags = WL_OUTPUT_MODE_CURRENT;
|
mode_flags = WL_OUTPUT_MODE_CURRENT;
|
||||||
if (output->crtc->current_mode == output->preferred_mode)
|
if (output->crtc->current_mode == output->preferred_mode)
|
||||||
mode_flags |= WL_OUTPUT_MODE_PREFERRED;
|
mode_flags |= WL_OUTPUT_MODE_PREFERRED;
|
||||||
@@ -749,27 +752,27 @@ wayland_output_update_for_output (MetaWaylandOutput *wayland_output,
|
|||||||
struct wl_resource *resource = iter->data;
|
struct wl_resource *resource = iter->data;
|
||||||
|
|
||||||
if (wayland_output->x != output->crtc->rect.x ||
|
if (wayland_output->x != output->crtc->rect.x ||
|
||||||
wayland_output->y != output->crtc->rect.y ||
|
wayland_output->y != output->crtc->rect.y ||
|
||||||
wayland_output->transform != output->crtc->transform)
|
wayland_output->transform != output->crtc->transform)
|
||||||
{
|
{
|
||||||
wl_resource_post_event (resource,
|
wl_resource_post_event (resource,
|
||||||
WL_OUTPUT_GEOMETRY,
|
WL_OUTPUT_GEOMETRY,
|
||||||
(int)output->crtc->rect.x,
|
(int)output->crtc->rect.x,
|
||||||
(int)output->crtc->rect.y,
|
(int)output->crtc->rect.y,
|
||||||
output->width_mm,
|
output->width_mm,
|
||||||
output->height_mm,
|
output->height_mm,
|
||||||
output->subpixel_order,
|
output->subpixel_order,
|
||||||
output->vendor,
|
output->vendor,
|
||||||
output->product,
|
output->product,
|
||||||
output->crtc->transform);
|
output->crtc->transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_resource_post_event (resource,
|
wl_resource_post_event (resource,
|
||||||
WL_OUTPUT_MODE,
|
WL_OUTPUT_MODE,
|
||||||
mode_flags,
|
mode_flags,
|
||||||
(int)output->crtc->rect.width,
|
(int)output->crtc->current_mode->width,
|
||||||
(int)output->crtc->rect.height,
|
(int)output->crtc->current_mode->height,
|
||||||
(int)output->crtc->current_mode->refresh_rate);
|
(int)output->crtc->current_mode->refresh_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* It's very important that we change the output pointer here, as
|
/* It's very important that we change the output pointer here, as
|
||||||
@@ -782,7 +785,7 @@ wayland_output_update_for_output (MetaWaylandOutput *wayland_output,
|
|||||||
|
|
||||||
static GHashTable *
|
static GHashTable *
|
||||||
meta_wayland_compositor_update_outputs (MetaWaylandCompositor *compositor,
|
meta_wayland_compositor_update_outputs (MetaWaylandCompositor *compositor,
|
||||||
MetaMonitorManager *monitors)
|
MetaMonitorManager *monitors)
|
||||||
{
|
{
|
||||||
MetaOutput *outputs;
|
MetaOutput *outputs;
|
||||||
unsigned int i, n_outputs;
|
unsigned int i, n_outputs;
|
||||||
@@ -798,24 +801,24 @@ meta_wayland_compositor_update_outputs (MetaWaylandCompositor *compositor,
|
|||||||
|
|
||||||
/* wayland does not expose disabled outputs */
|
/* wayland does not expose disabled outputs */
|
||||||
if (output->crtc == NULL)
|
if (output->crtc == NULL)
|
||||||
{
|
{
|
||||||
g_hash_table_remove (compositor->outputs, GSIZE_TO_POINTER (output->output_id));
|
g_hash_table_remove (compositor->outputs, GSIZE_TO_POINTER (output->output_id));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
wayland_output = g_hash_table_lookup (compositor->outputs, GSIZE_TO_POINTER (output->output_id));
|
wayland_output = g_hash_table_lookup (compositor->outputs, GSIZE_TO_POINTER (output->output_id));
|
||||||
|
|
||||||
if (wayland_output)
|
if (wayland_output)
|
||||||
{
|
{
|
||||||
g_hash_table_steal (compositor->outputs, GSIZE_TO_POINTER (output->output_id));
|
g_hash_table_steal (compositor->outputs, GSIZE_TO_POINTER (output->output_id));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
wayland_output = g_slice_new0 (MetaWaylandOutput);
|
wayland_output = g_slice_new0 (MetaWaylandOutput);
|
||||||
wayland_output->global = wl_global_create (compositor->wayland_display,
|
wayland_output->global = wl_global_create (compositor->wayland_display,
|
||||||
&wl_output_interface, 2,
|
&wl_output_interface, 2,
|
||||||
wayland_output, bind_output);
|
wayland_output, bind_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
wayland_output_update_for_output (wayland_output, output);
|
wayland_output_update_for_output (wayland_output, output);
|
||||||
g_hash_table_insert (new_table, GSIZE_TO_POINTER (output->output_id), wayland_output);
|
g_hash_table_insert (new_table, GSIZE_TO_POINTER (output->output_id), wayland_output);
|
||||||
@@ -1258,55 +1261,6 @@ bind_shell (struct wl_client *client,
|
|||||||
wl_resource_set_implementation (resource, &meta_wayland_shell_interface, data, NULL);
|
wl_resource_set_implementation (resource, &meta_wayland_shell_interface, data, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
gnome_session_died (GPid pid,
|
|
||||||
gint status,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
if (!WIFEXITED (status))
|
|
||||||
g_error ("gnome-session crashed; aborting");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* A clean exit of gnome-session implies a logout, exit cleanly */
|
|
||||||
meta_quit (META_EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
start_gnome_session (MetaWaylandCompositor *compositor)
|
|
||||||
{
|
|
||||||
GPid pid;
|
|
||||||
char *args[6];
|
|
||||||
GError *error;
|
|
||||||
|
|
||||||
args[0] = "setsid";
|
|
||||||
args[1] = "gnome-session";
|
|
||||||
args[2] = "--session";
|
|
||||||
args[3] = "gnome-wayland";
|
|
||||||
args[4] = "--debug";
|
|
||||||
args[5] = NULL;
|
|
||||||
|
|
||||||
error = NULL;
|
|
||||||
if (g_spawn_async (NULL, /* cwd */
|
|
||||||
args,
|
|
||||||
NULL,
|
|
||||||
G_SPAWN_SEARCH_PATH |
|
|
||||||
G_SPAWN_DO_NOT_REAP_CHILD,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
&pid,
|
|
||||||
&error))
|
|
||||||
{
|
|
||||||
g_message ("forked gnome-session, pid %d\n", pid);
|
|
||||||
|
|
||||||
g_child_watch_add (pid, gnome_session_died, NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_error ("Failed to fork gnome-session server: %s", error->message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
stage_destroy_cb (void)
|
stage_destroy_cb (void)
|
||||||
{
|
{
|
||||||
@@ -1429,11 +1383,11 @@ synthesize_motion_event (MetaWaylandCompositor *compositor,
|
|||||||
static void
|
static void
|
||||||
reset_idletimes (const ClutterEvent *event)
|
reset_idletimes (const ClutterEvent *event)
|
||||||
{
|
{
|
||||||
ClutterInputDevice *device;
|
ClutterInputDevice *device, *source_device;
|
||||||
MetaIdleMonitor *core_monitor, *device_monitor;
|
MetaIdleMonitor *core_monitor, *device_monitor;
|
||||||
int device_id;
|
int device_id;
|
||||||
|
|
||||||
device = clutter_event_get_source_device (event);
|
device = clutter_event_get_device (event);
|
||||||
device_id = clutter_input_device_get_device_id (device);
|
device_id = clutter_input_device_get_device_id (device);
|
||||||
|
|
||||||
core_monitor = meta_idle_monitor_get_core ();
|
core_monitor = meta_idle_monitor_get_core ();
|
||||||
@@ -1441,6 +1395,14 @@ reset_idletimes (const ClutterEvent *event)
|
|||||||
|
|
||||||
meta_idle_monitor_reset_idletime (core_monitor);
|
meta_idle_monitor_reset_idletime (core_monitor);
|
||||||
meta_idle_monitor_reset_idletime (device_monitor);
|
meta_idle_monitor_reset_idletime (device_monitor);
|
||||||
|
|
||||||
|
source_device = clutter_event_get_source_device (event);
|
||||||
|
if (source_device != device)
|
||||||
|
{
|
||||||
|
device_id = clutter_input_device_get_device_id (device);
|
||||||
|
device_monitor = meta_idle_monitor_get_for_device (device_id);
|
||||||
|
meta_idle_monitor_reset_idletime (device_monitor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@@ -1513,20 +1475,6 @@ event_cb (ClutterActor *stage,
|
|||||||
synthesize_motion_event (compositor, event);
|
synthesize_motion_event (compositor, event);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
case CLUTTER_KEY_PRESS:
|
|
||||||
case CLUTTER_KEY_RELEASE:
|
|
||||||
meta_verbose ("Clutter key event %s for key %d (%d), state %d\n",
|
|
||||||
event->type == CLUTTER_KEY_PRESS ? "press" : "release",
|
|
||||||
clutter_event_get_key_symbol (event),
|
|
||||||
clutter_event_get_key_code (event),
|
|
||||||
clutter_event_get_state (event));
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
case CLUTTER_SCROLL:
|
|
||||||
meta_verbose ("Clutter scroll event %s\n",
|
|
||||||
clutter_event_get_scroll_direction (event) == CLUTTER_SCROLL_DOWN ? "down" : "up");
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@@ -1584,101 +1532,19 @@ event_emission_hook_cb (GSignalInvocationHint *ihint,
|
|||||||
return TRUE /* stay connected */;
|
return TRUE /* stay connected */;
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
on_our_vt_enter (MetaTTY *tty,
|
|
||||||
MetaWaylandCompositor *compositor)
|
|
||||||
{
|
|
||||||
GError *error;
|
|
||||||
|
|
||||||
error = NULL;
|
|
||||||
if (!meta_weston_launch_set_master (compositor->weston_launch,
|
|
||||||
compositor->drm_fd, TRUE, &error))
|
|
||||||
{
|
|
||||||
g_warning ("Failed to become DRM master: %s", error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
clutter_evdev_reclaim_devices ();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
on_our_vt_leave (MetaTTY *tty,
|
|
||||||
MetaWaylandCompositor *compositor)
|
|
||||||
{
|
|
||||||
GError *error;
|
|
||||||
|
|
||||||
error = NULL;
|
|
||||||
if (!meta_weston_launch_set_master (compositor->weston_launch,
|
|
||||||
compositor->drm_fd, FALSE, &error))
|
|
||||||
{
|
|
||||||
g_warning ("Failed to release DRM master: %s", error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
clutter_evdev_release_devices ();
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
on_evdev_device_open (const char *path,
|
|
||||||
int flags,
|
|
||||||
gpointer user_data,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
MetaWaylandCompositor *compositor = user_data;
|
|
||||||
|
|
||||||
return meta_weston_launch_open_input_device (compositor->weston_launch,
|
|
||||||
path, flags, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_monitors_changed (MetaMonitorManager *monitors,
|
on_monitors_changed (MetaMonitorManager *monitors,
|
||||||
MetaWaylandCompositor *compositor)
|
MetaWaylandCompositor *compositor)
|
||||||
{
|
{
|
||||||
compositor->outputs = meta_wayland_compositor_update_outputs (compositor, monitors);
|
compositor->outputs = meta_wayland_compositor_update_outputs (compositor, monitors);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
on_display_config_ready (GObject *object,
|
|
||||||
GAsyncResult *result,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
gboolean ok;
|
|
||||||
|
|
||||||
ok = meta_monitor_manager_init_dbus_finish (META_MONITOR_MANAGER (object), result, NULL);
|
|
||||||
g_assert (ok);
|
|
||||||
|
|
||||||
meta_idle_monitor_init_dbus ();
|
|
||||||
|
|
||||||
/* Now we have X and DBus, and our stuff is on the bus.
|
|
||||||
The only thing missing is gnome-session! */
|
|
||||||
start_gnome_session (user_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_wayland_init (void)
|
meta_wayland_init (void)
|
||||||
{
|
{
|
||||||
MetaWaylandCompositor *compositor = &_meta_wayland_compositor;
|
MetaWaylandCompositor *compositor = &_meta_wayland_compositor;
|
||||||
guint event_signal;
|
guint event_signal;
|
||||||
ClutterBackend *backend;
|
|
||||||
CoglContext *cogl_context;
|
|
||||||
CoglRenderer *cogl_renderer;
|
|
||||||
int weston_launch_fd;
|
|
||||||
MetaMonitorManager *monitors;
|
MetaMonitorManager *monitors;
|
||||||
GDBusConnection *session_bus;
|
|
||||||
char *session_bus_address;
|
|
||||||
|
|
||||||
memset (compositor, 0, sizeof (MetaWaylandCompositor));
|
memset (compositor, 0, sizeof (MetaWaylandCompositor));
|
||||||
|
|
||||||
@@ -1715,76 +1581,18 @@ meta_wayland_init (void)
|
|||||||
|
|
||||||
clutter_wayland_set_compositor_display (compositor->wayland_display);
|
clutter_wayland_set_compositor_display (compositor->wayland_display);
|
||||||
|
|
||||||
/* We need to set this before clutter_init(), so we do it unconditionally.
|
|
||||||
It doesn't harm anyway to do it under X11 */
|
|
||||||
weston_launch_fd = env_get_fd ("WESTON_LAUNCHER_SOCK");
|
|
||||||
if (weston_launch_fd >= 0)
|
|
||||||
compositor->weston_launch = g_socket_new_from_fd (weston_launch_fd, NULL);
|
|
||||||
clutter_evdev_set_open_callback (on_evdev_device_open, compositor);
|
|
||||||
|
|
||||||
if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
|
if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
|
||||||
g_error ("Failed to initialize Clutter");
|
g_error ("Failed to initialize Clutter");
|
||||||
|
|
||||||
backend = clutter_get_default_backend ();
|
|
||||||
cogl_context = clutter_backend_get_cogl_context (backend);
|
|
||||||
cogl_renderer = cogl_display_get_renderer (cogl_context_get_display (cogl_context));
|
|
||||||
|
|
||||||
if (cogl_renderer_get_winsys_id (cogl_renderer) == COGL_WINSYS_ID_EGL_KMS)
|
|
||||||
compositor->drm_fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
|
|
||||||
else
|
|
||||||
compositor->drm_fd = -1;
|
|
||||||
|
|
||||||
if (compositor->drm_fd >= 0)
|
|
||||||
{
|
|
||||||
GError *error;
|
|
||||||
char path[PATH_MAX];
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
/* Running on bare metal, let's initalize DRM master and VT handling */
|
|
||||||
compositor->tty = meta_tty_new ();
|
|
||||||
if (compositor->tty)
|
|
||||||
{
|
|
||||||
g_signal_connect (compositor->tty, "enter", G_CALLBACK (on_our_vt_enter), compositor);
|
|
||||||
g_signal_connect (compositor->tty, "leave", G_CALLBACK (on_our_vt_leave), compositor);
|
|
||||||
}
|
|
||||||
|
|
||||||
error = NULL;
|
|
||||||
if (!meta_weston_launch_set_master (compositor->weston_launch,
|
|
||||||
compositor->drm_fd, TRUE, &error))
|
|
||||||
{
|
|
||||||
g_error ("Failed to become DRM master: %s", error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Open a log in the home directory. This is necessary because otherwise
|
|
||||||
all background processes (such as gnome-session and children) get SIGTTOU
|
|
||||||
trying to write to the terminal.
|
|
||||||
|
|
||||||
Then close (</dev/null) stdin, so we don't get SIGTTIN or other crazy stuff.
|
|
||||||
*/
|
|
||||||
snprintf(path, PATH_MAX, "%s/gnome-wayland.log", g_get_user_cache_dir ());
|
|
||||||
fd = open (path, O_WRONLY | O_APPEND | O_CREAT | O_TRUNC, 0600);
|
|
||||||
if (fd < 0)
|
|
||||||
fd = open ("/dev/null", O_WRONLY | O_NOCTTY, 0600);
|
|
||||||
|
|
||||||
dup2 (fd, STDOUT_FILENO);
|
|
||||||
dup2 (fd, STDERR_FILENO);
|
|
||||||
close (fd);
|
|
||||||
|
|
||||||
fd = open ("/dev/null", O_WRONLY | O_NOCTTY, 0600);
|
|
||||||
dup2 (fd, STDIN_FILENO);
|
|
||||||
}
|
|
||||||
|
|
||||||
meta_monitor_manager_initialize ();
|
meta_monitor_manager_initialize ();
|
||||||
monitors = meta_monitor_manager_get ();
|
monitors = meta_monitor_manager_get ();
|
||||||
g_signal_connect (monitors, "monitors-changed",
|
g_signal_connect (monitors, "monitors-changed",
|
||||||
G_CALLBACK (on_monitors_changed), compositor);
|
G_CALLBACK (on_monitors_changed), compositor);
|
||||||
|
|
||||||
compositor->outputs = g_hash_table_new_full (NULL, NULL, NULL, wayland_output_destroy_notify);
|
compositor->outputs = g_hash_table_new_full (NULL, NULL, NULL, wayland_output_destroy_notify);
|
||||||
compositor->outputs = meta_wayland_compositor_update_outputs (compositor, monitors);
|
compositor->outputs = meta_wayland_compositor_update_outputs (compositor, monitors);
|
||||||
|
|
||||||
compositor->stage = meta_wayland_stage_new ();
|
compositor->stage = meta_wayland_stage_new ();
|
||||||
|
|
||||||
g_signal_connect_after (compositor->stage, "paint",
|
g_signal_connect_after (compositor->stage, "paint",
|
||||||
G_CALLBACK (paint_finished_cb), compositor);
|
G_CALLBACK (paint_finished_cb), compositor);
|
||||||
g_signal_connect (compositor->stage, "destroy",
|
g_signal_connect (compositor->stage, "destroy",
|
||||||
@@ -1792,8 +1600,7 @@ meta_wayland_init (void)
|
|||||||
|
|
||||||
meta_wayland_data_device_manager_init (compositor->wayland_display);
|
meta_wayland_data_device_manager_init (compositor->wayland_display);
|
||||||
|
|
||||||
compositor->seat = meta_wayland_seat_new (compositor->wayland_display,
|
compositor->seat = meta_wayland_seat_new (compositor->wayland_display);
|
||||||
compositor->drm_fd >= 0);
|
|
||||||
|
|
||||||
g_signal_connect (compositor->stage,
|
g_signal_connect (compositor->stage,
|
||||||
"captured-event",
|
"captured-event",
|
||||||
@@ -1815,6 +1622,8 @@ meta_wayland_init (void)
|
|||||||
compositor, bind_shell) == NULL)
|
compositor, bind_shell) == NULL)
|
||||||
g_error ("Failed to register a global shell object");
|
g_error ("Failed to register a global shell object");
|
||||||
|
|
||||||
|
clutter_actor_show (compositor->stage);
|
||||||
|
|
||||||
if (wl_display_add_socket (compositor->wayland_display, "wayland-0"))
|
if (wl_display_add_socket (compositor->wayland_display, "wayland-0"))
|
||||||
g_error ("Failed to create socket");
|
g_error ("Failed to create socket");
|
||||||
|
|
||||||
@@ -1832,44 +1641,10 @@ meta_wayland_init (void)
|
|||||||
g_error ("Failed to start X Wayland");
|
g_error ("Failed to start X Wayland");
|
||||||
|
|
||||||
putenv (g_strdup_printf ("DISPLAY=:%d", compositor->xwayland_display_index));
|
putenv (g_strdup_printf ("DISPLAY=:%d", compositor->xwayland_display_index));
|
||||||
|
|
||||||
/* Now xwayland is ready. Get ourselves a dbus daemon. This will autolaunch
|
|
||||||
if no bus is found.
|
|
||||||
*/
|
|
||||||
session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
|
|
||||||
if (!session_bus)
|
|
||||||
meta_fatal ("Could not connect to the session bus\n");
|
|
||||||
|
|
||||||
session_bus_address = g_dbus_address_get_for_bus_sync (G_BUS_TYPE_SESSION, NULL, NULL);
|
|
||||||
putenv (g_strdup_printf ("DBUS_SESSION_BUS_ADDRESS=%s", session_bus_address));
|
|
||||||
g_free (session_bus_address);
|
|
||||||
|
|
||||||
/* Now get our interface on the dbus (or gnome-settings-daemon will refuse
|
|
||||||
to start, which in turn will stall gnome-session from launching the rest
|
|
||||||
of the session)
|
|
||||||
*/
|
|
||||||
meta_monitor_manager_init_dbus (monitors, on_display_config_ready, compositor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_wayland_finalize (void)
|
meta_wayland_finalize (void)
|
||||||
{
|
{
|
||||||
MetaWaylandCompositor *compositor;
|
meta_xwayland_stop (meta_wayland_compositor_get_default ());
|
||||||
|
|
||||||
compositor = meta_wayland_compositor_get_default ();
|
|
||||||
|
|
||||||
meta_xwayland_stop (compositor);
|
|
||||||
g_clear_object (&compositor->tty);
|
|
||||||
}
|
|
||||||
|
|
||||||
MetaTTY *
|
|
||||||
meta_wayland_compositor_get_tty (MetaWaylandCompositor *compositor)
|
|
||||||
{
|
|
||||||
return compositor->tty;
|
|
||||||
}
|
|
||||||
|
|
||||||
gboolean
|
|
||||||
meta_wayland_compositor_is_native (MetaWaylandCompositor *compositor)
|
|
||||||
{
|
|
||||||
return compositor->drm_fd >= 0;
|
|
||||||
}
|
}
|
||||||
|
@@ -1,203 +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 <gio/gio.h>
|
|
||||||
#include <gio/gunixfdmessage.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 "meta-weston-launch.h"
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
send_message_to_wl (GSocket *weston_launch,
|
|
||||||
void *message,
|
|
||||||
gsize size,
|
|
||||||
GSocketControlMessage *out_cmsg,
|
|
||||||
GSocketControlMessage **in_cmsg,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
int ok;
|
|
||||||
GInputVector in_iov = { &ok, sizeof (int) };
|
|
||||||
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 (weston_launch, NULL,
|
|
||||||
&out_iov, 1,
|
|
||||||
out_all_cmsg, -1,
|
|
||||||
flags, NULL, error) != (gssize)size)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if (g_socket_receive_message (weston_launch, NULL,
|
|
||||||
&in_iov, 1,
|
|
||||||
&in_all_cmsg, NULL,
|
|
||||||
&flags, NULL, error) != sizeof (int))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if (ok != 0)
|
|
||||||
{
|
|
||||||
if (ok == -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 (-ok),
|
|
||||||
"Got failure from weston-launch: %s", strerror (-ok));
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
gboolean
|
|
||||||
meta_weston_launch_set_master (GSocket *weston_launch,
|
|
||||||
int drm_fd,
|
|
||||||
gboolean master,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
if (weston_launch)
|
|
||||||
{
|
|
||||||
struct weston_launcher_set_master message;
|
|
||||||
GSocketControlMessage *cmsg;
|
|
||||||
gboolean ok;
|
|
||||||
|
|
||||||
message.header.opcode = WESTON_LAUNCHER_DRM_SET_MASTER;
|
|
||||||
message.set_master = master;
|
|
||||||
|
|
||||||
cmsg = g_unix_fd_message_new ();
|
|
||||||
if (g_unix_fd_message_append_fd (G_UNIX_FD_MESSAGE (cmsg),
|
|
||||||
drm_fd, error) == FALSE)
|
|
||||||
{
|
|
||||||
g_object_unref (cmsg);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ok = send_message_to_wl (weston_launch, &message, sizeof message, cmsg, NULL, error);
|
|
||||||
|
|
||||||
g_object_unref (cmsg);
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (master)
|
|
||||||
ret = drmSetMaster (drm_fd);
|
|
||||||
else
|
|
||||||
ret = drmDropMaster (drm_fd);
|
|
||||||
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret),
|
|
||||||
"Failed to set DRM master directly: %s", strerror (-ret));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
meta_weston_launch_open_input_device (GSocket *weston_launch,
|
|
||||||
const char *name,
|
|
||||||
int flags,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
if (weston_launch)
|
|
||||||
{
|
|
||||||
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 (weston_launch, 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;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = open (name, flags, 0);
|
|
||||||
|
|
||||||
if (ret < 0)
|
|
||||||
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno),
|
|
||||||
"Failed to open input device directly: %s", strerror (errno));
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@@ -1,56 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef META_WESTON_LAUNCH_H
|
|
||||||
#define META_WESTON_LAUNCH_H
|
|
||||||
|
|
||||||
#include <glib-object.h>
|
|
||||||
|
|
||||||
/* Keep this in sync with weston-launch */
|
|
||||||
|
|
||||||
enum weston_launcher_opcode {
|
|
||||||
WESTON_LAUNCHER_OPEN,
|
|
||||||
WESTON_LAUNCHER_DRM_SET_MASTER
|
|
||||||
};
|
|
||||||
|
|
||||||
struct weston_launcher_message {
|
|
||||||
int opcode;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct weston_launcher_open {
|
|
||||||
struct weston_launcher_message header;
|
|
||||||
int flags;
|
|
||||||
char path[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct weston_launcher_set_master {
|
|
||||||
struct weston_launcher_message header;
|
|
||||||
int set_master;
|
|
||||||
};
|
|
||||||
|
|
||||||
gboolean meta_weston_launch_set_master (GSocket *weston_launch,
|
|
||||||
int drm_fd,
|
|
||||||
gboolean master,
|
|
||||||
GError **error);
|
|
||||||
int meta_weston_launch_open_input_device (GSocket *weston_launch,
|
|
||||||
const char *name,
|
|
||||||
int flags,
|
|
||||||
GError **error);
|
|
||||||
|
|
||||||
#endif
|
|
@@ -27,6 +27,9 @@
|
|||||||
gboolean
|
gboolean
|
||||||
meta_xwayland_start (MetaWaylandCompositor *compositor);
|
meta_xwayland_start (MetaWaylandCompositor *compositor);
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_xwayland_complete_init (void);
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_xwayland_stop (MetaWaylandCompositor *compositor);
|
meta_xwayland_stop (MetaWaylandCompositor *compositor);
|
||||||
|
|
||||||
|
@@ -430,14 +430,19 @@ meta_xwayland_start (MetaWaylandCompositor *compositor)
|
|||||||
|
|
||||||
g_main_loop_run (compositor->init_loop);
|
g_main_loop_run (compositor->init_loop);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* To be called right after connecting */
|
||||||
|
void
|
||||||
|
meta_xwayland_complete_init (void)
|
||||||
|
{
|
||||||
/* We install an X IO error handler in addition to the child watch,
|
/* We install an X IO error handler in addition to the child watch,
|
||||||
because after Xlib connects our child watch may not be called soon
|
because after Xlib connects our child watch may not be called soon
|
||||||
enough, and therefore we won't crash when X exits (and most important
|
enough, and therefore we won't crash when X exits (and most important
|
||||||
we won't reset the tty).
|
we won't reset the tty).
|
||||||
*/
|
*/
|
||||||
XSetIOErrorHandler (x_io_error);
|
XSetIOErrorHandler (x_io_error);
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@@ -1,703 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <pwd.h>
|
|
||||||
#include <grp.h>
|
|
||||||
#include <security/pam_appl.h>
|
|
||||||
|
|
||||||
#include <xf86drm.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_SYSTEMD_LOGIN
|
|
||||||
#include <systemd/sd-login.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "weston-launch.h"
|
|
||||||
|
|
||||||
#define MAX_ARGV_SIZE 256
|
|
||||||
|
|
||||||
struct weston_launch {
|
|
||||||
struct pam_conv pc;
|
|
||||||
pam_handle_t *ph;
|
|
||||||
int tty;
|
|
||||||
int ttynr;
|
|
||||||
int sock[2];
|
|
||||||
struct passwd *pw;
|
|
||||||
|
|
||||||
int signalfd;
|
|
||||||
|
|
||||||
pid_t child;
|
|
||||||
int verbose;
|
|
||||||
char *new_user;
|
|
||||||
};
|
|
||||||
|
|
||||||
union cmsg_data { unsigned char b[4]; int fd; };
|
|
||||||
|
|
||||||
static gid_t *
|
|
||||||
read_groups(void)
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
gid_t *groups;
|
|
||||||
|
|
||||||
n = getgroups(0, NULL);
|
|
||||||
|
|
||||||
if (n < 0) {
|
|
||||||
fprintf(stderr, "Unable to retrieve groups: %m\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
groups = malloc(n * sizeof(gid_t));
|
|
||||||
if (!groups)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (getgroups(n, groups) < 0) {
|
|
||||||
fprintf(stderr, "Unable to retrieve groups: %m\n");
|
|
||||||
free(groups);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return groups;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
weston_launch_allowed(struct weston_launch *wl)
|
|
||||||
{
|
|
||||||
struct group *gr;
|
|
||||||
gid_t *groups;
|
|
||||||
int i;
|
|
||||||
#ifdef HAVE_SYSTEMD_LOGIN
|
|
||||||
char *session, *seat;
|
|
||||||
int err;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (getuid() == 0)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
gr = getgrnam("weston-launch");
|
|
||||||
if (gr) {
|
|
||||||
groups = read_groups();
|
|
||||||
if (groups) {
|
|
||||||
for (i = 0; groups[i]; ++i) {
|
|
||||||
if (groups[i] == gr->gr_gid) {
|
|
||||||
free(groups);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(groups);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_SYSTEMD_LOGIN
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
pam_conversation_fn(int msg_count,
|
|
||||||
const struct pam_message **messages,
|
|
||||||
struct pam_response **responses,
|
|
||||||
void *user_data)
|
|
||||||
{
|
|
||||||
return PAM_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
setup_pam(struct weston_launch *wl)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
|
|
||||||
wl->pc.conv = pam_conversation_fn;
|
|
||||||
wl->pc.appdata_ptr = wl;
|
|
||||||
|
|
||||||
err = pam_start("login", wl->pw->pw_name, &wl->pc, &wl->ph);
|
|
||||||
if (err != PAM_SUCCESS) {
|
|
||||||
fprintf(stderr, "failed to start pam transaction: %d: %s\n",
|
|
||||||
err, pam_strerror(wl->ph, err));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = pam_set_item(wl->ph, PAM_TTY, ttyname(wl->tty));
|
|
||||||
if (err != PAM_SUCCESS) {
|
|
||||||
fprintf(stderr, "failed to set PAM_TTY item: %d: %s\n",
|
|
||||||
err, pam_strerror(wl->ph, err));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = pam_open_session(wl->ph, 0);
|
|
||||||
if (err != PAM_SUCCESS) {
|
|
||||||
fprintf(stderr, "failed to open pam session: %d: %s\n",
|
|
||||||
err, pam_strerror(wl->ph, err));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
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_setmaster(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
|
|
||||||
{
|
|
||||||
int ret = -1;
|
|
||||||
struct cmsghdr *cmsg;
|
|
||||||
struct weston_launcher_set_master *message;
|
|
||||||
union cmsg_data *data;
|
|
||||||
|
|
||||||
if (len != sizeof(*message)) {
|
|
||||||
error(0, 0, "missing value in setmaster request");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
message = msg->msg_iov->iov_base;
|
|
||||||
|
|
||||||
cmsg = CMSG_FIRSTHDR(msg);
|
|
||||||
if (!cmsg ||
|
|
||||||
cmsg->cmsg_level != SOL_SOCKET ||
|
|
||||||
cmsg->cmsg_type != SCM_RIGHTS) {
|
|
||||||
error(0, 0, "invalid control message");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = (union cmsg_data *) CMSG_DATA(cmsg);
|
|
||||||
if (data->fd == -1) {
|
|
||||||
error(0, 0, "missing drm fd in socket request");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (message->set_master)
|
|
||||||
ret = drmSetMaster(data->fd);
|
|
||||||
else
|
|
||||||
ret = drmDropMaster(data->fd);
|
|
||||||
|
|
||||||
close(data->fd);
|
|
||||||
|
|
||||||
if (wl->verbose)
|
|
||||||
fprintf(stderr, "weston-launch: %sMaster, ret: %d, fd: %d\n",
|
|
||||||
message->set_master ? "set" : "drop", ret, data->fd);
|
|
||||||
|
|
||||||
out:
|
|
||||||
do {
|
|
||||||
len = send(wl->sock[0], &ret, sizeof ret, 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)
|
|
||||||
{
|
|
||||||
int fd = -1, ret = -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;
|
|
||||||
|
|
||||||
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)
|
|
||||||
goto err0;
|
|
||||||
|
|
||||||
fd = open(message->path, message->flags);
|
|
||||||
if (fd < 0) {
|
|
||||||
fprintf(stderr, "Error opening device %s: %m\n",
|
|
||||||
message->path);
|
|
||||||
goto err0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (major(s.st_rdev) != INPUT_MAJOR) {
|
|
||||||
close(fd);
|
|
||||||
fd = -1;
|
|
||||||
fprintf(stderr, "Device %s is not an input device\n",
|
|
||||||
message->path);
|
|
||||||
goto err0;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
ret = 0;
|
|
||||||
}
|
|
||||||
iov.iov_base = &ret;
|
|
||||||
iov.iov_len = sizeof ret;
|
|
||||||
|
|
||||||
if (wl->verbose)
|
|
||||||
fprintf(stderr, "weston-launch: opened %s: ret: %d, fd: %d\n",
|
|
||||||
message->path, 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_DRM_SET_MASTER:
|
|
||||||
ret = handle_setmaster(wl, &msg, len);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
quit(struct weston_launch *wl, int status)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
|
|
||||||
close(wl->signalfd);
|
|
||||||
close(wl->sock[0]);
|
|
||||||
|
|
||||||
if (wl->new_user) {
|
|
||||||
err = pam_close_session(wl->ph, 0);
|
|
||||||
if (err)
|
|
||||||
fprintf(stderr, "pam_close_session failed: %d: %s\n",
|
|
||||||
err, pam_strerror(wl->ph, err));
|
|
||||||
pam_end(wl->ph, err);
|
|
||||||
}
|
|
||||||
|
|
||||||
exit(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
default:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
setup_tty(struct weston_launch *wl, const char *tty)
|
|
||||||
{
|
|
||||||
struct stat buf;
|
|
||||||
char *t;
|
|
||||||
|
|
||||||
if (!wl->new_user) {
|
|
||||||
wl->tty = STDIN_FILENO;
|
|
||||||
} else if (tty) {
|
|
||||||
t = ttyname(STDIN_FILENO);
|
|
||||||
if (t && strcmp(t, tty) == 0)
|
|
||||||
wl->tty = STDIN_FILENO;
|
|
||||||
else
|
|
||||||
wl->tty = open(tty, O_RDWR | O_NOCTTY);
|
|
||||||
} else {
|
|
||||||
int tty0 = open("/dev/tty0", O_WRONLY | O_CLOEXEC);
|
|
||||||
char filename[16];
|
|
||||||
|
|
||||||
if (tty0 < 0)
|
|
||||||
error(1, errno, "could not open tty0");
|
|
||||||
|
|
||||||
if (ioctl(tty0, VT_OPENQRY, &wl->ttynr) < 0 || wl->ttynr == -1)
|
|
||||||
error(1, errno, "failed to find non-opened console");
|
|
||||||
|
|
||||||
snprintf(filename, sizeof filename, "/dev/tty%d", wl->ttynr);
|
|
||||||
wl->tty = open(filename, O_RDWR | O_NOCTTY);
|
|
||||||
close(tty0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wl->tty < 0)
|
|
||||||
error(1, errno, "failed to open tty");
|
|
||||||
|
|
||||||
if (tty) {
|
|
||||||
if (fstat(wl->tty, &buf) < 0)
|
|
||||||
error(1, errno, "stat %s failed", tty);
|
|
||||||
|
|
||||||
if (major(buf.st_rdev) != TTY_MAJOR)
|
|
||||||
error(1, 0, "invalid tty device: %s", tty);
|
|
||||||
|
|
||||||
wl->ttynr = minor(buf.st_rdev);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
setup_session(struct weston_launch *wl)
|
|
||||||
{
|
|
||||||
char **env;
|
|
||||||
char *term;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (wl->tty != STDIN_FILENO) {
|
|
||||||
if (setsid() < 0)
|
|
||||||
error(1, errno, "setsid failed");
|
|
||||||
if (ioctl(wl->tty, TIOCSCTTY, 0) < 0)
|
|
||||||
error(1, errno, "TIOCSCTTY failed - tty is in use");
|
|
||||||
}
|
|
||||||
|
|
||||||
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");
|
|
||||||
|
|
||||||
term = getenv("TERM");
|
|
||||||
clearenv();
|
|
||||||
setenv("TERM", term, 1);
|
|
||||||
setenv("USER", wl->pw->pw_name, 1);
|
|
||||||
setenv("LOGNAME", wl->pw->pw_name, 1);
|
|
||||||
setenv("HOME", wl->pw->pw_dir, 1);
|
|
||||||
setenv("SHELL", wl->pw->pw_shell, 1);
|
|
||||||
|
|
||||||
env = pam_getenvlist(wl->ph);
|
|
||||||
if (env) {
|
|
||||||
for (i = 0; env[i]; ++i) {
|
|
||||||
if (putenv(env[i]) < 0)
|
|
||||||
error(0, 0, "putenv %s failed", env[i]);
|
|
||||||
}
|
|
||||||
free(env);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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());
|
|
||||||
if (wl->new_user)
|
|
||||||
setup_session(wl);
|
|
||||||
|
|
||||||
if (wl->tty != STDIN_FILENO)
|
|
||||||
setenv_fd("WESTON_TTY_FD", wl->tty);
|
|
||||||
|
|
||||||
setenv_fd("WESTON_LAUNCHER_SOCK", wl->sock[1]);
|
|
||||||
|
|
||||||
unsetenv("DISPLAY");
|
|
||||||
|
|
||||||
/* Do not give our signal mask to the new process. */
|
|
||||||
sigemptyset(&mask);
|
|
||||||
sigaddset(&mask, SIGTERM);
|
|
||||||
sigaddset(&mask, SIGCHLD);
|
|
||||||
sigaddset(&mask, SIGINT);
|
|
||||||
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, " -t, --tty Start session on alternative tty\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;
|
|
||||||
char *tty = NULL;
|
|
||||||
struct option opts[] = {
|
|
||||||
{ "user", required_argument, NULL, 'u' },
|
|
||||||
{ "tty", required_argument, NULL, 't' },
|
|
||||||
{ "verbose", no_argument, NULL, 'v' },
|
|
||||||
{ "help", no_argument, NULL, 'h' },
|
|
||||||
{ 0, 0, NULL, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
memset(&wl, 0, sizeof wl);
|
|
||||||
|
|
||||||
while ((c = getopt_long(argc, argv, "u:t::vh", opts, &i)) != -1) {
|
|
||||||
switch (c) {
|
|
||||||
case 'u':
|
|
||||||
wl.new_user = optarg;
|
|
||||||
if (getuid() != 0)
|
|
||||||
error(1, 0, "Permission denied. -u allowed for root only");
|
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
tty = optarg;
|
|
||||||
break;
|
|
||||||
case 'v':
|
|
||||||
wl.verbose = 1;
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
help("weston-launch");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((argc - optind) > (MAX_ARGV_SIZE - 6))
|
|
||||||
error(1, E2BIG, "Too many arguments to pass to weston");
|
|
||||||
|
|
||||||
if (strcmp (argv[optind], "mutter") &&
|
|
||||||
strcmp (argv[optind], "gnome-shell") &&
|
|
||||||
strcmp (argv[optind], "gnome-shell-real") && 0)
|
|
||||||
error(1, 0, "mutter-launch can only be used to launch mutter or gnome-shell");
|
|
||||||
|
|
||||||
if (wl.new_user)
|
|
||||||
wl.pw = getpwnam(wl.new_user);
|
|
||||||
else
|
|
||||||
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 should either:\n"
|
|
||||||
#ifdef HAVE_SYSTEMD_LOGIN
|
|
||||||
" - run from an active and local (systemd) session.\n"
|
|
||||||
#else
|
|
||||||
" - enable systemd session support for weston-launch.\n"
|
|
||||||
#endif
|
|
||||||
" - or add yourself to the 'weston-launch' group.");
|
|
||||||
|
|
||||||
if (setup_tty(&wl, tty) < 0)
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
|
|
||||||
if (wl.new_user && setup_pam(&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]);
|
|
||||||
if (wl.tty != STDIN_FILENO)
|
|
||||||
close(wl.tty);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
@@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _WESTON_LAUNCH_H_
|
|
||||||
#define _WESTON_LAUNCH_H_
|
|
||||||
|
|
||||||
enum weston_launcher_opcode {
|
|
||||||
WESTON_LAUNCHER_OPEN,
|
|
||||||
WESTON_LAUNCHER_DRM_SET_MASTER
|
|
||||||
};
|
|
||||||
|
|
||||||
struct weston_launcher_message {
|
|
||||||
int opcode;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct weston_launcher_open {
|
|
||||||
struct weston_launcher_message header;
|
|
||||||
int flags;
|
|
||||||
char path[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct weston_launcher_set_master {
|
|
||||||
struct weston_launcher_message header;
|
|
||||||
int set_master;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@@ -149,11 +149,9 @@
|
|||||||
|
|
||||||
@serial must match the serial from the last GetResources() call,
|
@serial must match the serial from the last GetResources() call,
|
||||||
or org.freedesktop.DBus.AccessDenied will be generated.
|
or org.freedesktop.DBus.AccessDenied will be generated.
|
||||||
(XXX: a better error maybe?)
|
|
||||||
|
|
||||||
If @persistent is true, mutter will attempt to replicate this
|
If @persistent is true, mutter will attempt to replicate this
|
||||||
configuration the next time this HW layout appears.
|
configuration the next time this HW layout appears.
|
||||||
(XXX: or is this gnome-settings-daemon role?)
|
|
||||||
|
|
||||||
@crtcs represents the new logical configuration, as a list
|
@crtcs represents the new logical configuration, as a list
|
||||||
of structures containing:
|
of structures containing:
|
||||||
@@ -207,11 +205,14 @@
|
|||||||
|
|
||||||
Changes the backlight of @output to @value, which is
|
Changes the backlight of @output to @value, which is
|
||||||
expressed as a percentage and rounded to the HW limits.
|
expressed as a percentage and rounded to the HW limits.
|
||||||
|
|
||||||
|
Returns the new value after rounding.
|
||||||
-->
|
-->
|
||||||
<method name="ChangeBacklight">
|
<method name="ChangeBacklight">
|
||||||
<arg name="serial" direction="in" type="u" />
|
<arg name="serial" direction="in" type="u" />
|
||||||
<arg name="output" direction="in" type="u" />
|
<arg name="output" direction="in" type="u" />
|
||||||
<arg name="value" direction="in" type="i" />
|
<arg name="value" direction="in" type="i" />
|
||||||
|
<arg name="new_value" direction="out" type="i" />
|
||||||
</method>
|
</method>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
@@ -279,5 +280,14 @@
|
|||||||
XRandR interface directly).
|
XRandR interface directly).
|
||||||
-->
|
-->
|
||||||
<property name="PowerSaveMode" type="i" access="readwrite" />
|
<property name="PowerSaveMode" type="i" access="readwrite" />
|
||||||
|
|
||||||
|
<!--
|
||||||
|
MonitorsChanged:
|
||||||
|
|
||||||
|
The signal is emitted every time the screen configuration
|
||||||
|
changes.
|
||||||
|
The client should then call GetResources() to read the new layout.
|
||||||
|
-->
|
||||||
|
<signal name="MonitorsChanged" />
|
||||||
</interface>
|
</interface>
|
||||||
</node>
|
</node>
|
||||||
|
Reference in New Issue
Block a user