Compare commits
2 Commits
3.13.1
...
wip/split-
Author | SHA1 | Date | |
---|---|---|---|
b9d798c213 | |||
5abf41ab5a |
8
.gitignore
vendored
8
.gitignore
vendored
@ -22,7 +22,7 @@ missing
|
||||
src/50-mutter-navigation.xml
|
||||
src/50-mutter-system.xml
|
||||
src/50-mutter-windows.xml
|
||||
src/mutter.desktop
|
||||
src/mutter-wm.desktop
|
||||
src/mutter-wayland.desktop
|
||||
*.o
|
||||
*.a
|
||||
@ -46,8 +46,8 @@ POTFILES
|
||||
po/*.pot
|
||||
50-metacity-desktop-key.xml
|
||||
50-metacity-key.xml
|
||||
libmutter.pc
|
||||
mutter
|
||||
libmutter-wayland.pc
|
||||
mutter-wayland
|
||||
mutter-launch
|
||||
org.gnome.mutter.gschema.valid
|
||||
org.gnome.mutter.gschema.xml
|
||||
@ -56,7 +56,6 @@ org.gnome.mutter.wayland.gschema.xml
|
||||
testasyncgetprop
|
||||
testboxes
|
||||
testgradient
|
||||
m4/*
|
||||
mutter-grayscale
|
||||
mutter-mag
|
||||
mutter-message
|
||||
@ -78,6 +77,7 @@ src/mutter-marshal.[ch]
|
||||
src/stamp-mutter-marshal.h
|
||||
src/meta-dbus-display-config.[ch]
|
||||
src/meta-dbus-idle-monitor.[ch]
|
||||
src/mutter-plugins.pc
|
||||
src/gtk-shell-protocol.c
|
||||
src/gtk-shell-server-protocol.h
|
||||
src/xdg-shell-protocol.c
|
||||
|
@ -1,8 +1,6 @@
|
||||
|
||||
SUBDIRS=src po doc
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
|
||||
|
||||
DISTCLEANFILES = intltool-extract intltool-merge intltool-update po/stamp-it po/.intltool-merge-cache
|
||||
|
||||
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
|
||||
|
30
NEWS
30
NEWS
@ -1,33 +1,3 @@
|
||||
3.13.1
|
||||
======
|
||||
* Fix opacity values from _NET_WM_WINDOW_OPACITY [Nirbheek; #727874]
|
||||
* Merge wayland branch [Jasper, Giovanni, Robert B., Neil, Adel, Rui, Jonas,
|
||||
Lionel, Tim, Owen, Florian, Colin W., Cosimo, Ray, Kalev, Pavel, Robert A.,
|
||||
Magdalen, Marek, Matthias, Alban, Seán, Daniel, Stefano, Carlos, Colin G.,
|
||||
Andreas, Alexander, Ryan, Marc-André, Asad, Alberto, Bastien, Hans,
|
||||
Debarshi, Sindhu, Andika, Rico, Olav]
|
||||
* Don't prevent workspace switches for present_with_time() [Florian; #728018]
|
||||
* Add shortcuts for switching to the last workspace [Elad; #659288]
|
||||
* Make move/resize menu items behave like the keybindings [Jasper; #728617]
|
||||
* Misc. bug fixes and cleanups [Jasper, Bastien, Florian, Adel; #720631,
|
||||
#727979, #728423, #728395, #729044]
|
||||
|
||||
Contributors:
|
||||
Jonas Ådahl, Elad Alfassa, Robert Ancell, Magdalen Berns, Robert Bragg,
|
||||
Giovanni Campagna, Cosimo Cecchi, Marek Chalupa, Nirbheek Chauhan,
|
||||
Matthias Clasen, Alban Crequy, Seán de Búrca, Daniel Drake, Jason Ekstrand,
|
||||
Stefano Facchini, Adel Gadllah, Carlos Garnacho, Colin Guthrie,
|
||||
Andreas Heider, Lionel Landwerlin, Alexander Larsson, Kalev Lember,
|
||||
Ryan Lortie, Tim Lunn, Marc-André Lureau, Rui Matos, Asad Mehmood,
|
||||
Alberto Milone, Florian Müllner, Bastien Nocera, Hans Petter Jansson,
|
||||
Debarshi Ray, Neil Roberts, Sindhu S, Jasper St. Pierre, Ray Strode,
|
||||
Andika Triwidada, Rico Tzschichholz, Pavel Vasin, Olav Vitters,
|
||||
Colin Walters, A. Walton, Owen W. Taylor
|
||||
|
||||
Translations:
|
||||
Inaki Larranaga Murgoitio [eu], marablack3 [el], Daniel Mustieles [es],
|
||||
Fran Diéguez [gl], Yosef Or Boczko [he], Dirgita [id]
|
||||
|
||||
3.12.0
|
||||
======
|
||||
* Fix grab issue with SSD xwayland windows [Rui; #726123]
|
||||
|
73
configure.ac
73
configure.ac
@ -2,8 +2,8 @@ AC_PREREQ(2.50)
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
m4_define([mutter_major_version], [3])
|
||||
m4_define([mutter_minor_version], [13])
|
||||
m4_define([mutter_micro_version], [1])
|
||||
m4_define([mutter_minor_version], [12])
|
||||
m4_define([mutter_micro_version], [0])
|
||||
|
||||
m4_define([mutter_version],
|
||||
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
||||
@ -13,7 +13,6 @@ m4_define([mutter_plugin_api_version], [3])
|
||||
AC_INIT([mutter], [mutter_version],
|
||||
[http://bugzilla.gnome.org/enter_bug.cgi?product=mutter])
|
||||
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_SRCDIR(src/core/display.c)
|
||||
AC_CONFIG_HEADERS(config.h)
|
||||
|
||||
@ -21,6 +20,10 @@ AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz tar-ustar subdir-objects])
|
||||
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],)
|
||||
AM_MAINTAINER_MODE([enable])
|
||||
|
||||
# Change pkglibdir and pkgdatadir to mutter-wayland instead of mutter
|
||||
PACKAGE="mutter-wayland"
|
||||
AC_SUBST([PACKAGE], [$PACKAGE])
|
||||
|
||||
MUTTER_MAJOR_VERSION=mutter_major_version
|
||||
MUTTER_MINOR_VERSION=mutter_minor_version
|
||||
MUTTER_MICRO_VERSION=mutter_micro_version
|
||||
@ -36,7 +39,7 @@ AC_SUBST(MUTTER_PLUGIN_DIR)
|
||||
# Honor aclocal flags
|
||||
AC_SUBST(ACLOCAL_AMFLAGS, "\${ACLOCAL_FLAGS}")
|
||||
|
||||
GETTEXT_PACKAGE=mutter
|
||||
GETTEXT_PACKAGE=mutter-wayland
|
||||
AC_SUBST(GETTEXT_PACKAGE)
|
||||
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[Name of default gettext domain])
|
||||
|
||||
@ -69,12 +72,12 @@ CANBERRA_GTK_VERSION=0.26
|
||||
CLUTTER_PACKAGE=clutter-1.0
|
||||
|
||||
MUTTER_PC_MODULES="
|
||||
gtk+-3.0 >= 3.9.11
|
||||
gtk+-3.0 >= 3.3.7
|
||||
gio-2.0 >= 2.25.10
|
||||
pango >= 1.2.0
|
||||
cairo >= 1.10.0
|
||||
gsettings-desktop-schemas >= 3.7.3
|
||||
xcomposite >= 0.2 xfixes xext xdamage xi >= 1.6.0
|
||||
xcomposite >= 0.2 xfixes xrender xdamage xi >= 1.6.0
|
||||
$CLUTTER_PACKAGE >= 1.17.5
|
||||
cogl-1.0 >= 1.17.1
|
||||
upower-glib >= 0.99.0
|
||||
@ -130,7 +133,7 @@ AC_ARG_WITH([wayland-protocols],
|
||||
AC_ARG_WITH([xwayland-path],
|
||||
[AS_HELP_STRING([--with-xwayland-path], [Absolute path for an X Wayland server])],
|
||||
[XWAYLAND_PATH="$withval"],
|
||||
[XWAYLAND_PATH="$bindir/Xwayland"])
|
||||
[XWAYLAND_PATH="$bindir/Xorg"])
|
||||
|
||||
AM_GLIB_GNU_GETTEXT
|
||||
|
||||
@ -249,6 +252,28 @@ if test x$have_xinerama = xno; then
|
||||
AC_MSG_ERROR([Xinerama extension was not found])
|
||||
fi
|
||||
|
||||
SHAPE_LIBS=
|
||||
found_shape=no
|
||||
AC_CHECK_LIB(Xext, XShapeQueryExtension,
|
||||
[AC_CHECK_HEADER(X11/extensions/shape.h,
|
||||
SHAPE_LIBS=-lXext found_shape=yes)],
|
||||
, $ALL_X_LIBS)
|
||||
|
||||
if test x$enable_shape = xno; then
|
||||
found_shape=no
|
||||
fi
|
||||
|
||||
if test x$enable_shape = xyes; then
|
||||
if test "$found_shape" = "no"; then
|
||||
AC_MSG_ERROR([--enable-shape forced and Shape not found])
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "x$found_shape" = "xyes"; then
|
||||
AC_DEFINE(HAVE_SHAPE, , [Have the shape extension library])
|
||||
fi
|
||||
|
||||
found_xkb=no
|
||||
AC_CHECK_LIB(X11, XkbQueryExtension,
|
||||
[AC_CHECK_HEADER(X11/XKBlib.h,
|
||||
@ -266,13 +291,37 @@ AC_CHECK_LIB(Xrandr, XRRUpdateConfiguration,
|
||||
[AC_CHECK_HEADER(X11/extensions/Xrandr.h,
|
||||
RANDR_LIBS=-lXrandr found_randr=yes,,
|
||||
[#include <X11/Xlib.h>])],
|
||||
, -lXext $ALL_X_LIBS)
|
||||
, -lXrender -lXext $ALL_X_LIBS)
|
||||
|
||||
if test "x$found_randr" = "xyes"; then
|
||||
AC_DEFINE(HAVE_RANDR, , [Have the Xrandr extension library])
|
||||
fi
|
||||
|
||||
MUTTER_LIBS="$MUTTER_LIBS $RANDR_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm"
|
||||
XSYNC_LIBS=
|
||||
found_xsync=no
|
||||
AC_CHECK_LIB(Xext, XSyncQueryExtension,
|
||||
[AC_CHECK_HEADER(X11/extensions/sync.h,
|
||||
found_xsync=yes,,
|
||||
[#include <X11/Xlib.h>])],
|
||||
, $ALL_X_LIBS)
|
||||
|
||||
if test x$enable_xsync = xno; then
|
||||
found_xsync=no
|
||||
fi
|
||||
|
||||
if test x$enable_xsync = xyes; then
|
||||
if test "$found_xsync" = "no"; then
|
||||
AC_MSG_ERROR([--enable-xsync forced and XSync not found])
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "x$found_xsync" = "xyes"; then
|
||||
XSYNC_LIBS=-lXext
|
||||
AC_DEFINE(HAVE_XSYNC, , [Have the Xsync extension library])
|
||||
fi
|
||||
|
||||
MUTTER_LIBS="$MUTTER_LIBS $XSYNC_LIBS $RANDR_LIBS $SHAPE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm"
|
||||
|
||||
found_sm=no
|
||||
case "$MUTTER_LIBS" in
|
||||
@ -402,7 +451,7 @@ doc/man/Makefile
|
||||
doc/reference/Makefile
|
||||
doc/reference/meta-docs.sgml
|
||||
src/Makefile
|
||||
src/libmutter.pc
|
||||
src/libmutter-wayland.pc
|
||||
src/compositor/plugins/Makefile
|
||||
po/Makefile.in
|
||||
])
|
||||
@ -419,7 +468,7 @@ fi
|
||||
|
||||
dnl ==========================================================================
|
||||
echo "
|
||||
mutter-$VERSION
|
||||
mutter-wayland-$VERSION
|
||||
|
||||
prefix: ${prefix}
|
||||
source code location: ${srcdir}
|
||||
@ -429,6 +478,8 @@ mutter-$VERSION
|
||||
libcanberra: ${have_libcanberra}
|
||||
Introspection: ${found_introspection}
|
||||
Session management: ${found_sm}
|
||||
Shape extension: ${found_shape}
|
||||
Xsync: ${found_xsync}
|
||||
"
|
||||
|
||||
|
||||
|
@ -1,3 +0,0 @@
|
||||
defaultcursordir = $(datadir)/mutter/cursors
|
||||
|
||||
dist_defaultcursor_DATA = left_ptr.png
|
@ -140,7 +140,7 @@ expand_content_files= \
|
||||
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
|
||||
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
|
||||
GTKDOC_CFLAGS=$(MUTTER_CFLAGS)
|
||||
GTKDOC_LIBS=$(MUTTER_LIBS) $(top_builddir)/src/libmutter.la
|
||||
GTKDOC_LIBS=$(MUTTER_LIBS) $(top_builddir)/src/libmutter-wayland.la
|
||||
|
||||
# This includes the standard gtk-doc make rules, copied by gtkdocize.
|
||||
include $(top_srcdir)/gtk-doc.make
|
||||
|
@ -21,6 +21,7 @@ environment.</description>
|
||||
-->
|
||||
<mailing-list rdf:resource="http://mail.gnome.org/mailman/listinfo/gnome-shell-list" />
|
||||
<download-page rdf:resource="http://download.gnome.org/sources/mutter/" />
|
||||
<download-page rdf:resource="http://download.gnome.org/sources/mutter-wayland/" />
|
||||
<bug-database rdf:resource="http://bugzilla.gnome.org/browse.cgi?product=mutter" />
|
||||
|
||||
<category rdf:resource="http://api.gnome.org/doap-extensions#desktop" />
|
||||
|
@ -3,7 +3,6 @@
|
||||
src/50-mutter-navigation.xml.in
|
||||
src/50-mutter-system.xml.in
|
||||
src/50-mutter-windows.xml.in
|
||||
src/backends/meta-monitor-manager.c
|
||||
src/compositor/compositor.c
|
||||
src/compositor/meta-background.c
|
||||
src/core/bell.c
|
||||
@ -13,12 +12,16 @@ src/core/display.c
|
||||
src/core/errors.c
|
||||
src/core/keybindings.c
|
||||
src/core/main.c
|
||||
src/core/monitor.c
|
||||
src/core/mutter.c
|
||||
src/core/prefs.c
|
||||
src/core/screen.c
|
||||
src/x11/session.c
|
||||
src/core/util.c
|
||||
src/core/window.c
|
||||
src/mutter.desktop.in
|
||||
src/x11/window-props.c
|
||||
src/x11/xprops.c
|
||||
src/mutter-wayland.desktop.in
|
||||
src/org.gnome.mutter.gschema.xml.in
|
||||
src/org.gnome.mutter.wayland.gschema.xml.in
|
||||
src/ui/frames.c
|
||||
@ -27,6 +30,3 @@ src/ui/metaaccellabel.c
|
||||
src/ui/resizepopup.c
|
||||
src/ui/theme.c
|
||||
src/ui/theme-parser.c
|
||||
src/x11/session.c
|
||||
src/x11/window-props.c
|
||||
src/x11/xprops.c
|
||||
|
2834
po/ca@valencia.po
2834
po/ca@valencia.po
File diff suppressed because it is too large
Load Diff
805
po/pt_BR.po
805
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
417
po/sk.po
417
po/sk.po
@ -13,9 +13,9 @@ msgstr ""
|
||||
"Project-Id-Version: mutter\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
|
||||
"product=mutter&keywords=I18N+L10N&component=general\n"
|
||||
"POT-Creation-Date: 2013-08-21 17:41+0000\n"
|
||||
"PO-Revision-Date: 2013-08-02 14:46+0200\n"
|
||||
"Last-Translator: Ján Kyselica <kyselica.jan@gmail.com>\n"
|
||||
"POT-Creation-Date: 2013-05-24 21:44+0000\n"
|
||||
"PO-Revision-Date: 2013-05-18 16:53+0100\n"
|
||||
"Last-Translator: Jan Kyselica <kyselica.jan@gmail.com>\n"
|
||||
"Language-Team: Slovak <gnome-sk-list@gnome.org>\n"
|
||||
"Language: sk\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -87,8 +87,9 @@ msgstr "Prepnúť okná aplikácie"
|
||||
# PK: zisti co to robi
|
||||
# description
|
||||
#: ../src/50-mutter-navigation.xml.in.h:13
|
||||
#, fuzzy
|
||||
msgid "Switch system controls"
|
||||
msgstr "Prepnúť medzi ovládacími prvkami systému"
|
||||
msgstr "Prepnúť medzi systémovými ovládacími prvkami"
|
||||
|
||||
# description
|
||||
#: ../src/50-mutter-navigation.xml.in.h:14
|
||||
@ -103,8 +104,9 @@ msgstr "Prepnúť okná aplikácie priamo"
|
||||
# MČ: podobne ako vyššie: „cycle-panels“
|
||||
# description
|
||||
#: ../src/50-mutter-navigation.xml.in.h:16
|
||||
#, fuzzy
|
||||
msgid "Switch system controls directly"
|
||||
msgstr "Prepnúť medzi ovládacími prvkami systému priamo"
|
||||
msgstr "Prepnúť medzi systémovými ovládacími prvkami priamo"
|
||||
|
||||
# description
|
||||
#: ../src/50-mutter-navigation.xml.in.h:17
|
||||
@ -265,13 +267,13 @@ msgstr "Zobraziť rozdelenie napravo"
|
||||
# PK: je %i cislo obrazovky? ak ano tak "č. %i"
|
||||
#. This probably means that a non-WM compositor like xcompmgr is running;
|
||||
#. * we have no way to get it to exit
|
||||
#: ../src/compositor/compositor.c:596
|
||||
#, c-format
|
||||
#: ../src/compositor/compositor.c:571
|
||||
#, fuzzy, c-format
|
||||
msgid ""
|
||||
"Another compositing manager is already running on screen %i on display \"%s"
|
||||
"\"."
|
||||
msgstr ""
|
||||
"Pre obrazovku č. %i na displeji „%s“ je spustený už iný správca rozloženia."
|
||||
"Pre obrazovku %i na displeji „%s“ je spustený už iný správca rozloženia."
|
||||
|
||||
#: ../src/compositor/meta-background.c:1076
|
||||
msgid "background texture could not be created from file"
|
||||
@ -311,18 +313,18 @@ msgstr "_Počkať"
|
||||
msgid "_Force Quit"
|
||||
msgstr "_Vynútiť ukončenie"
|
||||
|
||||
#: ../src/core/display.c:421
|
||||
#: ../src/core/display.c:401
|
||||
#, c-format
|
||||
msgid "Missing %s extension required for compositing"
|
||||
msgstr "Rozšírenie %s, potrebné pre kompozitné prostredie, chýba"
|
||||
|
||||
# X window system preloz, napr. system na spravu okien X
|
||||
#: ../src/core/display.c:513
|
||||
#: ../src/core/display.c:493
|
||||
#, c-format
|
||||
msgid "Failed to open X Window System display '%s'\n"
|
||||
msgstr "Zlyhalo otvorenie displeja systému na správu okien X „%s“\n"
|
||||
|
||||
#: ../src/core/keybindings.c:1136
|
||||
#: ../src/core/keybindings.c:970
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Some other program is already using the key %s with modifiers %x as a "
|
||||
@ -330,7 +332,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Iný program už používa kláves %s s modifikátormi %x ako klávesovú skratku\n"
|
||||
|
||||
#: ../src/core/keybindings.c:1333
|
||||
#: ../src/core/keybindings.c:1151
|
||||
#, c-format
|
||||
msgid "\"%s\" is not a valid accelerator\n"
|
||||
msgstr "„%s“ nie je platný akcelerátor\n"
|
||||
@ -376,20 +378,6 @@ msgid ""
|
||||
msgstr ""
|
||||
"Nepodarilo sa nájsť tému! Overte, že %s existuje a obsahuje obvyklé témy.\n"
|
||||
|
||||
#: ../src/core/monitor.c:702
|
||||
msgid "Built-in display"
|
||||
msgstr "Vstavaný displej"
|
||||
|
||||
#. TRANSLATORS: this is a monitor name (in case we don't know
|
||||
#. the vendor), it's Unknown followed by a size in inches,
|
||||
#. like 'Unknown 15"'
|
||||
#.
|
||||
#: ../src/core/monitor.c:730
|
||||
#, c-format
|
||||
#| msgid "Unknown element %s"
|
||||
msgid "Unknown %s"
|
||||
msgstr "Neznámy %s"
|
||||
|
||||
#: ../src/core/mutter.c:40
|
||||
#, c-format
|
||||
msgid ""
|
||||
@ -415,7 +403,7 @@ msgstr "Zobrazí verziu"
|
||||
msgid "Mutter plugin to use"
|
||||
msgstr "Použije zásuvný modul Mutter"
|
||||
|
||||
#: ../src/core/prefs.c:1202
|
||||
#: ../src/core/prefs.c:1193
|
||||
msgid ""
|
||||
"Workarounds for broken applications disabled. Some applications may not "
|
||||
"behave properly.\n"
|
||||
@ -423,12 +411,12 @@ msgstr ""
|
||||
"Náhradné riešenia pre chybné aplikácie nie sú povolené. Niektoré aplikácie "
|
||||
"sa nemusia správať správne.\n"
|
||||
|
||||
#: ../src/core/prefs.c:1277
|
||||
#: ../src/core/prefs.c:1268
|
||||
#, c-format
|
||||
msgid "Could not parse font description \"%s\" from GSettings key %s\n"
|
||||
msgstr "Nepodarilo sa spracovať popis písma „%s“ z kľúča GSettings %s\n"
|
||||
|
||||
#: ../src/core/prefs.c:1343
|
||||
#: ../src/core/prefs.c:1334
|
||||
#, c-format
|
||||
msgid ""
|
||||
"\"%s\" found in configuration database is not a valid value for mouse button "
|
||||
@ -437,7 +425,7 @@ msgstr ""
|
||||
"V konfiguračnej databáze sa našlo „%s“, čo nie je platná hodnota pre "
|
||||
"modifikátor tlačidla myši\n"
|
||||
|
||||
#: ../src/core/prefs.c:1909
|
||||
#: ../src/core/prefs.c:1881
|
||||
#, c-format
|
||||
msgid ""
|
||||
"\"%s\" found in configuration database is not a valid value for keybinding "
|
||||
@ -446,17 +434,17 @@ msgstr ""
|
||||
"V konfiguračnej databáze sa našlo „%s“, čo nie je platná hodnota pre "
|
||||
"klávesovú skratku „%s“\n"
|
||||
|
||||
#: ../src/core/prefs.c:1999
|
||||
#: ../src/core/prefs.c:1945
|
||||
#, c-format
|
||||
msgid "Workspace %d"
|
||||
msgstr "Pracovný priestor č. %d"
|
||||
|
||||
#: ../src/core/screen.c:537
|
||||
#: ../src/core/screen.c:691
|
||||
#, c-format
|
||||
msgid "Screen %d on display '%s' is invalid\n"
|
||||
msgstr "Obrazovka č. %d na displeji „%s“ nie je platná\n"
|
||||
|
||||
#: ../src/core/screen.c:553
|
||||
#: ../src/core/screen.c:707
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Screen %d on display \"%s\" already has a window manager; try using the --"
|
||||
@ -465,7 +453,7 @@ msgstr ""
|
||||
"Obrazovka č. %d na displeji „%s“ už má správcu okien. Skúste použiť prepínač "
|
||||
"--replace, aby sa aktuálny správca nahradil.\n"
|
||||
|
||||
#: ../src/core/screen.c:580
|
||||
#: ../src/core/screen.c:734
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Could not acquire window manager selection on screen %d display \"%s\"\n"
|
||||
@ -473,12 +461,12 @@ msgstr ""
|
||||
"Nepodarilo sa získať výber správcu okien pre obrazovku č. %d na displeji "
|
||||
"„%s“\n"
|
||||
|
||||
#: ../src/core/screen.c:658
|
||||
#: ../src/core/screen.c:812
|
||||
#, c-format
|
||||
msgid "Screen %d on display \"%s\" already has a window manager\n"
|
||||
msgstr "Obrazovka č. %d na displeji „%s“ už má správcu okien\n"
|
||||
|
||||
#: ../src/core/screen.c:850
|
||||
#: ../src/core/screen.c:998
|
||||
#, c-format
|
||||
msgid "Could not release screen %d on display \"%s\"\n"
|
||||
msgstr "Nepodarilo sa uvoľniť obrazovku č. %d na displeji „%s“\n"
|
||||
@ -554,7 +542,8 @@ msgstr "Zlyhalo otvorenie súboru so záznamom pomocou fdopen() %s: %s\n"
|
||||
msgid "Opened log file %s\n"
|
||||
msgstr "Otvorený súbor so záznamom %s\n"
|
||||
|
||||
#: ../src/core/util.c:119
|
||||
#: ../src/core/util.c:119 ../src/tools/mutter-message.c:149
|
||||
#, c-format
|
||||
msgid "Mutter was compiled without support for verbose mode\n"
|
||||
msgstr "Mutter bol skompilovaný bez výpisu podrobností pri behu\n"
|
||||
|
||||
@ -562,20 +551,20 @@ msgstr "Mutter bol skompilovaný bez výpisu podrobností pri behu\n"
|
||||
msgid "Window manager: "
|
||||
msgstr "Správca okien: "
|
||||
|
||||
#: ../src/core/util.c:414
|
||||
#: ../src/core/util.c:412
|
||||
msgid "Bug in window manager: "
|
||||
msgstr "Chyba v správcovi okien: "
|
||||
|
||||
#: ../src/core/util.c:445
|
||||
#: ../src/core/util.c:443
|
||||
msgid "Window manager warning: "
|
||||
msgstr "Varovanie správcu okien: "
|
||||
|
||||
#: ../src/core/util.c:473
|
||||
#: ../src/core/util.c:471
|
||||
msgid "Window manager error: "
|
||||
msgstr "Chyba správcu okien: "
|
||||
|
||||
#. first time through
|
||||
#: ../src/core/window.c:7533
|
||||
#: ../src/core/window.c:7505
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER "
|
||||
@ -591,7 +580,7 @@ msgstr ""
|
||||
#. * MWM but not WM_NORMAL_HINTS are basically broken. We complain
|
||||
#. * about these apps but make them work.
|
||||
#.
|
||||
#: ../src/core/window.c:8257
|
||||
#: ../src/core/window.c:8229
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Window %s sets an MWM hint indicating it isn't resizable, but sets min size "
|
||||
@ -601,7 +590,7 @@ msgstr ""
|
||||
"nastavuje minimálnu veľkosť %d x %d a maximálnu veľkosť %d x %d. To nedáva "
|
||||
"zmysel.\n"
|
||||
|
||||
#: ../src/core/window-props.c:347
|
||||
#: ../src/core/window-props.c:318
|
||||
#, c-format
|
||||
msgid "Application set a bogus _NET_WM_PID %lu\n"
|
||||
msgstr "Aplikácia nastavila neplatné _NET_WM_PID %lu\n"
|
||||
@ -609,18 +598,18 @@ msgstr "Aplikácia nastavila neplatné _NET_WM_PID %lu\n"
|
||||
# PK: co je toto?
|
||||
# JK: nedokazem zistit
|
||||
# PM: vyžiadaj komentár od vývojárov, pomožeme aj ostatným prekladateľom
|
||||
#: ../src/core/window-props.c:463
|
||||
#: ../src/core/window-props.c:434
|
||||
#, fuzzy, c-format
|
||||
msgid "%s (on %s)"
|
||||
msgstr "%s (na %s)"
|
||||
|
||||
#: ../src/core/window-props.c:1546
|
||||
#: ../src/core/window-props.c:1517
|
||||
#, c-format
|
||||
msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n"
|
||||
msgstr "Neplatné WM_TRANSIENT_FOR okno 0x%lx nastavené pre %s.\n"
|
||||
|
||||
# MČ: zacykliť sa, alebo vytvoriť slučku.
|
||||
#: ../src/core/window-props.c:1557
|
||||
#: ../src/core/window-props.c:1528
|
||||
#, c-format
|
||||
msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n"
|
||||
msgstr "WM_TRANSIENT_FOR okno 0x%lx pre %s môže vytvoriť slučku.\n"
|
||||
@ -708,9 +697,9 @@ msgid ""
|
||||
"vertically and resizes them horizontally to cover half of the available "
|
||||
"area. Dropping windows on the top screen edge maximizes them completely."
|
||||
msgstr ""
|
||||
"Ak je povolené, upustenie okien pri zvislých okrajoch obrazovky ich zvislo "
|
||||
"maximalizuje a vodorovná veľkosť sa zmení na polovicu dostupnej plochy. "
|
||||
"Upustenie okien pri vrchnom okraji obrazovky ich maximalizuje úplne."
|
||||
"Ak je povolené, upustenie okien pri zvislých okrajoch obrazovky ich "
|
||||
"zvislo maximalizuje a vodorovná veľkosť sa zmení na polovicu dostupnej "
|
||||
"plochy. Upustenie okien pri vrchnom okraji obrazovky ich maximalizuje úplne."
|
||||
|
||||
# summary
|
||||
#: ../src/org.gnome.mutter.gschema.xml.in.h:7
|
||||
@ -746,8 +735,9 @@ msgstr ""
|
||||
# PM: ja by som dal Bez vyvovlávania tabulátorom
|
||||
# summary
|
||||
#: ../src/org.gnome.mutter.gschema.xml.in.h:11
|
||||
#, fuzzy
|
||||
msgid "No tab popup"
|
||||
msgstr "Bez vyvolávania tabulátorom"
|
||||
msgstr "Nepoužívať prekryvnú ponuku tabulátora"
|
||||
|
||||
# MČ: Neviem, čo to presne má robiť, ale popis som pochopil inak. „…či sa má používať rozbaľovacia ponuka a zvýraznenie rámikom sa má vypnúť…“
|
||||
# description
|
||||
@ -816,104 +806,109 @@ msgstr "Vybrať okno z rozbaľovacej ponuky tabulátoru"
|
||||
msgid "Cancel tab popup"
|
||||
msgstr "Zrušit rozbaľovaciu ponuku tabulátoru"
|
||||
|
||||
#: ../src/tools/mutter-message.c:123
|
||||
#, c-format
|
||||
msgid "Usage: %s\n"
|
||||
msgstr "Použitie: %s\n"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:67
|
||||
#: ../src/ui/menu.c:69
|
||||
msgid "Mi_nimize"
|
||||
msgstr "Mi_nimalizovať"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:69
|
||||
#: ../src/ui/menu.c:71
|
||||
msgid "Ma_ximize"
|
||||
msgstr "Ma_ximalizovať"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:71
|
||||
#: ../src/ui/menu.c:73
|
||||
msgid "Unma_ximize"
|
||||
msgstr "Zrušiť ma_ximalizáciu"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:73
|
||||
#: ../src/ui/menu.c:75
|
||||
msgid "Roll _Up"
|
||||
msgstr "_Zabaliť"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:75
|
||||
#: ../src/ui/menu.c:77
|
||||
msgid "_Unroll"
|
||||
msgstr "_Rozbaliť"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:77
|
||||
#: ../src/ui/menu.c:79
|
||||
msgid "_Move"
|
||||
msgstr "Pre_miestniť"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:79
|
||||
#: ../src/ui/menu.c:81
|
||||
msgid "_Resize"
|
||||
msgstr "Zmeniť veľko_sť"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:81
|
||||
#: ../src/ui/menu.c:83
|
||||
msgid "Move Titlebar On_screen"
|
||||
msgstr "Presunúť titulok na _obrazovku"
|
||||
|
||||
#. separator
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:84 ../src/ui/menu.c:86
|
||||
#: ../src/ui/menu.c:86 ../src/ui/menu.c:88
|
||||
msgid "Always on _Top"
|
||||
msgstr "Vždy na_vrchu"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:88
|
||||
#: ../src/ui/menu.c:90
|
||||
msgid "_Always on Visible Workspace"
|
||||
msgstr "Vž_dy na viditeľnom pracovnom priestore"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:90
|
||||
#: ../src/ui/menu.c:92
|
||||
msgid "_Only on This Workspace"
|
||||
msgstr "_Len na tomto pracovnom priestore"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:92
|
||||
#: ../src/ui/menu.c:94
|
||||
msgid "Move to Workspace _Left"
|
||||
msgstr "Presunúť na pracovný priestor vľav_o"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:94
|
||||
#: ../src/ui/menu.c:96
|
||||
msgid "Move to Workspace R_ight"
|
||||
msgstr "Presunúť na pracovný priestor v_pravo"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:96
|
||||
#: ../src/ui/menu.c:98
|
||||
msgid "Move to Workspace _Up"
|
||||
msgstr "Presunúť na pracovný priestor _hore"
|
||||
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:98
|
||||
#: ../src/ui/menu.c:100
|
||||
msgid "Move to Workspace _Down"
|
||||
msgstr "Presunúť na pracovný priestor _dole"
|
||||
|
||||
#. separator
|
||||
#. Translators: Translate this string the same way as you do in libwnck!
|
||||
#: ../src/ui/menu.c:102
|
||||
#: ../src/ui/menu.c:104
|
||||
msgid "_Close"
|
||||
msgstr "_Zavrieť"
|
||||
|
||||
#: ../src/ui/menu.c:202
|
||||
#: ../src/ui/menu.c:204
|
||||
#, c-format
|
||||
msgid "Workspace %d%n"
|
||||
msgstr "Pracovná priestor %d%n"
|
||||
|
||||
#: ../src/ui/menu.c:212
|
||||
#: ../src/ui/menu.c:214
|
||||
#, c-format
|
||||
msgid "Workspace 1_0"
|
||||
msgstr "Pracovný priestor 1_0"
|
||||
|
||||
#: ../src/ui/menu.c:214
|
||||
#: ../src/ui/menu.c:216
|
||||
#, c-format
|
||||
msgid "Workspace %s%d"
|
||||
msgstr "Pracovný priestor %s%d"
|
||||
|
||||
#: ../src/ui/menu.c:384
|
||||
#: ../src/ui/menu.c:397
|
||||
msgid "Move to Another _Workspace"
|
||||
msgstr "P_resunúť na iný pracovný priestor"
|
||||
|
||||
@ -1071,21 +1066,21 @@ msgstr ""
|
||||
# MČ: Preformuloval by som koniec: „platné sú len znaky A-Za-z0-9-_“
|
||||
# PK: color_name je asi nejaky atribut, to sa nepreklada, ked tak do zatvorky
|
||||
#: ../src/ui/theme.c:1219
|
||||
#, c-format
|
||||
#, fuzzy, c-format
|
||||
msgid ""
|
||||
"Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-"
|
||||
"_ are valid"
|
||||
msgstr ""
|
||||
"V parametri color_name (názov farby) pre gtk:custom je neplatný znak „%c“, platné sú len "
|
||||
"V parametri názov_farby pre gtk:custom je neplatný znak „%c“, platné sú len "
|
||||
"znaky A-Za-z0-9-_"
|
||||
|
||||
#: ../src/ui/theme.c:1233
|
||||
#, c-format
|
||||
#, fuzzy, c-format
|
||||
msgid ""
|
||||
"Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not "
|
||||
"fit the format"
|
||||
msgstr ""
|
||||
"Formát Gtk:custom je „gtk:custom(color_name,fallback)“, „%s“ tomu "
|
||||
"Formát Gtk:custom je „gtk:custom(názov_farby,fallback)“, „%s“ tomu "
|
||||
"nezodpovedá"
|
||||
|
||||
#: ../src/ui/theme.c:1278
|
||||
@ -1271,20 +1266,20 @@ msgid ""
|
||||
"Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>"
|
||||
msgstr "Chýbajúce <frame state=„%s“ resize=„%s“ focus=„%s“ style=„whatever“/>"
|
||||
|
||||
#: ../src/ui/theme.c:5082
|
||||
#: ../src/ui/theme.c:5084
|
||||
#, c-format
|
||||
msgid "Failed to load theme \"%s\": %s\n"
|
||||
msgstr "Zlyhalo načítanie témy „%s“: %s\n"
|
||||
|
||||
# PK: prvok?
|
||||
# JK: XML značka (XML tag)
|
||||
#: ../src/ui/theme.c:5218 ../src/ui/theme.c:5225 ../src/ui/theme.c:5232
|
||||
#: ../src/ui/theme.c:5239 ../src/ui/theme.c:5246
|
||||
#: ../src/ui/theme.c:5220 ../src/ui/theme.c:5227 ../src/ui/theme.c:5234
|
||||
#: ../src/ui/theme.c:5241 ../src/ui/theme.c:5248
|
||||
#, c-format
|
||||
msgid "No <%s> set for theme \"%s\""
|
||||
msgstr "Pre tému „%s“ nie je nastavená <%s>"
|
||||
|
||||
#: ../src/ui/theme.c:5254
|
||||
#: ../src/ui/theme.c:5256
|
||||
#, c-format
|
||||
msgid ""
|
||||
"No frame style set for window type \"%s\" in theme \"%s\", add a <window "
|
||||
@ -1293,13 +1288,13 @@ msgstr ""
|
||||
"Pre typ okna „%s“ nie je sada štýlov v téme „%s“, pridajte prvok <window "
|
||||
"type=„%s“ style_set=„whatever“/>"
|
||||
|
||||
#: ../src/ui/theme.c:5661 ../src/ui/theme.c:5723 ../src/ui/theme.c:5786
|
||||
#: ../src/ui/theme.c:5663 ../src/ui/theme.c:5725 ../src/ui/theme.c:5788
|
||||
#, c-format
|
||||
msgid ""
|
||||
"User-defined constants must begin with a capital letter; \"%s\" does not"
|
||||
msgstr "Používateľské konštanty musia začínať veľkým písmenom, „%s“ nezačína"
|
||||
|
||||
#: ../src/ui/theme.c:5669 ../src/ui/theme.c:5731 ../src/ui/theme.c:5794
|
||||
#: ../src/ui/theme.c:5671 ../src/ui/theme.c:5733 ../src/ui/theme.c:5796
|
||||
#, c-format
|
||||
msgid "Constant \"%s\" has already been defined"
|
||||
msgstr "Konštanta „%s“ už je definovaná"
|
||||
@ -1402,7 +1397,7 @@ msgstr "<%s> musí uvádzať buď geometriu alebo rodiča, ktorý má geometriu"
|
||||
msgid "You must specify a background for an alpha value to be meaningful"
|
||||
msgstr "Ak má byť hodnota alpha zmysluplná, tak musíte vybrať nejaké pozadie"
|
||||
|
||||
# PM: asi atribút type
|
||||
# PM: asi atribút type
|
||||
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=698123
|
||||
#: ../src/ui/theme-parser.c:1264
|
||||
#, fuzzy, c-format
|
||||
@ -1564,7 +1559,6 @@ msgid "\"%s\" is not a valid value for resize attribute"
|
||||
msgstr "„%s“ nie je platná hodnota pre atribút zmeny veľkosti"
|
||||
|
||||
# PK: shaded states? to zatvorky daj popis co je resize
|
||||
# PM: skôr "pre stavy maximized (maximalizovaný)/shaded (zatienený)"
|
||||
#: ../src/ui/theme-parser.c:3147
|
||||
#, fuzzy, c-format
|
||||
msgid ""
|
||||
@ -1706,172 +1700,221 @@ msgstr "<%s> uvedený dvakrát pre túto tému"
|
||||
msgid "Failed to find a valid file for theme %s\n"
|
||||
msgstr "Zlyhalo nájdenie platného súboru pre tému%s\n"
|
||||
|
||||
#~ msgid "Usage: %s\n"
|
||||
#~ msgstr "Použitie: %s\n"
|
||||
#: ../src/ui/theme-viewer.c:99
|
||||
msgid "_Windows"
|
||||
msgstr "_Okná"
|
||||
|
||||
#~ msgid "_Windows"
|
||||
#~ msgstr "_Okná"
|
||||
#: ../src/ui/theme-viewer.c:100
|
||||
msgid "_Dialog"
|
||||
msgstr "_Dialógové okno"
|
||||
|
||||
#~ msgid "_Dialog"
|
||||
#~ msgstr "_Dialógové okno"
|
||||
#: ../src/ui/theme-viewer.c:101
|
||||
msgid "_Modal dialog"
|
||||
msgstr "_Modálne dialógové okno"
|
||||
|
||||
#~ msgid "_Modal dialog"
|
||||
#~ msgstr "_Modálne dialógové okno"
|
||||
#: ../src/ui/theme-viewer.c:102
|
||||
msgid "_Utility"
|
||||
msgstr "_Nástroje"
|
||||
|
||||
#~ msgid "_Utility"
|
||||
#~ msgstr "_Nástroje"
|
||||
|
||||
#~ msgid "_Splashscreen"
|
||||
#~ msgstr "Ú_vodná obrazovka"
|
||||
#: ../src/ui/theme-viewer.c:103
|
||||
msgid "_Splashscreen"
|
||||
msgstr "Ú_vodná obrazovka"
|
||||
|
||||
# MČ: nie som si istý prekladom „dok“, nemal by to byť „panel“?
|
||||
#~ msgid "_Top dock"
|
||||
#~ msgstr "_Horný panel"
|
||||
#: ../src/ui/theme-viewer.c:104
|
||||
msgid "_Top dock"
|
||||
msgstr "_Horný panel"
|
||||
|
||||
#~ msgid "_Bottom dock"
|
||||
#~ msgstr "_Spodný panel"
|
||||
#: ../src/ui/theme-viewer.c:105
|
||||
msgid "_Bottom dock"
|
||||
msgstr "_Spodný panel"
|
||||
|
||||
#~ msgid "_Left dock"
|
||||
#~ msgstr "Ľ_avý panel"
|
||||
#: ../src/ui/theme-viewer.c:106
|
||||
msgid "_Left dock"
|
||||
msgstr "Ľ_avý panel"
|
||||
|
||||
#~ msgid "_Right dock"
|
||||
#~ msgstr "_Pravý panel"
|
||||
#: ../src/ui/theme-viewer.c:107
|
||||
msgid "_Right dock"
|
||||
msgstr "_Pravý panel"
|
||||
|
||||
#~ msgid "_All docks"
|
||||
#~ msgstr "_Všetky panely"
|
||||
#: ../src/ui/theme-viewer.c:108
|
||||
msgid "_All docks"
|
||||
msgstr "_Všetky panely"
|
||||
|
||||
#~ msgid "Des_ktop"
|
||||
#~ msgstr "P_racovná plocha"
|
||||
#: ../src/ui/theme-viewer.c:109
|
||||
msgid "Des_ktop"
|
||||
msgstr "P_racovná plocha"
|
||||
|
||||
# tooltip
|
||||
#~ msgid "Open another one of these windows"
|
||||
#~ msgstr "Otvorí ďalšie z týchto okien"
|
||||
#: ../src/ui/theme-viewer.c:115
|
||||
msgid "Open another one of these windows"
|
||||
msgstr "Otvorí ďalšie z týchto okien"
|
||||
|
||||
# PK: prekladat to v uvodzovkach? nahlas bug
|
||||
# tooltip
|
||||
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=698123
|
||||
#: ../src/ui/theme-viewer.c:117
|
||||
#, fuzzy
|
||||
#~ msgid "This is a demo button with an 'open' icon"
|
||||
#~ msgstr "Toto je ukážkové tlačidlo s ikonou „open“"
|
||||
msgid "This is a demo button with an 'open' icon"
|
||||
msgstr "Toto je ukážkové tlačidlo s ikonou „open“"
|
||||
|
||||
# tooltip
|
||||
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=698123
|
||||
#: ../src/ui/theme-viewer.c:119
|
||||
#, fuzzy
|
||||
#~ msgid "This is a demo button with a 'quit' icon"
|
||||
#~ msgstr "Toto je ukážkové tlačidlo s ikonou „quit“"
|
||||
msgid "This is a demo button with a 'quit' icon"
|
||||
msgstr "Toto je ukážkové tlačidlo s ikonou „quit“"
|
||||
|
||||
# label
|
||||
#~ msgid "This is a sample message in a sample dialog"
|
||||
#~ msgstr "Toto je ukážková správa v ukážkovom dialógovom okne"
|
||||
#: ../src/ui/theme-viewer.c:248
|
||||
msgid "This is a sample message in a sample dialog"
|
||||
msgstr "Toto je ukážková správa v ukážkovom dialógovom okne"
|
||||
|
||||
# PK: falosna
|
||||
#~ msgid "Fake menu item %d\n"
|
||||
#~ msgstr "Falošná položka ponuky č. %d\n"
|
||||
#: ../src/ui/theme-viewer.c:328
|
||||
#, c-format
|
||||
msgid "Fake menu item %d\n"
|
||||
msgstr "Falošná položka ponuky č. %d\n"
|
||||
|
||||
#~ msgid "Border-only window"
|
||||
#~ msgstr "Okno len s okrajom"
|
||||
#: ../src/ui/theme-viewer.c:363
|
||||
msgid "Border-only window"
|
||||
msgstr "Okno len s okrajom"
|
||||
|
||||
#~ msgid "Bar"
|
||||
#~ msgstr "Lišta"
|
||||
#: ../src/ui/theme-viewer.c:365
|
||||
msgid "Bar"
|
||||
msgstr "Lišta"
|
||||
|
||||
#~ msgid "Normal Application Window"
|
||||
#~ msgstr "Normálne aplikačné okno"
|
||||
#: ../src/ui/theme-viewer.c:382
|
||||
msgid "Normal Application Window"
|
||||
msgstr "Normálne aplikačné okno"
|
||||
|
||||
#~ msgid "Dialog Box"
|
||||
#~ msgstr "Dialógové okno"
|
||||
#: ../src/ui/theme-viewer.c:386
|
||||
msgid "Dialog Box"
|
||||
msgstr "Dialógové okno"
|
||||
|
||||
#~ msgid "Modal Dialog Box"
|
||||
#~ msgstr "Modálne dialógové okno"
|
||||
#: ../src/ui/theme-viewer.c:390
|
||||
msgid "Modal Dialog Box"
|
||||
msgstr "Modálne dialógové okno"
|
||||
|
||||
#~ msgid "Utility Palette"
|
||||
#~ msgstr "Paleta nástrojov"
|
||||
#: ../src/ui/theme-viewer.c:394
|
||||
msgid "Utility Palette"
|
||||
msgstr "Paleta nástrojov"
|
||||
|
||||
#~ msgid "Torn-off Menu"
|
||||
#~ msgstr "Vypnúť ponuku"
|
||||
#: ../src/ui/theme-viewer.c:398
|
||||
msgid "Torn-off Menu"
|
||||
msgstr "Vypnúť ponuku"
|
||||
|
||||
#~ msgid "Border"
|
||||
#~ msgstr "Okraj"
|
||||
#: ../src/ui/theme-viewer.c:402
|
||||
msgid "Border"
|
||||
msgstr "Okraj"
|
||||
|
||||
#~ msgid "Attached Modal Dialog"
|
||||
#~ msgstr "Pričlenené modálne okno"
|
||||
#: ../src/ui/theme-viewer.c:406
|
||||
msgid "Attached Modal Dialog"
|
||||
msgstr "Pričlenené modálne okno"
|
||||
|
||||
#~ msgid "Button layout test %d"
|
||||
#~ msgstr "Test rozloženia tlačidiel č. %d"
|
||||
#: ../src/ui/theme-viewer.c:737
|
||||
#, c-format
|
||||
msgid "Button layout test %d"
|
||||
msgstr "Test rozloženia tlačidiel č. %d"
|
||||
|
||||
# PK: plural forms
|
||||
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=697987
|
||||
#, fuzzy
|
||||
#~ msgid "%g milliseconds to draw one window frame"
|
||||
#~ msgstr "%g milisekúnd pre vykreslenie jedného rámca okna"
|
||||
#: ../src/ui/theme-viewer.c:766
|
||||
#, fuzzy, c-format
|
||||
msgid "%g milliseconds to draw one window frame"
|
||||
msgstr "%g milisekúnd pre vykreslenie jedného rámca okna"
|
||||
|
||||
#~ msgid "Usage: metacity-theme-viewer [THEMENAME]\n"
|
||||
#~ msgstr "Použitie: metacity-theme-viewer [NÁZOVTÉMY]\n"
|
||||
#: ../src/ui/theme-viewer.c:811
|
||||
#, c-format
|
||||
msgid "Usage: metacity-theme-viewer [THEMENAME]\n"
|
||||
msgstr "Použitie: metacity-theme-viewer [NÁZOVTÉMY]\n"
|
||||
|
||||
#~ msgid "Error loading theme: %s\n"
|
||||
#~ msgstr "Chyba pri načítavaní témy: %s\n"
|
||||
#: ../src/ui/theme-viewer.c:818
|
||||
#, c-format
|
||||
msgid "Error loading theme: %s\n"
|
||||
msgstr "Chyba pri načítavaní témy: %s\n"
|
||||
|
||||
# PK: plural forms
|
||||
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=697987
|
||||
#, fuzzy
|
||||
#~ msgid "Loaded theme \"%s\" in %g seconds\n"
|
||||
#~ msgstr "Téma „%s“ načítaná za %g sekúnd\n"
|
||||
#: ../src/ui/theme-viewer.c:824
|
||||
#, fuzzy, c-format
|
||||
msgid "Loaded theme \"%s\" in %g seconds\n"
|
||||
msgstr "Téma „%s“ načítaná za %g sekúnd\n"
|
||||
|
||||
# PK: inde titulku, aky je rozdiel
|
||||
#~ msgid "Normal Title Font"
|
||||
#~ msgstr "Obyčajné písmo titulku"
|
||||
#: ../src/ui/theme-viewer.c:869
|
||||
msgid "Normal Title Font"
|
||||
msgstr "Obyčajné písmo titulku"
|
||||
|
||||
#~ msgid "Small Title Font"
|
||||
#~ msgstr "Malé písmo titulku"
|
||||
#: ../src/ui/theme-viewer.c:875
|
||||
msgid "Small Title Font"
|
||||
msgstr "Malé písmo titulku"
|
||||
|
||||
#~ msgid "Large Title Font"
|
||||
#~ msgstr "Veľké písmo titulku"
|
||||
#: ../src/ui/theme-viewer.c:881
|
||||
msgid "Large Title Font"
|
||||
msgstr "Veľké písmo titulku"
|
||||
|
||||
#~ msgid "Button Layouts"
|
||||
#~ msgstr "Rozloženia tlačidiel"
|
||||
#: ../src/ui/theme-viewer.c:886
|
||||
msgid "Button Layouts"
|
||||
msgstr "Rozloženia tlačidiel"
|
||||
|
||||
#~ msgid "Benchmark"
|
||||
#~ msgstr "Test rýchlosti"
|
||||
#: ../src/ui/theme-viewer.c:891
|
||||
msgid "Benchmark"
|
||||
msgstr "Test rýchlosti"
|
||||
|
||||
#~ msgid "Window Title Goes Here"
|
||||
#~ msgstr "Sem príde názov okna"
|
||||
#: ../src/ui/theme-viewer.c:947
|
||||
msgid "Window Title Goes Here"
|
||||
msgstr "Sem príde názov okna"
|
||||
|
||||
# PK: plural forms
|
||||
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=697987
|
||||
#, fuzzy
|
||||
#~ msgid ""
|
||||
#~ "Drew %d frames in %g client-side seconds (%g milliseconds per frame) and "
|
||||
#~ "%g seconds wall clock time including X server resources (%g milliseconds "
|
||||
#~ "per frame)\n"
|
||||
#~ msgstr ""
|
||||
#~ "Vykreslených %d rámcov za %g sekúnd na strane klienta (%g milisekúnd na "
|
||||
#~ "rámec) a %g sekúnd celkového času vrátane zdrojov servera X (%g "
|
||||
#~ "milisekúnd na rámec)\n"
|
||||
#: ../src/ui/theme-viewer.c:1053
|
||||
#, fuzzy, c-format
|
||||
msgid ""
|
||||
"Drew %d frames in %g client-side seconds (%g milliseconds per frame) and %g "
|
||||
"seconds wall clock time including X server resources (%g milliseconds per "
|
||||
"frame)\n"
|
||||
msgstr ""
|
||||
"Vykreslených %d rámcov za %g sekúnd na strane klienta (%g milisekúnd na "
|
||||
"rámec) a %g sekúnd celkového času vrátane zdrojov servera X (%g milisekúnd "
|
||||
"na rámec)\n"
|
||||
|
||||
#~ msgid "position expression test returned TRUE but set error"
|
||||
#~ msgstr "test výrazu polohy vrátil TRUE, ale nastavil chybu"
|
||||
#: ../src/ui/theme-viewer.c:1273
|
||||
msgid "position expression test returned TRUE but set error"
|
||||
msgstr "test výrazu polohy vrátil TRUE, ale nastavil chybu"
|
||||
|
||||
#~ msgid "position expression test returned FALSE but didn't set error"
|
||||
#~ msgstr "test výrazu polohy vrátil FALSE, ale nenastavil chybu"
|
||||
#: ../src/ui/theme-viewer.c:1275
|
||||
msgid "position expression test returned FALSE but didn't set error"
|
||||
msgstr "test výrazu polohy vrátil FALSE, ale nenastavil chybu"
|
||||
|
||||
#~ msgid "Error was expected but none given"
|
||||
#~ msgstr "Bola očakávaná chyba, ale žiadna nenastala"
|
||||
#: ../src/ui/theme-viewer.c:1279
|
||||
msgid "Error was expected but none given"
|
||||
msgstr "Bola očakávaná chyba, ale žiadna nenastala"
|
||||
|
||||
#~ msgid "Error %d was expected but %d given"
|
||||
#~ msgstr "Bola očakávaná chyba %d, ale nastala %d"
|
||||
#: ../src/ui/theme-viewer.c:1281
|
||||
#, c-format
|
||||
msgid "Error %d was expected but %d given"
|
||||
msgstr "Bola očakávaná chyba %d, ale nastala %d"
|
||||
|
||||
#~ msgid "Error not expected but one was returned: %s"
|
||||
#~ msgstr "Chyba nebola očakávaná, ale bola vrátená: %s"
|
||||
#: ../src/ui/theme-viewer.c:1287
|
||||
#, c-format
|
||||
msgid "Error not expected but one was returned: %s"
|
||||
msgstr "Chyba nebola očakávaná, ale bola vrátená: %s"
|
||||
|
||||
#~ msgid "x value was %d, %d was expected"
|
||||
#~ msgstr "hodnota x bola %d, očakávaná bola %d"
|
||||
#: ../src/ui/theme-viewer.c:1291
|
||||
#, c-format
|
||||
msgid "x value was %d, %d was expected"
|
||||
msgstr "hodnota x bola %d, očakávaná bola %d"
|
||||
|
||||
#~ msgid "y value was %d, %d was expected"
|
||||
#~ msgstr "hodnota y bola %d, očakávaná bola %d"
|
||||
#: ../src/ui/theme-viewer.c:1294
|
||||
#, c-format
|
||||
msgid "y value was %d, %d was expected"
|
||||
msgstr "hodnota y bola %d, očakávaná bola %d"
|
||||
|
||||
# PK: plural forms
|
||||
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=697987
|
||||
#, fuzzy
|
||||
#~ msgid ""
|
||||
#~ "%d coordinate expressions parsed in %g seconds (%g seconds average)\n"
|
||||
#~ msgstr ""
|
||||
#~ "%d výrazov pre súradnice analyzovaných za %g sekúnd (priemer %g sekúnd)\n"
|
||||
#: ../src/ui/theme-viewer.c:1359
|
||||
#, fuzzy, c-format
|
||||
msgid "%d coordinate expressions parsed in %g seconds (%g seconds average)\n"
|
||||
msgstr ""
|
||||
"%d výrazov pre súradnice analyzovaných za %g sekúnd (priemer %g sekúnd)\n"
|
||||
|
758
po/sr@latin.po
758
po/sr@latin.po
File diff suppressed because it is too large
Load Diff
1228
po/zh_CN.po
1228
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
524
po/zh_HK.po
524
po/zh_HK.po
File diff suppressed because it is too large
Load Diff
524
po/zh_TW.po
524
po/zh_TW.po
File diff suppressed because it is too large
Load Diff
@ -17,9 +17,6 @@
|
||||
<KeyListEntry name="move-to-workspace-4"
|
||||
_description="Move window to workspace 4" />
|
||||
|
||||
<KeyListEntry name="move-to-workspace-last"
|
||||
_description="Move window to last workspace" />
|
||||
|
||||
<KeyListEntry name="move-to-workspace-left"
|
||||
_description="Move window one workspace to the left" />
|
||||
|
||||
@ -80,9 +77,6 @@
|
||||
<KeyListEntry name="switch-to-workspace-4"
|
||||
_description="Switch to workspace 4" />
|
||||
|
||||
<KeyListEntry name="switch-to-workspace-last"
|
||||
_description="Switch to last workspace" />
|
||||
|
||||
<KeyListEntry name="switch-to-workspace-left"
|
||||
_description="Move to workspace left" />
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
# Flag build for parallelism; see https://savannah.gnu.org/patch/?6905
|
||||
.AUTOPARALLEL:
|
||||
|
||||
lib_LTLIBRARIES = libmutter.la
|
||||
lib_LTLIBRARIES = libmutter-wayland.la
|
||||
|
||||
SUBDIRS=compositor/plugins
|
||||
|
||||
@ -11,6 +11,7 @@ INCLUDES= \
|
||||
-DCOGL_ENABLE_EXPERIMENTAL_API \
|
||||
-DCOGL_ENABLE_EXPERIMENTAL_2_0_API \
|
||||
$(MUTTER_CFLAGS) \
|
||||
-I$(top_builddir) \
|
||||
-I$(srcdir) \
|
||||
-I$(srcdir)/backends \
|
||||
-I$(srcdir)/core \
|
||||
@ -40,24 +41,23 @@ mutter_built_sources = \
|
||||
gtk-shell-protocol.c \
|
||||
gtk-shell-server-protocol.h \
|
||||
xdg-shell-protocol.c \
|
||||
xdg-shell-server-protocol.h
|
||||
xdg-shell-server-protocol.h \
|
||||
xserver-protocol.c \
|
||||
xserver-server-protocol.h
|
||||
|
||||
wayland_protocols = \
|
||||
wayland/protocol/gtk-shell.xml \
|
||||
wayland/protocol/xdg-shell.xml
|
||||
wayland/protocol/xdg-shell.xml \
|
||||
wayland/protocol/xserver.xml
|
||||
|
||||
libmutter_la_SOURCES = \
|
||||
libmutter_wayland_la_SOURCES = \
|
||||
backends/meta-backend.c \
|
||||
backends/meta-backend.h \
|
||||
backends/meta-backend-private.h \
|
||||
backends/meta-cursor.c \
|
||||
backends/meta-cursor.h \
|
||||
backends/meta-cursor-private.h \
|
||||
backends/meta-cursor-tracker.c \
|
||||
backends/meta-cursor-tracker-private.h \
|
||||
backends/meta-cursor-renderer.c \
|
||||
backends/meta-cursor-renderer.h \
|
||||
backends/meta-display-config-shared.h \
|
||||
backends/meta-idle-monitor.c \
|
||||
backends/meta-idle-monitor-private.h \
|
||||
backends/meta-idle-monitor-dbus.c \
|
||||
@ -70,24 +70,22 @@ libmutter_la_SOURCES = \
|
||||
backends/meta-monitor-manager-dummy.h \
|
||||
backends/edid-parse.c \
|
||||
backends/edid.h \
|
||||
backends/native/meta-backend-native.c \
|
||||
backends/native/meta-backend-native.h \
|
||||
backends/native/meta-cursor-renderer-native.c \
|
||||
backends/native/meta-cursor-renderer-native.h \
|
||||
backends/native/meta-cursor-tracker-native.c \
|
||||
backends/native/meta-cursor-tracker-native.h \
|
||||
backends/native/meta-idle-monitor-native.c \
|
||||
backends/native/meta-idle-monitor-native.h \
|
||||
backends/native/meta-monitor-manager-kms.c \
|
||||
backends/native/meta-monitor-manager-kms.h \
|
||||
backends/native/meta-launcher.c \
|
||||
backends/native/meta-launcher.h \
|
||||
backends/x11/meta-backend-x11.c \
|
||||
backends/x11/meta-backend-x11.h \
|
||||
backends/native/meta-weston-launch.c \
|
||||
backends/native/meta-weston-launch.h \
|
||||
backends/x11/meta-cursor-tracker-x11.c \
|
||||
backends/x11/meta-cursor-tracker-x11.h \
|
||||
backends/x11/meta-idle-monitor-xsync.c \
|
||||
backends/x11/meta-idle-monitor-xsync.h \
|
||||
backends/x11/meta-monitor-manager-xrandr.c \
|
||||
backends/x11/meta-monitor-manager-xrandr.h \
|
||||
core/meta-accel-parse.c \
|
||||
core/meta-accel-parse.h \
|
||||
backends/x11/meta-xrandr-shared.h \
|
||||
core/above-tab-keycode.c \
|
||||
core/barrier.c \
|
||||
meta/barrier.h \
|
||||
core/bell.c \
|
||||
@ -122,8 +120,6 @@ libmutter_la_SOURCES = \
|
||||
compositor/meta-surface-actor-x11.h \
|
||||
compositor/meta-surface-actor-wayland.c \
|
||||
compositor/meta-surface-actor-wayland.h \
|
||||
compositor/meta-stage.h \
|
||||
compositor/meta-stage.c \
|
||||
compositor/meta-texture-rectangle.c \
|
||||
compositor/meta-texture-rectangle.h \
|
||||
compositor/meta-texture-tower.c \
|
||||
@ -222,9 +218,8 @@ libmutter_la_SOURCES = \
|
||||
wayland/meta-wayland.c \
|
||||
wayland/meta-wayland.h \
|
||||
wayland/meta-wayland-private.h \
|
||||
wayland/meta-xwayland.c \
|
||||
wayland/meta-xwayland.h \
|
||||
wayland/meta-xwayland-private.h \
|
||||
wayland/meta-xwayland.c \
|
||||
wayland/meta-wayland-data-device.c \
|
||||
wayland/meta-wayland-data-device.h \
|
||||
wayland/meta-wayland-keyboard.c \
|
||||
@ -233,20 +228,20 @@ libmutter_la_SOURCES = \
|
||||
wayland/meta-wayland-pointer.h \
|
||||
wayland/meta-wayland-seat.c \
|
||||
wayland/meta-wayland-seat.h \
|
||||
wayland/meta-wayland-stage.h \
|
||||
wayland/meta-wayland-stage.c \
|
||||
wayland/meta-wayland-surface.c \
|
||||
wayland/meta-wayland-surface.h \
|
||||
wayland/meta-wayland-types.h \
|
||||
wayland/meta-wayland-versions.h \
|
||||
wayland/meta-wayland-outputs.c \
|
||||
wayland/meta-wayland-outputs.h \
|
||||
wayland/window-wayland.c \
|
||||
wayland/window-wayland.h
|
||||
|
||||
nodist_libmutter_la_SOURCES = \
|
||||
nodist_libmutter_wayland_la_SOURCES = \
|
||||
$(mutter_built_sources)
|
||||
|
||||
libmutter_la_LDFLAGS = -no-undefined
|
||||
libmutter_la_LIBADD = $(MUTTER_LIBS)
|
||||
libmutter_wayland_la_LDFLAGS = -no-undefined
|
||||
libmutter_wayland_la_LIBADD = $(MUTTER_LIBS)
|
||||
|
||||
# Headers installed for plugins; introspected information will
|
||||
# be extracted into Mutter-<version>.gir
|
||||
@ -284,16 +279,16 @@ libmutterinclude_base_headers = \
|
||||
libmutterinclude_extra_headers = \
|
||||
meta/atomnames.h
|
||||
|
||||
libmutterincludedir = $(includedir)/mutter/meta
|
||||
libmutterincludedir = $(includedir)/mutter-wayland/meta
|
||||
|
||||
libmutterinclude_HEADERS = \
|
||||
$(libmutterinclude_base_headers) \
|
||||
$(libmutterinclude_extra_headers)
|
||||
|
||||
bin_PROGRAMS=mutter
|
||||
bin_PROGRAMS=mutter-wayland
|
||||
|
||||
mutter_SOURCES = core/mutter.c
|
||||
mutter_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
mutter_wayland_SOURCES = core/mutter.c
|
||||
mutter_wayland_LDADD = $(MUTTER_LIBS) libmutter-wayland.la
|
||||
|
||||
bin_PROGRAMS+=mutter-launch
|
||||
|
||||
@ -328,15 +323,15 @@ typelib_DATA = Meta-$(api_version).typelib
|
||||
|
||||
INTROSPECTION_GIRS = Meta-$(api_version).gir
|
||||
|
||||
Meta-$(api_version).gir: libmutter.la
|
||||
Meta-$(api_version).gir: libmutter-wayland.la
|
||||
@META_GIR@_INCLUDES = GObject-2.0 GDesktopEnums-3.0 Gdk-3.0 Gtk-3.0 Clutter-1.0 xlib-2.0 xfixes-4.0 Cogl-1.0
|
||||
@META_GIR@_EXPORT_PACKAGES = libmutter
|
||||
@META_GIR@_EXPORT_PACKAGES = libmutter-wayland
|
||||
@META_GIR@_CFLAGS = $(INCLUDES)
|
||||
@META_GIR@_LIBS = libmutter.la
|
||||
@META_GIR@_LIBS = libmutter-wayland.la
|
||||
@META_GIR@_FILES = \
|
||||
mutter-enum-types.h \
|
||||
$(libmutterinclude_base_headers) \
|
||||
$(filter %.c,$(libmutter_la_SOURCES) $(nodist_libmutter_la_SOURCES))
|
||||
$(filter %.c,$(libmutter_wayland_la_SOURCES) $(nodist_libmutter_wayland_la_SOURCES))
|
||||
@META_GIR@_SCANNERFLAGS = --warn-all --warn-error
|
||||
|
||||
endif
|
||||
@ -347,14 +342,14 @@ testasyncgetprop_SOURCES = x11/testasyncgetprop.c
|
||||
|
||||
noinst_PROGRAMS=testboxes testgradient testasyncgetprop
|
||||
|
||||
testboxes_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
testgradient_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter.la
|
||||
testboxes_LDADD = $(MUTTER_LIBS) libmutter-wayland.la
|
||||
testgradient_LDADD = $(MUTTER_LIBS) libmutter-wayland.la
|
||||
testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter-wayland.la
|
||||
|
||||
@INTLTOOL_DESKTOP_RULE@
|
||||
|
||||
desktopfilesdir=$(datadir)/applications
|
||||
desktopfiles_in_files=mutter.desktop.in
|
||||
desktopfiles_in_files=mutter-wayland.desktop.in
|
||||
desktopfiles_files=$(desktopfiles_in_files:.desktop.in=.desktop)
|
||||
desktopfiles_DATA = $(desktopfiles_files)
|
||||
|
||||
@ -375,7 +370,7 @@ convertdir = $(datadir)/GConf/gsettings
|
||||
convert_DATA = mutter-schemas.convert
|
||||
|
||||
CLEANFILES = \
|
||||
mutter.desktop \
|
||||
mutter-wayland.desktop \
|
||||
mutter-wm.desktop \
|
||||
org.gnome.mutter.gschema.xml \
|
||||
org.gnome.mutter.wayland.gschema.xml \
|
||||
@ -386,7 +381,7 @@ CLEANFILES = \
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
|
||||
pkgconfig_DATA = libmutter.pc
|
||||
pkgconfig_DATA = libmutter-wayland.pc
|
||||
|
||||
EXTRA_DIST=$(desktopfiles_files) \
|
||||
$(wmproperties_files) \
|
||||
@ -398,7 +393,7 @@ EXTRA_DIST=$(desktopfiles_files) \
|
||||
org.gnome.mutter.gschema.xml.in \
|
||||
org.gnome.mutter.wayland.gschema.xml.in \
|
||||
mutter-schemas.convert \
|
||||
libmutter.pc.in \
|
||||
libmutter-wayland.pc.in \
|
||||
mutter-enum-types.h.in \
|
||||
mutter-enum-types.c.in \
|
||||
org.gnome.Mutter.DisplayConfig.xml \
|
||||
|
@ -1,67 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef META_BACKEND_PRIVATE_H
|
||||
#define META_BACKEND_PRIVATE_H
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "meta-backend.h"
|
||||
|
||||
#define META_TYPE_BACKEND (meta_backend_get_type ())
|
||||
#define META_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BACKEND, MetaBackend))
|
||||
#define META_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_BACKEND, MetaBackendClass))
|
||||
#define META_IS_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_BACKEND))
|
||||
#define META_IS_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_BACKEND))
|
||||
#define META_BACKEND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_BACKEND, MetaBackendClass))
|
||||
|
||||
struct _MetaBackend
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
MetaIdleMonitor *device_monitors[256];
|
||||
int device_id_max;
|
||||
};
|
||||
|
||||
struct _MetaBackendClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (* post_init) (MetaBackend *backend);
|
||||
|
||||
MetaIdleMonitor * (* create_idle_monitor) (MetaBackend *backend,
|
||||
int device_id);
|
||||
MetaMonitorManager * (* create_monitor_manager) (MetaBackend *backend);
|
||||
MetaCursorRenderer * (* create_cursor_renderer) (MetaBackend *backend);
|
||||
|
||||
gboolean (* grab_device) (MetaBackend *backend,
|
||||
int device_id,
|
||||
uint32_t timestamp);
|
||||
gboolean (* ungrab_device) (MetaBackend *backend,
|
||||
int device_id,
|
||||
uint32_t timestamp);
|
||||
};
|
||||
|
||||
#endif /* META_BACKEND_PRIVATE_H */
|
@ -25,193 +25,14 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "meta-backend.h"
|
||||
#include "meta-backend-private.h"
|
||||
#include <meta/main.h>
|
||||
|
||||
#include <gdk/gdkx.h>
|
||||
#include <clutter/clutter.h>
|
||||
#include <clutter/x11/clutter-x11.h>
|
||||
|
||||
#include "backends/x11/meta-backend-x11.h"
|
||||
#include "backends/native/meta-backend-native.h"
|
||||
|
||||
static MetaBackend *_backend;
|
||||
|
||||
MetaBackend *
|
||||
meta_get_backend (void)
|
||||
{
|
||||
return _backend;
|
||||
}
|
||||
|
||||
struct _MetaBackendPrivate
|
||||
{
|
||||
MetaMonitorManager *monitor_manager;
|
||||
MetaCursorRenderer *cursor_renderer;
|
||||
};
|
||||
typedef struct _MetaBackendPrivate MetaBackendPrivate;
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaBackend, meta_backend, G_TYPE_OBJECT);
|
||||
|
||||
static void
|
||||
meta_backend_finalize (GObject *object)
|
||||
{
|
||||
MetaBackend *backend = META_BACKEND (object);
|
||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||
int i;
|
||||
|
||||
g_clear_object (&priv->monitor_manager);
|
||||
|
||||
for (i = 0; i <= backend->device_id_max; i++)
|
||||
{
|
||||
if (backend->device_monitors[i])
|
||||
g_object_unref (backend->device_monitors[i]);
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (meta_backend_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_real_post_init (MetaBackend *backend)
|
||||
{
|
||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||
|
||||
priv->cursor_renderer = META_BACKEND_GET_CLASS (backend)->create_cursor_renderer (backend);
|
||||
priv->monitor_manager = META_BACKEND_GET_CLASS (backend)->create_monitor_manager (backend);
|
||||
}
|
||||
|
||||
static MetaCursorRenderer *
|
||||
meta_backend_real_create_cursor_renderer (MetaBackend *backend)
|
||||
{
|
||||
return meta_cursor_renderer_new ();
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_backend_real_grab_device (MetaBackend *backend,
|
||||
int device_id,
|
||||
uint32_t timestamp)
|
||||
{
|
||||
/* Do nothing */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_backend_real_ungrab_device (MetaBackend *backend,
|
||||
int device_id,
|
||||
uint32_t timestamp)
|
||||
{
|
||||
/* Do nothing */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_class_init (MetaBackendClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = meta_backend_finalize;
|
||||
|
||||
klass->post_init = meta_backend_real_post_init;
|
||||
klass->create_cursor_renderer = meta_backend_real_create_cursor_renderer;
|
||||
klass->grab_device = meta_backend_real_grab_device;
|
||||
klass->ungrab_device = meta_backend_real_ungrab_device;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_init (MetaBackend *backend)
|
||||
{
|
||||
_backend = backend;
|
||||
}
|
||||
|
||||
/* FIXME -- destroy device monitors at some point */
|
||||
G_GNUC_UNUSED static void
|
||||
destroy_device_monitor (MetaBackend *backend,
|
||||
int device_id)
|
||||
{
|
||||
g_clear_object (&backend->device_monitors[device_id]);
|
||||
if (device_id == backend->device_id_max)
|
||||
backend->device_id_max--;
|
||||
}
|
||||
|
||||
static MetaIdleMonitor *
|
||||
meta_backend_create_idle_monitor (MetaBackend *backend,
|
||||
int device_id)
|
||||
{
|
||||
return META_BACKEND_GET_CLASS (backend)->create_idle_monitor (backend, device_id);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_post_init (MetaBackend *backend)
|
||||
{
|
||||
META_BACKEND_GET_CLASS (backend)->post_init (backend);
|
||||
}
|
||||
|
||||
MetaIdleMonitor *
|
||||
meta_backend_get_idle_monitor (MetaBackend *backend,
|
||||
int device_id)
|
||||
{
|
||||
g_return_val_if_fail (device_id >= 0 && device_id < 256, NULL);
|
||||
|
||||
if (!backend->device_monitors[device_id])
|
||||
{
|
||||
backend->device_monitors[device_id] = meta_backend_create_idle_monitor (backend, device_id);
|
||||
backend->device_id_max = MAX (backend->device_id_max, device_id);
|
||||
}
|
||||
|
||||
return backend->device_monitors[device_id];
|
||||
}
|
||||
|
||||
MetaMonitorManager *
|
||||
meta_backend_get_monitor_manager (MetaBackend *backend)
|
||||
{
|
||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||
|
||||
return priv->monitor_manager;
|
||||
}
|
||||
|
||||
MetaCursorRenderer *
|
||||
meta_backend_get_cursor_renderer (MetaBackend *backend)
|
||||
{
|
||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||
|
||||
return priv->cursor_renderer;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_backend_grab_device (MetaBackend *backend,
|
||||
int device_id,
|
||||
uint32_t timestamp)
|
||||
{
|
||||
return META_BACKEND_GET_CLASS (backend)->grab_device (backend, device_id, timestamp);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_backend_ungrab_device (MetaBackend *backend,
|
||||
int device_id,
|
||||
uint32_t timestamp)
|
||||
{
|
||||
return META_BACKEND_GET_CLASS (backend)->ungrab_device (backend, device_id, timestamp);
|
||||
}
|
||||
|
||||
static GType
|
||||
get_backend_type (void)
|
||||
{
|
||||
#if defined(CLUTTER_WINDOWING_X11)
|
||||
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_X11))
|
||||
return META_TYPE_BACKEND_X11;
|
||||
#endif
|
||||
|
||||
#if defined(CLUTTER_WINDOWING_EGL)
|
||||
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
|
||||
return META_TYPE_BACKEND_NATIVE;
|
||||
#endif
|
||||
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
static void
|
||||
meta_create_backend (void)
|
||||
{
|
||||
/* meta_backend_init() above install the backend globally so
|
||||
* so meta_get_backend() works even during initialization. */
|
||||
g_object_new (get_backend_type (), NULL);
|
||||
}
|
||||
#include "backends/native/meta-weston-launch.h"
|
||||
#include <meta/util.h>
|
||||
|
||||
/* Mutter is responsible for pulling events off the X queue, so Clutter
|
||||
* doesn't need (and shouldn't) run its normal event source which polls
|
||||
@ -261,12 +82,37 @@ static GSourceFuncs event_funcs = {
|
||||
event_dispatch
|
||||
};
|
||||
|
||||
static MetaLauncher *launcher;
|
||||
|
||||
void
|
||||
meta_clutter_init (void)
|
||||
{
|
||||
GSource *source;
|
||||
|
||||
meta_create_backend ();
|
||||
/* When running as an X11 compositor, we install our own event filter and
|
||||
* pass events to Clutter explicitly, so we need to prevent Clutter from
|
||||
* handling our events.
|
||||
*
|
||||
* However, when running as a Wayland compostior under X11 nested, Clutter
|
||||
* Clutter needs to see events related to its own window. We need to
|
||||
* eventually replace this with a proper frontend / backend split: Clutter
|
||||
* under nested is connecting to the "host X server" to get its events it
|
||||
* needs to put up a window, and GTK+ is connecting to the "inner X server".
|
||||
* The two would the same in the X11 compositor case, but not when running
|
||||
* XWayland as a Wayland compositor.
|
||||
*/
|
||||
if (!meta_is_wayland_compositor ())
|
||||
{
|
||||
clutter_x11_set_display (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
|
||||
clutter_x11_disable_event_retrieval ();
|
||||
}
|
||||
|
||||
/* If we're running on bare metal, we're a display server,
|
||||
* so start talking to weston-launch. */
|
||||
#if defined(CLUTTER_WINDOWING_EGL)
|
||||
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
|
||||
launcher = meta_launcher_new ();
|
||||
#endif
|
||||
|
||||
if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
|
||||
g_error ("Unable to initialize Clutter.\n");
|
||||
@ -274,6 +120,38 @@ meta_clutter_init (void)
|
||||
source = g_source_new (&event_funcs, sizeof (GSource));
|
||||
g_source_attach (source, NULL);
|
||||
g_source_unref (source);
|
||||
|
||||
meta_backend_post_init (_backend);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_activate_vt (int vt, GError **error)
|
||||
{
|
||||
if (launcher)
|
||||
return meta_launcher_activate_vt (launcher, vt, error);
|
||||
else
|
||||
{
|
||||
g_debug ("Ignoring VT switch keybinding, not running as display server");
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_activate_session:
|
||||
*
|
||||
* Tells mutter to activate the session. When mutter is a
|
||||
* Wayland compositor, this tells logind to switch over to
|
||||
* the new session.
|
||||
*/
|
||||
gboolean
|
||||
meta_activate_session (void)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (!meta_launcher_activate_vt (launcher, -1, &error))
|
||||
{
|
||||
g_warning ("Could not activate session: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -27,29 +27,8 @@
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include <meta/meta-idle-monitor.h>
|
||||
#include "meta-monitor-manager.h"
|
||||
#include "meta-cursor-renderer.h"
|
||||
|
||||
typedef struct _MetaBackend MetaBackend;
|
||||
typedef struct _MetaBackendClass MetaBackendClass;
|
||||
|
||||
GType meta_backend_get_type (void);
|
||||
|
||||
MetaBackend * meta_get_backend (void);
|
||||
|
||||
MetaIdleMonitor * meta_backend_get_idle_monitor (MetaBackend *backend,
|
||||
int device_id);
|
||||
MetaMonitorManager * meta_backend_get_monitor_manager (MetaBackend *backend);
|
||||
MetaCursorRenderer * meta_backend_get_cursor_renderer (MetaBackend *backend);
|
||||
|
||||
gboolean meta_backend_grab_device (MetaBackend *backend,
|
||||
int device_id,
|
||||
uint32_t timestamp);
|
||||
gboolean meta_backend_ungrab_device (MetaBackend *backend,
|
||||
int device_id,
|
||||
uint32_t timestamp);
|
||||
|
||||
void meta_clutter_init (void);
|
||||
|
||||
gboolean meta_activate_vt (int vt, GError **error);
|
||||
|
||||
#endif /* META_BACKEND_H */
|
||||
|
@ -27,6 +27,11 @@
|
||||
#include <cogl/cogl.h>
|
||||
#include <gbm.h>
|
||||
|
||||
#include <X11/cursorfont.h>
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
#include <X11/Xcursor/Xcursor.h>
|
||||
#include <wayland-server.h>
|
||||
|
||||
typedef struct {
|
||||
CoglTexture2D *texture;
|
||||
struct gbm_bo *bo;
|
||||
@ -36,7 +41,6 @@ typedef struct {
|
||||
struct _MetaCursorReference {
|
||||
int ref_count;
|
||||
|
||||
MetaCursor cursor;
|
||||
MetaCursorImage image;
|
||||
};
|
||||
|
||||
@ -48,4 +52,26 @@ struct gbm_bo *meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
|
||||
int *hot_x,
|
||||
int *hot_y);
|
||||
|
||||
void meta_cursor_reference_load_gbm_buffer (MetaCursorReference *cursor,
|
||||
struct gbm_device *gbm,
|
||||
uint8_t *pixels,
|
||||
int width,
|
||||
int height,
|
||||
int rowstride,
|
||||
uint32_t gbm_format);
|
||||
|
||||
void meta_cursor_reference_import_gbm_buffer (MetaCursorReference *cursor,
|
||||
struct gbm_device *gbm,
|
||||
struct wl_resource *buffer,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
MetaCursorReference *meta_cursor_reference_from_xfixes_cursor_image (XFixesCursorImage *cursor_image);
|
||||
|
||||
MetaCursorReference *meta_cursor_reference_from_xcursor_image (XcursorImage *xc_image);
|
||||
|
||||
MetaCursorReference *meta_cursor_reference_from_buffer (struct wl_resource *buffer,
|
||||
int hot_x,
|
||||
int hot_y);
|
||||
|
||||
#endif /* META_CURSOR_PRIVATE_H */
|
||||
|
@ -1,161 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "meta-cursor-renderer.h"
|
||||
#include "meta-cursor-private.h"
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
#include <cogl/cogl-wayland-server.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include "meta-stage.h"
|
||||
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
|
||||
struct _MetaCursorRendererPrivate
|
||||
{
|
||||
int current_x, current_y;
|
||||
MetaRectangle current_rect;
|
||||
|
||||
MetaCursorReference *displayed_cursor;
|
||||
};
|
||||
typedef struct _MetaCursorRendererPrivate MetaCursorRendererPrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRenderer, meta_cursor_renderer, G_TYPE_OBJECT);
|
||||
|
||||
static void
|
||||
queue_redraw (MetaCursorRenderer *renderer)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||
ClutterActor *stage = compositor->stage;
|
||||
|
||||
/* During early initialization, we can have no stage */
|
||||
if (!stage)
|
||||
return;
|
||||
|
||||
/* If we're not using a MetaStage, quit early */
|
||||
if (!META_IS_STAGE (stage))
|
||||
return;
|
||||
|
||||
meta_stage_set_cursor (META_STAGE (stage),
|
||||
priv->displayed_cursor,
|
||||
&priv->current_rect);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_renderer_real_update_cursor (MetaCursorRenderer *renderer)
|
||||
{
|
||||
queue_redraw (renderer);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_renderer_class_init (MetaCursorRendererClass *klass)
|
||||
{
|
||||
klass->update_cursor = meta_cursor_renderer_real_update_cursor;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_renderer_init (MetaCursorRenderer *renderer)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
update_cursor (MetaCursorRenderer *renderer)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||
|
||||
if (priv->displayed_cursor)
|
||||
{
|
||||
CoglTexture *texture;
|
||||
int hot_x, hot_y;
|
||||
|
||||
texture = meta_cursor_reference_get_cogl_texture (priv->displayed_cursor, &hot_x, &hot_y);
|
||||
|
||||
priv->current_rect.x = priv->current_x - hot_x;
|
||||
priv->current_rect.y = priv->current_y - hot_y;
|
||||
priv->current_rect.width = cogl_texture_get_width (COGL_TEXTURE (texture));
|
||||
priv->current_rect.height = cogl_texture_get_height (COGL_TEXTURE (texture));
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->current_rect.x = 0;
|
||||
priv->current_rect.y = 0;
|
||||
priv->current_rect.width = 0;
|
||||
priv->current_rect.height = 0;
|
||||
}
|
||||
|
||||
META_CURSOR_RENDERER_GET_CLASS (renderer)->update_cursor (renderer);
|
||||
}
|
||||
|
||||
MetaCursorRenderer *
|
||||
meta_cursor_renderer_new (void)
|
||||
{
|
||||
return g_object_new (META_TYPE_CURSOR_RENDERER, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_renderer_set_cursor (MetaCursorRenderer *renderer,
|
||||
MetaCursorReference *cursor)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||
|
||||
if (priv->displayed_cursor == cursor)
|
||||
return;
|
||||
|
||||
priv->displayed_cursor = cursor;
|
||||
update_cursor (renderer);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_renderer_set_position (MetaCursorRenderer *renderer,
|
||||
int x, int y)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
priv->current_x = x;
|
||||
priv->current_y = y;
|
||||
|
||||
update_cursor (renderer);
|
||||
}
|
||||
|
||||
MetaCursorReference *
|
||||
meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||
|
||||
return priv->displayed_cursor;
|
||||
}
|
||||
|
||||
const MetaRectangle *
|
||||
meta_cursor_renderer_get_rect (MetaCursorRenderer *renderer)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||
|
||||
return &priv->current_rect;
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#ifndef META_CURSOR_RENDERER_H
|
||||
#define META_CURSOR_RENDERER_H
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include <meta/screen.h>
|
||||
#include "meta-cursor.h"
|
||||
|
||||
#include <gbm.h>
|
||||
|
||||
#define META_TYPE_CURSOR_RENDERER (meta_cursor_renderer_get_type ())
|
||||
#define META_CURSOR_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CURSOR_RENDERER, MetaCursorRenderer))
|
||||
#define META_CURSOR_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_CURSOR_RENDERER, MetaCursorRendererClass))
|
||||
#define META_IS_CURSOR_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_CURSOR_RENDERER))
|
||||
#define META_IS_CURSOR_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_CURSOR_RENDERER))
|
||||
#define META_CURSOR_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_CURSOR_RENDERER, MetaCursorRendererClass))
|
||||
|
||||
typedef struct _MetaCursorRenderer MetaCursorRenderer;
|
||||
typedef struct _MetaCursorRendererClass MetaCursorRendererClass;
|
||||
|
||||
struct _MetaCursorRenderer
|
||||
{
|
||||
GObject parent;
|
||||
};
|
||||
|
||||
struct _MetaCursorRendererClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (* update_cursor) (MetaCursorRenderer *renderer);
|
||||
};
|
||||
|
||||
GType meta_cursor_renderer_get_type (void) G_GNUC_CONST;
|
||||
|
||||
MetaCursorRenderer * meta_cursor_renderer_new (void);
|
||||
|
||||
void meta_cursor_renderer_set_cursor (MetaCursorRenderer *renderer,
|
||||
MetaCursorReference *cursor);
|
||||
|
||||
void meta_cursor_renderer_set_position (MetaCursorRenderer *renderer,
|
||||
int x, int y);
|
||||
|
||||
MetaCursorReference * meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer);
|
||||
const MetaRectangle * meta_cursor_renderer_get_rect (MetaCursorRenderer *renderer);
|
||||
|
||||
#endif /* META_CURSOR_RENDERER_H */
|
@ -24,17 +24,12 @@
|
||||
|
||||
#include <meta/meta-cursor-tracker.h>
|
||||
#include <wayland-server.h>
|
||||
#include <gbm.h>
|
||||
|
||||
#include "meta-cursor.h"
|
||||
#include "meta-cursor-renderer.h"
|
||||
|
||||
struct _MetaCursorTracker {
|
||||
GObject parent_instance;
|
||||
|
||||
MetaScreen *screen;
|
||||
MetaCursorRenderer *renderer;
|
||||
|
||||
gboolean is_showing;
|
||||
|
||||
/* The cursor tracker stores the cursor for the current grab
|
||||
@ -51,9 +46,15 @@ struct _MetaCursorTracker {
|
||||
*/
|
||||
MetaCursorReference *displayed_cursor;
|
||||
|
||||
/* This is the cursor that would be displayed if we hadn't been
|
||||
* asked to hide it. i.e. it's the same as displayed_cursor unless
|
||||
* is_showing is false.
|
||||
*/
|
||||
MetaCursorReference *current_cursor;
|
||||
|
||||
MetaCursorReference *grab_cursor;
|
||||
|
||||
/* Wayland clients can set a NULL buffer as their cursor
|
||||
/* Wayland clients can set a NULL buffer as their cursor
|
||||
* explicitly, which means that we shouldn't display anything.
|
||||
* So, we can't simply store a NULL in window_cursor to
|
||||
* determine an unset window cursor; we need an extra boolean.
|
||||
@ -62,14 +63,39 @@ struct _MetaCursorTracker {
|
||||
MetaCursorReference *window_cursor;
|
||||
|
||||
MetaCursorReference *root_cursor;
|
||||
|
||||
MetaCursorReference *theme_cursors[META_CURSOR_LAST];
|
||||
};
|
||||
|
||||
struct _MetaCursorTrackerClass {
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (*get_pointer) (MetaCursorTracker *tracker,
|
||||
int *x,
|
||||
int *y,
|
||||
ClutterModifierType *mods);
|
||||
|
||||
void (*sync_cursor) (MetaCursorTracker *tracker);
|
||||
|
||||
void (*ensure_cursor) (MetaCursorTracker *tracker);
|
||||
|
||||
void (*load_cursor_pixels) (MetaCursorTracker *tracker,
|
||||
MetaCursorReference *cursor,
|
||||
uint8_t *pixels,
|
||||
int width,
|
||||
int height,
|
||||
int rowstride,
|
||||
uint32_t format);
|
||||
|
||||
void (*load_cursor_buffer) (MetaCursorTracker *tracker,
|
||||
MetaCursorReference *cursor,
|
||||
struct wl_resource *buffer);
|
||||
};
|
||||
|
||||
gboolean meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
|
||||
XEvent *xevent);
|
||||
void _meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
|
||||
gboolean has_cursor,
|
||||
MetaCursorReference *cursor);
|
||||
void _meta_cursor_tracker_sync_cursor (MetaCursorTracker *tracker);
|
||||
|
||||
void meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker,
|
||||
MetaCursorReference *cursor);
|
||||
@ -78,11 +104,13 @@ void meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
|
||||
void meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker);
|
||||
void meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
|
||||
MetaCursorReference *cursor);
|
||||
|
||||
void meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
|
||||
int new_x,
|
||||
int new_y);
|
||||
|
||||
MetaCursorReference * meta_cursor_tracker_get_displayed_cursor (MetaCursorTracker *tracker);
|
||||
MetaCursorReference *
|
||||
meta_cursor_tracker_get_cursor_from_theme (MetaCursorTracker *tracker,
|
||||
MetaCursor cursor);
|
||||
MetaCursorReference *
|
||||
meta_cursor_tracker_get_cursor_from_buffer (MetaCursorTracker *tracker,
|
||||
struct wl_resource *buffer,
|
||||
int hot_x,
|
||||
int hot_y);
|
||||
|
||||
#endif
|
||||
|
@ -33,21 +33,12 @@
|
||||
#include <meta/util.h>
|
||||
#include <meta/errors.h>
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
#include <cogl/cogl-wayland-server.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
|
||||
#include "meta-backend.h"
|
||||
|
||||
#include "meta-cursor-private.h"
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
#include "backends/native/meta-cursor-tracker-native.h"
|
||||
#include "backends/x11/meta-cursor-tracker-x11.h"
|
||||
#include "screen-private.h"
|
||||
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
|
||||
G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT);
|
||||
|
||||
enum {
|
||||
@ -57,43 +48,6 @@ enum {
|
||||
|
||||
static guint signals[LAST_SIGNAL];
|
||||
|
||||
static MetaCursorReference *
|
||||
get_displayed_cursor (MetaCursorTracker *tracker)
|
||||
{
|
||||
if (!tracker->is_showing)
|
||||
return NULL;
|
||||
|
||||
if (tracker->grab_cursor)
|
||||
return tracker->grab_cursor;
|
||||
|
||||
if (tracker->has_window_cursor)
|
||||
return tracker->window_cursor;
|
||||
|
||||
return tracker->root_cursor;
|
||||
}
|
||||
|
||||
static void
|
||||
update_displayed_cursor (MetaCursorTracker *tracker)
|
||||
{
|
||||
meta_cursor_renderer_set_cursor (tracker->renderer, tracker->displayed_cursor);
|
||||
}
|
||||
|
||||
static void
|
||||
sync_cursor (MetaCursorTracker *tracker)
|
||||
{
|
||||
MetaCursorReference *displayed_cursor = get_displayed_cursor (tracker);
|
||||
|
||||
if (tracker->displayed_cursor == displayed_cursor)
|
||||
return;
|
||||
|
||||
g_clear_pointer (&tracker->displayed_cursor, meta_cursor_reference_unref);
|
||||
if (displayed_cursor)
|
||||
tracker->displayed_cursor = meta_cursor_reference_ref (displayed_cursor);
|
||||
|
||||
update_displayed_cursor (tracker);
|
||||
g_signal_emit (tracker, signals[CURSOR_CHANGED], 0);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_tracker_init (MetaCursorTracker *self)
|
||||
{
|
||||
@ -109,15 +63,43 @@ static void
|
||||
meta_cursor_tracker_finalize (GObject *object)
|
||||
{
|
||||
MetaCursorTracker *self = META_CURSOR_TRACKER (object);
|
||||
int i;
|
||||
|
||||
if (self->displayed_cursor)
|
||||
meta_cursor_reference_unref (self->displayed_cursor);
|
||||
if (self->root_cursor)
|
||||
meta_cursor_reference_unref (self->root_cursor);
|
||||
|
||||
for (i = 0; i < META_CURSOR_LAST; i++)
|
||||
if (self->theme_cursors[i])
|
||||
meta_cursor_reference_unref (self->theme_cursors[i]);
|
||||
|
||||
G_OBJECT_CLASS (meta_cursor_tracker_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
default_do_nothing (MetaCursorTracker *tracker)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
default_load_cursor_pixels (MetaCursorTracker *tracker,
|
||||
MetaCursorReference *cursor,
|
||||
uint8_t *pixels,
|
||||
int width,
|
||||
int height,
|
||||
int rowstride,
|
||||
uint32_t format)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
default_load_cursor_buffer (MetaCursorTracker *tracker,
|
||||
MetaCursorReference *cursor,
|
||||
struct wl_resource *buffer)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass)
|
||||
{
|
||||
@ -125,6 +107,11 @@ meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass)
|
||||
|
||||
object_class->finalize = meta_cursor_tracker_finalize;
|
||||
|
||||
klass->sync_cursor = default_do_nothing;
|
||||
klass->ensure_cursor = default_do_nothing;
|
||||
klass->load_cursor_pixels = default_load_cursor_pixels;
|
||||
klass->load_cursor_buffer = default_load_cursor_buffer;
|
||||
|
||||
signals[CURSOR_CHANGED] = g_signal_new ("cursor-changed",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
@ -133,52 +120,6 @@ meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass)
|
||||
G_TYPE_NONE, 0);
|
||||
}
|
||||
|
||||
static MetaCursorTracker *
|
||||
make_wayland_cursor_tracker (MetaScreen *screen)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaWaylandCompositor *compositor;
|
||||
MetaCursorTracker *self;
|
||||
|
||||
self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
|
||||
self->screen = screen;
|
||||
self->renderer = meta_backend_get_cursor_renderer (backend);
|
||||
|
||||
compositor = meta_wayland_compositor_get_default ();
|
||||
compositor->seat->pointer.cursor_tracker = self;
|
||||
meta_cursor_tracker_update_position (self, 0, 0);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static MetaCursorTracker *
|
||||
make_x11_cursor_tracker (MetaScreen *screen)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaCursorTracker *self;
|
||||
|
||||
self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
|
||||
self->screen = screen;
|
||||
self->renderer = meta_backend_get_cursor_renderer (backend);
|
||||
|
||||
XFixesSelectCursorInput (screen->display->xdisplay,
|
||||
screen->xroot,
|
||||
XFixesDisplayCursorNotifyMask);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static MetaCursorTracker *
|
||||
meta_cursor_tracker_new (MetaScreen *screen)
|
||||
{
|
||||
if (meta_is_wayland_compositor ())
|
||||
return make_wayland_cursor_tracker (screen);
|
||||
else
|
||||
return make_x11_cursor_tracker (screen);
|
||||
}
|
||||
|
||||
static MetaCursorTracker *_cursor_tracker;
|
||||
|
||||
/**
|
||||
* meta_cursor_tracker_get_for_screen:
|
||||
* @screen: the #MetaScreen
|
||||
@ -190,123 +131,18 @@ static MetaCursorTracker *_cursor_tracker;
|
||||
MetaCursorTracker *
|
||||
meta_cursor_tracker_get_for_screen (MetaScreen *screen)
|
||||
{
|
||||
if (!_cursor_tracker)
|
||||
_cursor_tracker = meta_cursor_tracker_new (screen);
|
||||
MetaCursorTracker *self;
|
||||
|
||||
return _cursor_tracker;
|
||||
}
|
||||
|
||||
static void
|
||||
set_window_cursor (MetaCursorTracker *tracker,
|
||||
gboolean has_cursor,
|
||||
MetaCursorReference *cursor)
|
||||
{
|
||||
g_clear_pointer (&tracker->window_cursor, meta_cursor_reference_unref);
|
||||
if (cursor)
|
||||
tracker->window_cursor = meta_cursor_reference_ref (cursor);
|
||||
tracker->has_window_cursor = has_cursor;
|
||||
sync_cursor (tracker);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
|
||||
XEvent *xevent)
|
||||
{
|
||||
XFixesCursorNotifyEvent *notify_event;
|
||||
if (screen->cursor_tracker)
|
||||
return screen->cursor_tracker;
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
return FALSE;
|
||||
|
||||
if (xevent->xany.type != tracker->screen->display->xfixes_event_base + XFixesCursorNotify)
|
||||
return FALSE;
|
||||
|
||||
notify_event = (XFixesCursorNotifyEvent *)xevent;
|
||||
if (notify_event->subtype != XFixesDisplayCursorNotify)
|
||||
return FALSE;
|
||||
|
||||
set_window_cursor (tracker, FALSE, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static MetaCursorReference *
|
||||
meta_cursor_reference_take_texture (CoglTexture2D *texture,
|
||||
int hot_x,
|
||||
int hot_y)
|
||||
{
|
||||
MetaCursorReference *self;
|
||||
|
||||
self = g_slice_new0 (MetaCursorReference);
|
||||
self->ref_count = 1;
|
||||
self->image.texture = texture;
|
||||
self->image.hot_x = hot_x;
|
||||
self->image.hot_y = hot_y;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static void
|
||||
ensure_xfixes_cursor (MetaCursorTracker *tracker)
|
||||
{
|
||||
XFixesCursorImage *cursor_image;
|
||||
CoglTexture2D *sprite;
|
||||
guint8 *cursor_data;
|
||||
gboolean free_cursor_data;
|
||||
CoglContext *ctx;
|
||||
|
||||
if (tracker->has_window_cursor)
|
||||
return;
|
||||
|
||||
cursor_image = XFixesGetCursorImage (tracker->screen->display->xdisplay);
|
||||
if (!cursor_image)
|
||||
return;
|
||||
|
||||
/* Like all X APIs, XFixesGetCursorImage() returns arrays of 32-bit
|
||||
* quantities as arrays of long; we need to convert on 64 bit */
|
||||
if (sizeof(long) == 4)
|
||||
{
|
||||
cursor_data = (guint8 *)cursor_image->pixels;
|
||||
free_cursor_data = FALSE;
|
||||
}
|
||||
self = g_object_new (META_TYPE_CURSOR_TRACKER_NATIVE, NULL);
|
||||
else
|
||||
{
|
||||
int i, j;
|
||||
guint32 *cursor_words;
|
||||
gulong *p;
|
||||
guint32 *q;
|
||||
self = g_object_new (META_TYPE_CURSOR_TRACKER_X11, NULL);
|
||||
|
||||
cursor_words = g_new (guint32, cursor_image->width * cursor_image->height);
|
||||
cursor_data = (guint8 *)cursor_words;
|
||||
|
||||
p = cursor_image->pixels;
|
||||
q = cursor_words;
|
||||
for (j = 0; j < cursor_image->height; j++)
|
||||
for (i = 0; i < cursor_image->width; i++)
|
||||
*(q++) = *(p++);
|
||||
|
||||
free_cursor_data = TRUE;
|
||||
}
|
||||
|
||||
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
sprite = cogl_texture_2d_new_from_data (ctx,
|
||||
cursor_image->width,
|
||||
cursor_image->height,
|
||||
CLUTTER_CAIRO_FORMAT_ARGB32,
|
||||
cursor_image->width * 4, /* stride */
|
||||
cursor_data,
|
||||
NULL);
|
||||
|
||||
if (free_cursor_data)
|
||||
g_free (cursor_data);
|
||||
|
||||
if (sprite != NULL)
|
||||
{
|
||||
MetaCursorReference *cursor = meta_cursor_reference_take_texture (sprite,
|
||||
cursor_image->xhot,
|
||||
cursor_image->yhot);
|
||||
set_window_cursor (tracker, TRUE, cursor);
|
||||
}
|
||||
XFree (cursor_image);
|
||||
screen->cursor_tracker = self;
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -319,11 +155,10 @@ meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker)
|
||||
{
|
||||
g_return_val_if_fail (META_IS_CURSOR_TRACKER (tracker), NULL);
|
||||
|
||||
if (!meta_is_wayland_compositor ())
|
||||
ensure_xfixes_cursor (tracker);
|
||||
META_CURSOR_TRACKER_GET_CLASS (tracker)->ensure_cursor (tracker);
|
||||
|
||||
if (tracker->displayed_cursor)
|
||||
return meta_cursor_reference_get_cogl_texture (tracker->displayed_cursor, NULL, NULL);
|
||||
if (tracker->current_cursor)
|
||||
return meta_cursor_reference_get_cogl_texture (tracker->current_cursor, NULL, NULL);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
@ -342,11 +177,10 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
|
||||
{
|
||||
g_return_if_fail (META_IS_CURSOR_TRACKER (tracker));
|
||||
|
||||
if (!meta_is_wayland_compositor ())
|
||||
ensure_xfixes_cursor (tracker);
|
||||
META_CURSOR_TRACKER_GET_CLASS (tracker)->ensure_cursor (tracker);
|
||||
|
||||
if (tracker->displayed_cursor)
|
||||
meta_cursor_reference_get_cogl_texture (tracker->displayed_cursor, x, y);
|
||||
if (tracker->current_cursor)
|
||||
meta_cursor_reference_get_cogl_texture (tracker->current_cursor, x, y);
|
||||
else
|
||||
{
|
||||
if (x)
|
||||
@ -356,6 +190,32 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
|
||||
gboolean has_cursor,
|
||||
MetaCursorReference *cursor)
|
||||
{
|
||||
g_clear_pointer (&tracker->window_cursor, meta_cursor_reference_unref);
|
||||
if (cursor)
|
||||
tracker->window_cursor = meta_cursor_reference_ref (cursor);
|
||||
tracker->has_window_cursor = has_cursor;
|
||||
|
||||
_meta_cursor_tracker_sync_cursor (tracker);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
|
||||
MetaCursorReference *cursor)
|
||||
{
|
||||
_meta_cursor_tracker_set_window_cursor (tracker, TRUE, cursor);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker)
|
||||
{
|
||||
_meta_cursor_tracker_set_window_cursor (tracker, FALSE, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker,
|
||||
MetaCursorReference *cursor)
|
||||
@ -364,20 +224,7 @@ meta_cursor_tracker_set_grab_cursor (MetaCursorTracker *tracker,
|
||||
if (cursor)
|
||||
tracker->grab_cursor = meta_cursor_reference_ref (cursor);
|
||||
|
||||
sync_cursor (tracker);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
|
||||
MetaCursorReference *cursor)
|
||||
{
|
||||
set_window_cursor (tracker, TRUE, cursor);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker)
|
||||
{
|
||||
set_window_cursor (tracker, FALSE, NULL);
|
||||
_meta_cursor_tracker_sync_cursor (tracker);
|
||||
}
|
||||
|
||||
void
|
||||
@ -388,57 +235,53 @@ meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
|
||||
if (cursor)
|
||||
tracker->root_cursor = meta_cursor_reference_ref (cursor);
|
||||
|
||||
sync_cursor (tracker);
|
||||
_meta_cursor_tracker_sync_cursor (tracker);
|
||||
}
|
||||
|
||||
static MetaCursorReference *
|
||||
get_current_cursor (MetaCursorTracker *tracker)
|
||||
{
|
||||
if (tracker->grab_cursor)
|
||||
return tracker->grab_cursor;
|
||||
|
||||
if (tracker->has_window_cursor)
|
||||
return tracker->window_cursor;
|
||||
|
||||
return tracker->root_cursor;
|
||||
}
|
||||
|
||||
static MetaCursorReference *
|
||||
get_displayed_cursor (MetaCursorTracker *tracker)
|
||||
{
|
||||
if (!tracker->is_showing)
|
||||
return NULL;
|
||||
|
||||
return get_current_cursor (tracker);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
|
||||
int new_x,
|
||||
int new_y)
|
||||
_meta_cursor_tracker_sync_cursor (MetaCursorTracker *tracker)
|
||||
{
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
MetaCursorReference *current_cursor = get_current_cursor (tracker);
|
||||
MetaCursorReference *displayed_cursor = get_displayed_cursor (tracker);
|
||||
|
||||
meta_cursor_renderer_set_position (tracker->renderer, new_x, new_y);
|
||||
}
|
||||
if (tracker->displayed_cursor != displayed_cursor)
|
||||
{
|
||||
g_clear_pointer (&tracker->displayed_cursor, meta_cursor_reference_unref);
|
||||
if (displayed_cursor)
|
||||
tracker->displayed_cursor = meta_cursor_reference_ref (displayed_cursor);
|
||||
|
||||
static void
|
||||
get_pointer_position_gdk (int *x,
|
||||
int *y,
|
||||
int *mods)
|
||||
{
|
||||
GdkDeviceManager *gmanager;
|
||||
GdkDevice *gdevice;
|
||||
GdkScreen *gscreen;
|
||||
META_CURSOR_TRACKER_GET_CLASS (tracker)->sync_cursor (tracker);
|
||||
}
|
||||
|
||||
gmanager = gdk_display_get_device_manager (gdk_display_get_default ());
|
||||
gdevice = gdk_x11_device_manager_lookup (gmanager, META_VIRTUAL_CORE_POINTER_ID);
|
||||
if (tracker->current_cursor != current_cursor)
|
||||
{
|
||||
g_clear_pointer (&tracker->current_cursor, meta_cursor_reference_unref);
|
||||
if (current_cursor)
|
||||
tracker->current_cursor = meta_cursor_reference_ref (current_cursor);
|
||||
|
||||
gdk_device_get_position (gdevice, &gscreen, x, y);
|
||||
if (mods)
|
||||
gdk_device_get_state (gdevice,
|
||||
gdk_screen_get_root_window (gscreen),
|
||||
NULL, (GdkModifierType*)mods);
|
||||
}
|
||||
|
||||
static void
|
||||
get_pointer_position_clutter (int *x,
|
||||
int *y,
|
||||
int *mods)
|
||||
{
|
||||
ClutterDeviceManager *cmanager;
|
||||
ClutterInputDevice *cdevice;
|
||||
ClutterPoint point;
|
||||
|
||||
cmanager = clutter_device_manager_get_default ();
|
||||
cdevice = clutter_device_manager_get_core_device (cmanager, CLUTTER_POINTER_DEVICE);
|
||||
|
||||
clutter_input_device_get_coords (cdevice, NULL, &point);
|
||||
if (x)
|
||||
*x = point.x;
|
||||
if (y)
|
||||
*y = point.y;
|
||||
if (mods)
|
||||
*mods = clutter_input_device_get_modifier_state (cdevice);
|
||||
g_signal_emit (tracker, signals[CURSOR_CHANGED], 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -447,15 +290,7 @@ meta_cursor_tracker_get_pointer (MetaCursorTracker *tracker,
|
||||
int *y,
|
||||
ClutterModifierType *mods)
|
||||
{
|
||||
/* We can't use the clutter interface when not running as a wayland compositor,
|
||||
because we need to query the server, rather than using the last cached value.
|
||||
OTOH, on wayland we can't use GDK, because that only sees the events
|
||||
we forward to xwayland.
|
||||
*/
|
||||
if (meta_is_wayland_compositor ())
|
||||
get_pointer_position_clutter (x, y, (int*)mods);
|
||||
else
|
||||
get_pointer_position_gdk (x, y, (int*)mods);
|
||||
META_CURSOR_TRACKER_GET_CLASS (tracker)->get_pointer (tracker, x, y, mods);
|
||||
}
|
||||
|
||||
void
|
||||
@ -466,23 +301,51 @@ meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker,
|
||||
return;
|
||||
tracker->is_showing = visible;
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
sync_cursor (tracker);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (visible)
|
||||
XFixesShowCursor (tracker->screen->display->xdisplay,
|
||||
tracker->screen->xroot);
|
||||
else
|
||||
XFixesHideCursor (tracker->screen->display->xdisplay,
|
||||
tracker->screen->xroot);
|
||||
}
|
||||
_meta_cursor_tracker_sync_cursor (tracker);
|
||||
}
|
||||
|
||||
MetaCursorReference *
|
||||
meta_cursor_tracker_get_displayed_cursor (MetaCursorTracker *tracker)
|
||||
meta_cursor_tracker_get_cursor_from_theme (MetaCursorTracker *tracker,
|
||||
MetaCursor meta_cursor)
|
||||
{
|
||||
return tracker->displayed_cursor;
|
||||
MetaCursorReference *cursor;
|
||||
XcursorImage *xc_image;
|
||||
|
||||
if (tracker->theme_cursors[meta_cursor])
|
||||
return meta_cursor_reference_ref (tracker->theme_cursors[meta_cursor]);
|
||||
|
||||
xc_image = meta_display_load_x_cursor (meta_get_display (), meta_cursor);
|
||||
if (!xc_image)
|
||||
return NULL;
|
||||
|
||||
cursor = meta_cursor_reference_from_xcursor_image (xc_image);
|
||||
|
||||
META_CURSOR_TRACKER_GET_CLASS (tracker)->load_cursor_pixels (tracker,
|
||||
cursor,
|
||||
(uint8_t *) xc_image->pixels,
|
||||
xc_image->width,
|
||||
xc_image->height,
|
||||
xc_image->width * 4,
|
||||
GBM_FORMAT_ARGB8888);
|
||||
XcursorImageDestroy (xc_image);
|
||||
|
||||
tracker->theme_cursors[meta_cursor] = cursor;
|
||||
|
||||
return meta_cursor_reference_ref (cursor);
|
||||
}
|
||||
|
||||
MetaCursorReference *
|
||||
meta_cursor_tracker_get_cursor_from_buffer (MetaCursorTracker *tracker,
|
||||
struct wl_resource *buffer,
|
||||
int hot_x,
|
||||
int hot_y)
|
||||
{
|
||||
MetaCursorReference *cursor;
|
||||
|
||||
cursor = meta_cursor_reference_from_buffer (buffer, hot_x, hot_y);
|
||||
|
||||
META_CURSOR_TRACKER_GET_CLASS (tracker)->load_cursor_buffer (tracker,
|
||||
cursor,
|
||||
buffer);
|
||||
return cursor;
|
||||
}
|
||||
|
@ -27,17 +27,23 @@
|
||||
|
||||
#include "display-private.h"
|
||||
#include "screen-private.h"
|
||||
#include "meta-backend.h"
|
||||
#include "backends/native/meta-cursor-renderer-native.h"
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <X11/cursorfont.h>
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
#include <X11/Xcursor/Xcursor.h>
|
||||
|
||||
#include <cogl/cogl-wayland-server.h>
|
||||
|
||||
static MetaCursorReference *
|
||||
meta_cursor_reference_new (void)
|
||||
{
|
||||
MetaCursorReference *self;
|
||||
|
||||
self = g_slice_new0 (MetaCursorReference);
|
||||
self->ref_count = 1;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
MetaCursorReference *
|
||||
meta_cursor_reference_ref (MetaCursorReference *self)
|
||||
{
|
||||
@ -71,77 +77,141 @@ meta_cursor_reference_unref (MetaCursorReference *self)
|
||||
meta_cursor_reference_free (self);
|
||||
}
|
||||
|
||||
static const char *
|
||||
translate_meta_cursor (MetaCursor cursor)
|
||||
static void
|
||||
translate_meta_cursor (MetaCursor cursor,
|
||||
guint *glyph_out,
|
||||
const char **name_out)
|
||||
{
|
||||
guint glyph = XC_num_glyphs;
|
||||
const char *name = NULL;
|
||||
|
||||
switch (cursor)
|
||||
{
|
||||
case META_CURSOR_DEFAULT:
|
||||
return "left_ptr";
|
||||
glyph = XC_left_ptr;
|
||||
break;
|
||||
case META_CURSOR_NORTH_RESIZE:
|
||||
return "top_side";
|
||||
glyph = XC_top_side;
|
||||
break;
|
||||
case META_CURSOR_SOUTH_RESIZE:
|
||||
return "bottom_side";
|
||||
glyph = XC_bottom_side;
|
||||
break;
|
||||
case META_CURSOR_WEST_RESIZE:
|
||||
return "left_side";
|
||||
glyph = XC_left_side;
|
||||
break;
|
||||
case META_CURSOR_EAST_RESIZE:
|
||||
return "right_side";
|
||||
glyph = XC_right_side;
|
||||
break;
|
||||
case META_CURSOR_SE_RESIZE:
|
||||
return "bottom_right_corner";
|
||||
glyph = XC_bottom_right_corner;
|
||||
break;
|
||||
case META_CURSOR_SW_RESIZE:
|
||||
return "bottom_left_corner";
|
||||
glyph = XC_bottom_left_corner;
|
||||
break;
|
||||
case META_CURSOR_NE_RESIZE:
|
||||
return "top_right_corner";
|
||||
glyph = XC_top_right_corner;
|
||||
break;
|
||||
case META_CURSOR_NW_RESIZE:
|
||||
return "top_left_corner";
|
||||
glyph = XC_top_left_corner;
|
||||
break;
|
||||
case META_CURSOR_MOVE_OR_RESIZE_WINDOW:
|
||||
return "fleur";
|
||||
glyph = XC_fleur;
|
||||
break;
|
||||
case META_CURSOR_BUSY:
|
||||
return "watch";
|
||||
glyph = XC_watch;
|
||||
break;
|
||||
case META_CURSOR_DND_IN_DRAG:
|
||||
return "dnd-none";
|
||||
name = "dnd-none";
|
||||
break;
|
||||
case META_CURSOR_DND_MOVE:
|
||||
return "dnd-move";
|
||||
name = "dnd-move";
|
||||
break;
|
||||
case META_CURSOR_DND_COPY:
|
||||
return "dnd-copy";
|
||||
name = "dnd-copy";
|
||||
break;
|
||||
case META_CURSOR_DND_UNSUPPORTED_TARGET:
|
||||
return "dnd-none";
|
||||
name = "dnd-none";
|
||||
break;
|
||||
case META_CURSOR_POINTING_HAND:
|
||||
return "hand2";
|
||||
glyph = XC_hand2;
|
||||
break;
|
||||
case META_CURSOR_CROSSHAIR:
|
||||
return "crosshair";
|
||||
glyph = XC_crosshair;
|
||||
break;
|
||||
case META_CURSOR_IBEAM:
|
||||
return "xterm";
|
||||
glyph = XC_xterm;
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
glyph = 0; /* silence compiler */
|
||||
break;
|
||||
}
|
||||
|
||||
g_assert_not_reached ();
|
||||
*glyph_out = glyph;
|
||||
*name_out = name;
|
||||
}
|
||||
|
||||
static Cursor
|
||||
load_cursor_on_server (MetaDisplay *display,
|
||||
MetaCursor cursor)
|
||||
{
|
||||
Cursor xcursor;
|
||||
guint glyph;
|
||||
const char *name;
|
||||
|
||||
translate_meta_cursor (cursor, &glyph, &name);
|
||||
|
||||
if (name != NULL)
|
||||
xcursor = XcursorLibraryLoadCursor (display->xdisplay, name);
|
||||
else
|
||||
xcursor = XCreateFontCursor (display->xdisplay, glyph);
|
||||
|
||||
return xcursor;
|
||||
}
|
||||
|
||||
Cursor
|
||||
meta_cursor_create_x_cursor (Display *xdisplay,
|
||||
MetaCursor cursor)
|
||||
meta_display_create_x_cursor (MetaDisplay *display,
|
||||
MetaCursor cursor)
|
||||
{
|
||||
return XcursorLibraryLoadCursor (xdisplay, translate_meta_cursor (cursor));
|
||||
return load_cursor_on_server (display, cursor);
|
||||
}
|
||||
|
||||
static XcursorImage *
|
||||
load_cursor_on_client (MetaCursor cursor)
|
||||
load_cursor_on_client (MetaDisplay *display,
|
||||
MetaCursor cursor)
|
||||
{
|
||||
return XcursorLibraryLoadImage (translate_meta_cursor (cursor),
|
||||
meta_prefs_get_cursor_theme (),
|
||||
meta_prefs_get_cursor_size ());
|
||||
XcursorImage *image;
|
||||
guint glyph;
|
||||
const char *name;
|
||||
const char *theme = XcursorGetTheme (display->xdisplay);
|
||||
int size = XcursorGetDefaultSize (display->xdisplay);
|
||||
|
||||
translate_meta_cursor (cursor, &glyph, &name);
|
||||
|
||||
if (name != NULL)
|
||||
image = XcursorLibraryLoadImage (name, theme, size);
|
||||
else
|
||||
image = XcursorShapeLoadImage (glyph, theme, size);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_image_load_gbm_buffer (struct gbm_device *gbm,
|
||||
MetaCursorImage *image,
|
||||
uint8_t *pixels,
|
||||
int width,
|
||||
int height,
|
||||
int rowstride,
|
||||
uint32_t gbm_format)
|
||||
XcursorImage *
|
||||
meta_display_load_x_cursor (MetaDisplay *display,
|
||||
MetaCursor cursor)
|
||||
{
|
||||
return load_cursor_on_client (display, cursor);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_reference_load_gbm_buffer (MetaCursorReference *cursor,
|
||||
struct gbm_device *gbm,
|
||||
uint8_t *pixels,
|
||||
int width,
|
||||
int height,
|
||||
int rowstride,
|
||||
uint32_t gbm_format)
|
||||
{
|
||||
if (width > 64 || height > 64)
|
||||
{
|
||||
@ -155,176 +225,132 @@ meta_cursor_image_load_gbm_buffer (struct gbm_device *gbm,
|
||||
uint8_t buf[4 * 64 * 64];
|
||||
int i;
|
||||
|
||||
image->bo = gbm_bo_create (gbm, 64, 64,
|
||||
gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
|
||||
cursor->image.bo = gbm_bo_create (gbm, 64, 64,
|
||||
gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
|
||||
|
||||
memset (buf, 0, sizeof(buf));
|
||||
for (i = 0; i < height; i++)
|
||||
memcpy (buf + i * 4 * 64, pixels + i * rowstride, width * 4);
|
||||
|
||||
gbm_bo_write (image->bo, buf, 64 * 64 * 4);
|
||||
gbm_bo_write (cursor->image.bo, buf, 64 * 64 * 4);
|
||||
}
|
||||
else
|
||||
meta_warning ("HW cursor for format %d not supported\n", gbm_format);
|
||||
}
|
||||
|
||||
static struct gbm_device *
|
||||
get_gbm_device (void)
|
||||
void
|
||||
meta_cursor_reference_import_gbm_buffer (MetaCursorReference *cursor,
|
||||
struct gbm_device *gbm,
|
||||
struct wl_resource *buffer,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
MetaBackend *meta_backend = meta_get_backend ();
|
||||
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend);
|
||||
/* HW cursors must be 64x64, but 64x64 is huge, and no cursor theme actually uses
|
||||
that, so themed cursors must be padded with transparent pixels to fill the
|
||||
overlay. This is trivial if we have CPU access to the data, but it's not
|
||||
possible if the buffer is in GPU memory (and possibly tiled too), so if we
|
||||
don't get the right size, we fallback to GL.
|
||||
*/
|
||||
if (width != 64 || height != 64)
|
||||
{
|
||||
meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (META_IS_CURSOR_RENDERER_NATIVE (renderer))
|
||||
return meta_cursor_renderer_native_get_gbm_device (META_CURSOR_RENDERER_NATIVE (renderer));
|
||||
else
|
||||
return NULL;
|
||||
cursor->image.bo = gbm_bo_import (gbm, GBM_BO_IMPORT_WL_BUFFER,
|
||||
buffer, GBM_BO_USE_CURSOR_64X64);
|
||||
if (!cursor->image.bo)
|
||||
meta_warning ("Importing HW cursor from wl_buffer failed\n");
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_image_load_from_xcursor_image (MetaCursorImage *image,
|
||||
XcursorImage *xc_image)
|
||||
MetaCursorReference *
|
||||
meta_cursor_reference_from_xfixes_cursor_image (XFixesCursorImage *cursor_image)
|
||||
{
|
||||
MetaCursorReference *cursor;
|
||||
CoglTexture2D *sprite;
|
||||
CoglContext *ctx;
|
||||
guint8 *cursor_data;
|
||||
gboolean free_cursor_data;
|
||||
|
||||
cursor = meta_cursor_reference_new ();
|
||||
|
||||
/* Like all X APIs, XFixesGetCursorImage() returns arrays of 32-bit
|
||||
* quantities as arrays of long; we need to convert on 64 bit */
|
||||
if (sizeof(long) == 4)
|
||||
{
|
||||
cursor_data = (guint8 *)cursor_image->pixels;
|
||||
free_cursor_data = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i, j;
|
||||
guint32 *cursor_words;
|
||||
gulong *p;
|
||||
guint32 *q;
|
||||
|
||||
cursor_words = g_new (guint32, cursor_image->width * cursor_image->height);
|
||||
cursor_data = (guint8 *)cursor_words;
|
||||
|
||||
p = cursor_image->pixels;
|
||||
q = cursor_words;
|
||||
for (j = 0; j < cursor_image->height; j++)
|
||||
for (i = 0; i < cursor_image->width; i++)
|
||||
*(q++) = *(p++);
|
||||
|
||||
free_cursor_data = TRUE;
|
||||
}
|
||||
|
||||
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
sprite = cogl_texture_2d_new_from_data (ctx,
|
||||
cursor_image->width,
|
||||
cursor_image->height,
|
||||
CLUTTER_CAIRO_FORMAT_ARGB32,
|
||||
cursor_image->width * 4, /* stride */
|
||||
cursor_data,
|
||||
NULL);
|
||||
if (free_cursor_data)
|
||||
g_free (cursor_data);
|
||||
|
||||
cursor->image.texture = sprite;
|
||||
cursor->image.hot_x = cursor_image->xhot;
|
||||
cursor->image.hot_y = cursor_image->yhot;
|
||||
|
||||
return cursor;
|
||||
}
|
||||
|
||||
MetaCursorReference *
|
||||
meta_cursor_reference_from_xcursor_image (XcursorImage *xc_image)
|
||||
{
|
||||
MetaCursorReference *cursor;
|
||||
int width, height, rowstride;
|
||||
CoglPixelFormat cogl_format;
|
||||
uint32_t gbm_format;
|
||||
ClutterBackend *clutter_backend;
|
||||
CoglContext *cogl_context;
|
||||
struct gbm_device *gbm;
|
||||
|
||||
cursor = meta_cursor_reference_new ();
|
||||
|
||||
width = xc_image->width;
|
||||
height = xc_image->height;
|
||||
rowstride = width * 4;
|
||||
|
||||
gbm_format = GBM_FORMAT_ARGB8888;
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
cogl_format = COGL_PIXEL_FORMAT_BGRA_8888;
|
||||
#else
|
||||
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888;
|
||||
#endif
|
||||
|
||||
image->hot_x = xc_image->xhot;
|
||||
image->hot_y = xc_image->yhot;
|
||||
cursor->image.hot_x = xc_image->xhot;
|
||||
cursor->image.hot_y = xc_image->yhot;
|
||||
|
||||
clutter_backend = clutter_get_default_backend ();
|
||||
cogl_context = clutter_backend_get_cogl_context (clutter_backend);
|
||||
image->texture = cogl_texture_2d_new_from_data (cogl_context,
|
||||
width, height,
|
||||
cogl_format,
|
||||
rowstride,
|
||||
(uint8_t *) xc_image->pixels,
|
||||
NULL);
|
||||
|
||||
gbm = get_gbm_device ();
|
||||
if (gbm)
|
||||
meta_cursor_image_load_gbm_buffer (gbm,
|
||||
image,
|
||||
(uint8_t *) xc_image->pixels,
|
||||
width, height, rowstride,
|
||||
gbm_format);
|
||||
}
|
||||
|
||||
MetaCursorReference *
|
||||
meta_cursor_reference_from_theme (MetaCursor cursor)
|
||||
{
|
||||
MetaCursorReference *self;
|
||||
XcursorImage *image;
|
||||
|
||||
image = load_cursor_on_client (cursor);
|
||||
if (!image)
|
||||
return NULL;
|
||||
|
||||
self = g_slice_new0 (MetaCursorReference);
|
||||
self->ref_count = 1;
|
||||
self->cursor = cursor;
|
||||
meta_cursor_image_load_from_xcursor_image (&self->image, image);
|
||||
|
||||
XcursorImageDestroy (image);
|
||||
return self;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_image_load_from_buffer (MetaCursorImage *image,
|
||||
struct wl_resource *buffer,
|
||||
int hot_x,
|
||||
int hot_y)
|
||||
{
|
||||
struct gbm_device *gbm = get_gbm_device ();
|
||||
|
||||
ClutterBackend *backend;
|
||||
CoglContext *cogl_context;
|
||||
struct wl_shm_buffer *shm_buffer;
|
||||
uint32_t gbm_format;
|
||||
int width, height;
|
||||
|
||||
image->hot_x = hot_x;
|
||||
image->hot_y = hot_y;
|
||||
|
||||
backend = clutter_get_default_backend ();
|
||||
cogl_context = clutter_backend_get_cogl_context (backend);
|
||||
|
||||
image->texture = cogl_wayland_texture_2d_new_from_buffer (cogl_context, buffer, NULL);
|
||||
|
||||
width = cogl_texture_get_width (COGL_TEXTURE (image->texture));
|
||||
height = cogl_texture_get_height (COGL_TEXTURE (image->texture));
|
||||
|
||||
shm_buffer = wl_shm_buffer_get (buffer);
|
||||
if (shm_buffer)
|
||||
{
|
||||
if (gbm)
|
||||
{
|
||||
int rowstride = wl_shm_buffer_get_stride (shm_buffer);
|
||||
|
||||
switch (wl_shm_buffer_get_format (shm_buffer))
|
||||
{
|
||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
case WL_SHM_FORMAT_ARGB8888:
|
||||
gbm_format = GBM_FORMAT_ARGB8888;
|
||||
break;
|
||||
case WL_SHM_FORMAT_XRGB8888:
|
||||
gbm_format = GBM_FORMAT_XRGB8888;
|
||||
break;
|
||||
#else
|
||||
case WL_SHM_FORMAT_ARGB8888:
|
||||
gbm_format = GBM_FORMAT_ARGB8888;
|
||||
break;
|
||||
case WL_SHM_FORMAT_XRGB8888:
|
||||
gbm_format = GBM_FORMAT_XRGB8888;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
g_warn_if_reached ();
|
||||
gbm_format = GBM_FORMAT_ARGB8888;
|
||||
}
|
||||
|
||||
meta_cursor_image_load_gbm_buffer (gbm,
|
||||
image,
|
||||
(uint8_t *) wl_shm_buffer_get_data (shm_buffer),
|
||||
width, height, rowstride,
|
||||
gbm_format);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* HW cursors must be 64x64, but 64x64 is huge, and no cursor theme actually uses
|
||||
that, so themed cursors must be padded with transparent pixels to fill the
|
||||
overlay. This is trivial if we have CPU access to the data, but it's not
|
||||
possible if the buffer is in GPU memory (and possibly tiled too), so if we
|
||||
don't get the right size, we fallback to GL.
|
||||
*/
|
||||
if (width != 64 || height != 64)
|
||||
{
|
||||
meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (gbm)
|
||||
{
|
||||
image->bo = gbm_bo_import (gbm, GBM_BO_IMPORT_WL_BUFFER,
|
||||
buffer, GBM_BO_USE_CURSOR_64X64);
|
||||
if (!image->bo)
|
||||
meta_warning ("Importing HW cursor from wl_buffer failed\n");
|
||||
}
|
||||
}
|
||||
cursor->image.texture = cogl_texture_2d_new_from_data (cogl_context,
|
||||
width, height,
|
||||
cogl_format,
|
||||
rowstride,
|
||||
(uint8_t *) xc_image->pixels,
|
||||
NULL);
|
||||
return cursor;
|
||||
}
|
||||
|
||||
MetaCursorReference *
|
||||
@ -332,13 +358,21 @@ meta_cursor_reference_from_buffer (struct wl_resource *buffer,
|
||||
int hot_x,
|
||||
int hot_y)
|
||||
{
|
||||
MetaCursorReference *self;
|
||||
MetaCursorReference *cursor;
|
||||
ClutterBackend *backend;
|
||||
CoglContext *cogl_context;
|
||||
|
||||
self = g_slice_new0 (MetaCursorReference);
|
||||
self->ref_count = 1;
|
||||
meta_cursor_image_load_from_buffer (&self->image, buffer, hot_x, hot_y);
|
||||
cursor = meta_cursor_reference_new ();
|
||||
|
||||
return self;
|
||||
cursor->image.hot_x = hot_x;
|
||||
cursor->image.hot_y = hot_y;
|
||||
|
||||
backend = clutter_get_default_backend ();
|
||||
cogl_context = clutter_backend_get_cogl_context (backend);
|
||||
|
||||
cursor->image.texture = cogl_wayland_texture_2d_new_from_buffer (cogl_context, buffer, NULL);
|
||||
|
||||
return cursor;
|
||||
}
|
||||
|
||||
CoglTexture *
|
||||
@ -364,9 +398,3 @@ meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor,
|
||||
*hot_y = cursor->image.hot_y;
|
||||
return cursor->image.bo;
|
||||
}
|
||||
|
||||
MetaCursor
|
||||
meta_cursor_reference_get_meta_cursor (MetaCursorReference *cursor)
|
||||
{
|
||||
return cursor->cursor;
|
||||
}
|
||||
|
@ -27,18 +27,4 @@ typedef struct _MetaCursorReference MetaCursorReference;
|
||||
MetaCursorReference * meta_cursor_reference_ref (MetaCursorReference *cursor);
|
||||
void meta_cursor_reference_unref (MetaCursorReference *cursor);
|
||||
|
||||
#include <meta/common.h>
|
||||
#include <wayland-server.h>
|
||||
|
||||
MetaCursorReference * meta_cursor_reference_from_theme (MetaCursor cursor);
|
||||
|
||||
MetaCursorReference * meta_cursor_reference_from_buffer (struct wl_resource *buffer,
|
||||
int hot_x,
|
||||
int hot_y);
|
||||
|
||||
MetaCursor meta_cursor_reference_get_meta_cursor (MetaCursorReference *cursor);
|
||||
|
||||
Cursor meta_cursor_create_x_cursor (Display *xdisplay,
|
||||
MetaCursor cursor);
|
||||
|
||||
#endif /* META_CURSOR_H */
|
||||
|
@ -38,7 +38,8 @@
|
||||
#include <meta/meta-idle-monitor.h>
|
||||
#include "meta-idle-monitor-private.h"
|
||||
#include "meta-idle-monitor-dbus.h"
|
||||
#include "meta-backend.h"
|
||||
#include "backends/x11/meta-idle-monitor-xsync.h"
|
||||
#include "backends/native/meta-idle-monitor-native.h"
|
||||
|
||||
G_STATIC_ASSERT(sizeof(unsigned long) == sizeof(gpointer));
|
||||
|
||||
@ -53,6 +54,9 @@ static GParamSpec *obj_props[PROP_LAST];
|
||||
|
||||
G_DEFINE_TYPE (MetaIdleMonitor, meta_idle_monitor, G_TYPE_OBJECT)
|
||||
|
||||
static MetaIdleMonitor *device_monitors[256];
|
||||
static int device_id_max;
|
||||
|
||||
void
|
||||
_meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch)
|
||||
{
|
||||
@ -156,6 +160,36 @@ meta_idle_monitor_init (MetaIdleMonitor *monitor)
|
||||
{
|
||||
}
|
||||
|
||||
static GType
|
||||
get_idle_monitor_type (void)
|
||||
{
|
||||
if (meta_is_wayland_compositor ())
|
||||
return META_TYPE_IDLE_MONITOR_NATIVE;
|
||||
else
|
||||
return META_TYPE_IDLE_MONITOR_XSYNC;
|
||||
}
|
||||
|
||||
static void
|
||||
ensure_device_monitor (int device_id)
|
||||
{
|
||||
if (device_monitors[device_id])
|
||||
return;
|
||||
|
||||
device_monitors[device_id] = g_object_new (get_idle_monitor_type (),
|
||||
"device-id", device_id,
|
||||
NULL);
|
||||
device_id_max = MAX (device_id_max, device_id);
|
||||
}
|
||||
|
||||
/* FIXME -- destroy device monitors at some point */
|
||||
G_GNUC_UNUSED static void
|
||||
destroy_device_monitor (int device_id)
|
||||
{
|
||||
g_clear_object (&device_monitors[device_id]);
|
||||
if (device_id == device_id_max)
|
||||
device_id_max--;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_idle_monitor_get_core:
|
||||
*
|
||||
@ -166,8 +200,8 @@ meta_idle_monitor_init (MetaIdleMonitor *monitor)
|
||||
MetaIdleMonitor *
|
||||
meta_idle_monitor_get_core (void)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
return meta_backend_get_idle_monitor (backend, 0);
|
||||
ensure_device_monitor (0);
|
||||
return device_monitors[0];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -181,8 +215,10 @@ meta_idle_monitor_get_core (void)
|
||||
MetaIdleMonitor *
|
||||
meta_idle_monitor_get_for_device (int device_id)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
return meta_backend_get_idle_monitor (backend, device_id);
|
||||
g_return_val_if_fail (device_id > 0 && device_id < 256, NULL);
|
||||
|
||||
ensure_device_monitor (device_id);
|
||||
return device_monitors[device_id];
|
||||
}
|
||||
|
||||
static MetaIdleMonitorWatch *
|
||||
@ -316,3 +352,16 @@ meta_idle_monitor_get_idletime (MetaIdleMonitor *monitor)
|
||||
{
|
||||
return META_IDLE_MONITOR_GET_CLASS (monitor)->get_idletime (monitor);
|
||||
}
|
||||
|
||||
void
|
||||
meta_idle_monitor_xsync_handle_xevent_all (XEvent *xevent)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
return;
|
||||
|
||||
for (i = 0; i <= device_id_max; i++)
|
||||
if (device_monitors[i])
|
||||
meta_idle_monitor_xsync_handle_xevent (device_monitors[i], (XSyncAlarmNotifyEvent*)xevent);
|
||||
}
|
||||
|
@ -840,9 +840,6 @@ meta_monitor_config_get_stored (MetaMonitorConfig *self,
|
||||
MetaConfiguration key;
|
||||
MetaConfiguration *stored;
|
||||
|
||||
if (n_outputs == 0)
|
||||
return NULL;
|
||||
|
||||
make_config_key (&key, outputs, n_outputs, -1);
|
||||
stored = g_hash_table_lookup (self->configs, &key);
|
||||
|
||||
@ -1250,12 +1247,6 @@ meta_monitor_config_make_default (MetaMonitorConfig *self,
|
||||
outputs = meta_monitor_manager_get_outputs (manager, &n_outputs);
|
||||
meta_monitor_manager_get_screen_limits (manager, &max_width, &max_height);
|
||||
|
||||
if (n_outputs == 0)
|
||||
{
|
||||
meta_verbose ("No output connected, not applying configuration\n");
|
||||
return;
|
||||
}
|
||||
|
||||
default_config = make_default_config (self, outputs, n_outputs, max_width, max_height);
|
||||
|
||||
if (default_config != NULL)
|
||||
|
@ -36,8 +36,9 @@
|
||||
#include "util-private.h"
|
||||
#include <meta/errors.h>
|
||||
#include "meta-monitor-config.h"
|
||||
#include "backends/native/meta-monitor-manager-kms.h"
|
||||
#include "backends/x11/meta-monitor-manager-xrandr.h"
|
||||
#include "meta-backend.h"
|
||||
#include "meta-monitor-manager-dummy.h"
|
||||
|
||||
enum {
|
||||
CONFIRM_DISPLAY_CHANGE,
|
||||
@ -167,6 +168,58 @@ make_logical_config (MetaMonitorManager *manager)
|
||||
manager->monitor_infos = (void*)g_array_free (monitor_infos, FALSE);
|
||||
}
|
||||
|
||||
static GType
|
||||
get_default_backend (void)
|
||||
{
|
||||
#if defined(CLUTTER_WINDOWING_EGL)
|
||||
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
|
||||
return META_TYPE_MONITOR_MANAGER_KMS;
|
||||
#endif
|
||||
|
||||
#if defined(CLUTTER_WINDOWING_X11)
|
||||
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_X11))
|
||||
{
|
||||
/* If we're a Wayland compositor using the X11 backend,
|
||||
* we're a nested configuration, so return the dummy
|
||||
* monitor setup. */
|
||||
if (meta_is_wayland_compositor ())
|
||||
return META_TYPE_MONITOR_MANAGER_DUMMY;
|
||||
else
|
||||
return META_TYPE_MONITOR_MANAGER_XRANDR;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CLUTTER_WINDOWING_WAYLAND)
|
||||
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_WAYLAND))
|
||||
{
|
||||
/* Use the dummy implementation on Wayland for now.
|
||||
* In the future, we should support wl_fullscreen_output
|
||||
* which will have CRTC management in the protocol. */
|
||||
return META_TYPE_MONITOR_MANAGER_DUMMY;
|
||||
}
|
||||
#endif
|
||||
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
static MetaMonitorManager *
|
||||
meta_monitor_manager_new (void)
|
||||
{
|
||||
const char *env;
|
||||
GType type;
|
||||
|
||||
env = g_getenv ("META_DEBUG_MULTIMONITOR");
|
||||
|
||||
if (env == NULL)
|
||||
type = get_default_backend ();
|
||||
else if (strcmp (env, "xrandr") == 0)
|
||||
type = META_TYPE_MONITOR_MANAGER_XRANDR;
|
||||
else
|
||||
type = META_TYPE_MONITOR_MANAGER;
|
||||
|
||||
return g_object_new (type, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_constructed (GObject *object)
|
||||
{
|
||||
@ -483,13 +536,13 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
|
||||
|
||||
g_variant_builder_add (&crtc_builder, "(uxiiiiiuaua{sv})",
|
||||
i, /* ID */
|
||||
(gint64)crtc->crtc_id,
|
||||
crtc->crtc_id,
|
||||
(int)crtc->rect.x,
|
||||
(int)crtc->rect.y,
|
||||
(int)crtc->rect.width,
|
||||
(int)crtc->rect.height,
|
||||
(int)(crtc->current_mode ? crtc->current_mode - manager->modes : -1),
|
||||
(guint32)crtc->transform,
|
||||
crtc->transform,
|
||||
&transforms,
|
||||
NULL /* properties */);
|
||||
}
|
||||
@ -560,7 +613,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
|
||||
|
||||
g_variant_builder_add (&output_builder, "(uxiausauaua{sv})",
|
||||
i, /* ID */
|
||||
(gint64)output->output_id,
|
||||
output->output_id,
|
||||
(int)(output->crtc ? output->crtc - manager->crtcs : -1),
|
||||
&crtcs,
|
||||
output->name,
|
||||
@ -575,9 +628,9 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
|
||||
|
||||
g_variant_builder_add (&mode_builder, "(uxuud)",
|
||||
i, /* ID */
|
||||
(gint64)mode->mode_id,
|
||||
(guint32)mode->width,
|
||||
(guint32)mode->height,
|
||||
mode->mode_id,
|
||||
mode->width,
|
||||
mode->height,
|
||||
(double)mode->refresh_rate);
|
||||
}
|
||||
|
||||
@ -878,7 +931,6 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
|
||||
if (persistent)
|
||||
{
|
||||
manager->persistent_timeout_id = g_timeout_add_seconds (20, save_config_timeout, manager);
|
||||
g_source_set_name_by_id (manager->persistent_timeout_id, "[mutter] save_config_timeout");
|
||||
g_signal_emit (manager, signals[CONFIRM_DISPLAY_CHANGE], 0);
|
||||
}
|
||||
|
||||
@ -1126,12 +1178,20 @@ initialize_dbus_interface (MetaMonitorManager *manager)
|
||||
g_object_unref);
|
||||
}
|
||||
|
||||
static MetaMonitorManager *global_monitor_manager;
|
||||
|
||||
void
|
||||
meta_monitor_manager_initialize (void)
|
||||
{
|
||||
global_monitor_manager = meta_monitor_manager_new ();
|
||||
}
|
||||
|
||||
MetaMonitorManager *
|
||||
meta_monitor_manager_get (void)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
g_assert (global_monitor_manager != NULL);
|
||||
|
||||
return meta_backend_get_monitor_manager (backend);
|
||||
return global_monitor_manager;
|
||||
}
|
||||
|
||||
MetaMonitorInfo *
|
||||
@ -1217,3 +1277,16 @@ meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager)
|
||||
g_free (old_monitor_infos);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_monitor_manager_handle_xevent (MetaMonitorManager *manager,
|
||||
XEvent *event)
|
||||
{
|
||||
MetaMonitorManagerClass *klass;
|
||||
|
||||
klass = META_MONITOR_MANAGER_GET_CLASS (manager);
|
||||
if (klass->handle_xevent)
|
||||
return klass->handle_xevent (manager, event);
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,6 @@
|
||||
|
||||
#include "meta-display-config-shared.h"
|
||||
#include "meta-dbus-display-config.h"
|
||||
#include "meta-cursor.h"
|
||||
|
||||
typedef struct _MetaMonitorManagerClass MetaMonitorManagerClass;
|
||||
typedef struct _MetaMonitorManager MetaMonitorManager;
|
||||
@ -124,7 +123,8 @@ struct _MetaCRTC
|
||||
/* Used when changing configuration */
|
||||
gboolean is_dirty;
|
||||
|
||||
MetaCursorReference *cursor;
|
||||
/* Updated by MetaCursorTracker */
|
||||
gboolean has_hw_cursor;
|
||||
};
|
||||
|
||||
struct _MetaMonitorMode
|
||||
@ -285,10 +285,14 @@ struct _MetaMonitorManagerClass
|
||||
unsigned short *,
|
||||
unsigned short *,
|
||||
unsigned short *);
|
||||
|
||||
gboolean (*handle_xevent) (MetaMonitorManager *,
|
||||
XEvent *);
|
||||
};
|
||||
|
||||
GType meta_monitor_manager_get_type (void);
|
||||
|
||||
void meta_monitor_manager_initialize (void);
|
||||
MetaMonitorManager *meta_monitor_manager_get (void);
|
||||
|
||||
void meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager);
|
||||
@ -309,6 +313,9 @@ void meta_monitor_manager_get_resources (MetaMonitorManager
|
||||
|
||||
int meta_monitor_manager_get_primary_index (MetaMonitorManager *manager);
|
||||
|
||||
gboolean meta_monitor_manager_handle_xevent (MetaMonitorManager *manager,
|
||||
XEvent *event);
|
||||
|
||||
void meta_monitor_manager_get_screen_size (MetaMonitorManager *manager,
|
||||
int *width,
|
||||
int *height);
|
||||
|
@ -1,235 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <meta/main.h>
|
||||
#include <clutter/evdev/clutter-evdev.h>
|
||||
#include "meta-backend-native.h"
|
||||
|
||||
#include "meta-idle-monitor-native.h"
|
||||
#include "meta-monitor-manager-kms.h"
|
||||
#include "meta-cursor-renderer-native.h"
|
||||
#include "meta-launcher.h"
|
||||
|
||||
struct _MetaBackendNativePrivate
|
||||
{
|
||||
MetaLauncher *launcher;
|
||||
};
|
||||
typedef struct _MetaBackendNativePrivate MetaBackendNativePrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaBackendNative, meta_backend_native, META_TYPE_BACKEND);
|
||||
|
||||
/*
|
||||
* The pointer constrain code is mostly a rip-off of the XRandR code from Xorg.
|
||||
* (from xserver/randr/rrcrtc.c, RRConstrainCursorHarder)
|
||||
*
|
||||
* Copyright © 2006 Keith Packard
|
||||
* Copyright 2010 Red Hat, Inc
|
||||
*
|
||||
*/
|
||||
|
||||
static gboolean
|
||||
check_all_screen_monitors(MetaMonitorInfo *monitors,
|
||||
unsigned n_monitors,
|
||||
float x,
|
||||
float y)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < n_monitors; i++)
|
||||
{
|
||||
MetaMonitorInfo *monitor = &monitors[i];
|
||||
int left, right, top, bottom;
|
||||
|
||||
left = monitor->rect.x;
|
||||
right = left + monitor->rect.width;
|
||||
top = monitor->rect.y;
|
||||
bottom = left + monitor->rect.height;
|
||||
|
||||
if ((x >= left) && (x < right) && (y >= top) && (y < bottom))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
constrain_all_screen_monitors (ClutterInputDevice *device,
|
||||
MetaMonitorInfo *monitors,
|
||||
unsigned n_monitors,
|
||||
float *x,
|
||||
float *y)
|
||||
{
|
||||
ClutterPoint current;
|
||||
unsigned int i;
|
||||
|
||||
clutter_input_device_get_coords (device, NULL, ¤t);
|
||||
|
||||
/* if we're trying to escape, clamp to the CRTC we're coming from */
|
||||
for (i = 0; i < n_monitors; i++)
|
||||
{
|
||||
MetaMonitorInfo *monitor = &monitors[i];
|
||||
int left, right, top, bottom;
|
||||
float nx, ny;
|
||||
|
||||
left = monitor->rect.x;
|
||||
right = left + monitor->rect.width;
|
||||
top = monitor->rect.y;
|
||||
bottom = left + monitor->rect.height;
|
||||
|
||||
nx = current.x;
|
||||
ny = current.y;
|
||||
|
||||
if ((nx >= left) && (nx < right) && (ny >= top) && (ny < bottom))
|
||||
{
|
||||
if (*x < left)
|
||||
*x = left;
|
||||
if (*x >= right)
|
||||
*x = right - 1;
|
||||
if (*y < top)
|
||||
*y = top;
|
||||
if (*y >= bottom)
|
||||
*y = bottom - 1;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_constrain_callback (ClutterInputDevice *device,
|
||||
guint32 time,
|
||||
float *new_x,
|
||||
float *new_y,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaMonitorManager *monitor_manager;
|
||||
MetaMonitorInfo *monitors;
|
||||
unsigned int n_monitors;
|
||||
gboolean ret;
|
||||
|
||||
monitor_manager = meta_monitor_manager_get ();
|
||||
monitors = meta_monitor_manager_get_monitor_infos (monitor_manager, &n_monitors);
|
||||
|
||||
/* if we're moving inside a monitor, we're fine */
|
||||
ret = check_all_screen_monitors(monitors, n_monitors, *new_x, *new_y);
|
||||
if (ret == TRUE)
|
||||
return;
|
||||
|
||||
/* if we're trying to escape, clamp to the CRTC we're coming from */
|
||||
constrain_all_screen_monitors(device, monitors, n_monitors, new_x, new_y);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_native_post_init (MetaBackend *backend)
|
||||
{
|
||||
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
|
||||
|
||||
META_BACKEND_CLASS (meta_backend_native_parent_class)->post_init (backend);
|
||||
|
||||
clutter_evdev_set_pointer_constrain_callback (manager, pointer_constrain_callback,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
static MetaIdleMonitor *
|
||||
meta_backend_native_create_idle_monitor (MetaBackend *backend,
|
||||
int device_id)
|
||||
{
|
||||
return g_object_new (META_TYPE_IDLE_MONITOR_NATIVE,
|
||||
"device-id", device_id,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static MetaMonitorManager *
|
||||
meta_backend_native_create_monitor_manager (MetaBackend *backend)
|
||||
{
|
||||
return g_object_new (META_TYPE_MONITOR_MANAGER_KMS, NULL);
|
||||
}
|
||||
|
||||
static MetaCursorRenderer *
|
||||
meta_backend_native_create_cursor_renderer (MetaBackend *backend)
|
||||
{
|
||||
return g_object_new (META_TYPE_CURSOR_RENDERER_NATIVE, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_native_class_init (MetaBackendNativeClass *klass)
|
||||
{
|
||||
MetaBackendClass *backend_class = META_BACKEND_CLASS (klass);
|
||||
|
||||
backend_class->post_init = meta_backend_native_post_init;
|
||||
backend_class->create_idle_monitor = meta_backend_native_create_idle_monitor;
|
||||
backend_class->create_monitor_manager = meta_backend_native_create_monitor_manager;
|
||||
backend_class->create_cursor_renderer = meta_backend_native_create_cursor_renderer;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_native_init (MetaBackendNative *native)
|
||||
{
|
||||
MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native);
|
||||
|
||||
/* We're a display server, so start talking to weston-launch. */
|
||||
priv->launcher = meta_launcher_new ();
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_activate_vt (int vt, GError **error)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaBackendNative *native = META_BACKEND_NATIVE (backend);
|
||||
MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native);
|
||||
|
||||
return meta_launcher_activate_vt (priv->launcher, vt, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_activate_session:
|
||||
*
|
||||
* Tells mutter to activate the session. When mutter is a
|
||||
* Wayland compositor, this tells logind to switch over to
|
||||
* the new session.
|
||||
*/
|
||||
gboolean
|
||||
meta_activate_session (void)
|
||||
{
|
||||
GError *error = NULL;
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
|
||||
/* Do nothing. */
|
||||
if (!META_IS_BACKEND_NATIVE (backend))
|
||||
return TRUE;
|
||||
|
||||
MetaBackendNative *native = META_BACKEND_NATIVE (backend);
|
||||
MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native);
|
||||
|
||||
if (!meta_launcher_activate_session (priv->launcher, &error))
|
||||
{
|
||||
g_warning ("Could not activate session: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#ifndef META_BACKEND_NATIVE_H
|
||||
#define META_BACKEND_NATIVE_H
|
||||
|
||||
#include "backends/meta-backend-private.h"
|
||||
|
||||
#define META_TYPE_BACKEND_NATIVE (meta_backend_native_get_type ())
|
||||
#define META_BACKEND_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BACKEND_NATIVE, MetaBackendNative))
|
||||
#define META_BACKEND_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_BACKEND_NATIVE, MetaBackendNativeClass))
|
||||
#define META_IS_BACKEND_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_BACKEND_NATIVE))
|
||||
#define META_IS_BACKEND_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_BACKEND_NATIVE))
|
||||
#define META_BACKEND_NATIVE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_BACKEND_NATIVE, MetaBackendNativeClass))
|
||||
|
||||
typedef struct _MetaBackendNative MetaBackendNative;
|
||||
typedef struct _MetaBackendNativeClass MetaBackendNativeClass;
|
||||
|
||||
struct _MetaBackendNative
|
||||
{
|
||||
MetaBackend parent;
|
||||
};
|
||||
|
||||
struct _MetaBackendNativeClass
|
||||
{
|
||||
MetaBackendClass parent_class;
|
||||
};
|
||||
|
||||
GType meta_backend_native_get_type (void) G_GNUC_CONST;
|
||||
|
||||
gboolean meta_activate_vt (int vt, GError **error);
|
||||
|
||||
#endif /* META_BACKEND_NATIVE_H */
|
@ -1,208 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "meta-cursor-renderer-native.h"
|
||||
|
||||
#include <gbm.h>
|
||||
|
||||
#include "meta-cursor-private.h"
|
||||
#include "meta-monitor-manager.h"
|
||||
|
||||
struct _MetaCursorRendererNativePrivate
|
||||
{
|
||||
gboolean has_hw_cursor;
|
||||
|
||||
int drm_fd;
|
||||
struct gbm_device *gbm;
|
||||
};
|
||||
typedef struct _MetaCursorRendererNativePrivate MetaCursorRendererNativePrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRendererNative, meta_cursor_renderer_native, META_TYPE_CURSOR_RENDERER);
|
||||
|
||||
static void
|
||||
meta_cursor_renderer_native_finalize (GObject *object)
|
||||
{
|
||||
MetaCursorRendererNative *renderer = META_CURSOR_RENDERER_NATIVE (object);
|
||||
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (renderer);
|
||||
|
||||
if (priv->gbm)
|
||||
gbm_device_destroy (priv->gbm);
|
||||
|
||||
G_OBJECT_CLASS (meta_cursor_renderer_native_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
set_crtc_cursor (MetaCursorRendererNative *native,
|
||||
MetaCRTC *crtc,
|
||||
MetaCursorReference *cursor,
|
||||
gboolean force)
|
||||
{
|
||||
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
|
||||
|
||||
if (crtc->cursor == cursor && !force)
|
||||
return;
|
||||
|
||||
crtc->cursor = cursor;
|
||||
|
||||
if (cursor)
|
||||
{
|
||||
struct gbm_bo *bo;
|
||||
union gbm_bo_handle handle;
|
||||
int width, height;
|
||||
int hot_x, hot_y;
|
||||
|
||||
bo = meta_cursor_reference_get_gbm_bo (cursor, &hot_x, &hot_y);
|
||||
|
||||
handle = gbm_bo_get_handle (bo);
|
||||
width = gbm_bo_get_width (bo);
|
||||
height = gbm_bo_get_height (bo);
|
||||
|
||||
drmModeSetCursor2 (priv->drm_fd, crtc->crtc_id, handle.u32,
|
||||
width, height, hot_x, hot_y);
|
||||
}
|
||||
else
|
||||
{
|
||||
drmModeSetCursor2 (priv->drm_fd, crtc->crtc_id, 0, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_hw_cursor (MetaCursorRendererNative *native,
|
||||
gboolean force)
|
||||
{
|
||||
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
|
||||
MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native);
|
||||
const MetaRectangle *cursor_rect = meta_cursor_renderer_get_rect (renderer);
|
||||
MetaCursorReference *cursor = meta_cursor_renderer_get_cursor (renderer);
|
||||
MetaMonitorManager *monitors;
|
||||
MetaCRTC *crtcs;
|
||||
unsigned int i, n_crtcs;
|
||||
|
||||
monitors = meta_monitor_manager_get ();
|
||||
meta_monitor_manager_get_resources (monitors, NULL, NULL, &crtcs, &n_crtcs, NULL, NULL);
|
||||
|
||||
for (i = 0; i < n_crtcs; i++)
|
||||
{
|
||||
gboolean crtc_should_have_cursor;
|
||||
MetaCursorReference *crtc_cursor;
|
||||
MetaRectangle *crtc_rect;
|
||||
|
||||
crtc_rect = &crtcs[i].rect;
|
||||
|
||||
crtc_should_have_cursor = (priv->has_hw_cursor && meta_rectangle_overlap (cursor_rect, crtc_rect));
|
||||
if (crtc_should_have_cursor)
|
||||
crtc_cursor = cursor;
|
||||
else
|
||||
crtc_cursor = NULL;
|
||||
|
||||
set_crtc_cursor (native, &crtcs[i], crtc_cursor, force);
|
||||
|
||||
if (cursor)
|
||||
{
|
||||
drmModeMoveCursor (priv->drm_fd, crtcs[i].crtc_id,
|
||||
cursor_rect->x - crtc_rect->x,
|
||||
cursor_rect->y - crtc_rect->y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
should_have_hw_cursor (MetaCursorRenderer *renderer)
|
||||
{
|
||||
MetaCursorReference *cursor = meta_cursor_renderer_get_cursor (renderer);
|
||||
|
||||
if (cursor)
|
||||
return (meta_cursor_reference_get_gbm_bo (cursor, NULL, NULL) != NULL);
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer)
|
||||
{
|
||||
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
|
||||
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
|
||||
|
||||
priv->has_hw_cursor = should_have_hw_cursor (renderer);
|
||||
update_hw_cursor (native, FALSE);
|
||||
|
||||
/* Fall back to the stage-based cursor if we don't have HW cursors. */
|
||||
if (!priv->has_hw_cursor)
|
||||
META_CURSOR_RENDERER_CLASS (meta_cursor_renderer_native_parent_class)->update_cursor (renderer);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_renderer_native_class_init (MetaCursorRendererNativeClass *klass)
|
||||
{
|
||||
MetaCursorRendererClass *renderer_class = META_CURSOR_RENDERER_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = meta_cursor_renderer_native_finalize;
|
||||
renderer_class->update_cursor = meta_cursor_renderer_native_update_cursor;
|
||||
}
|
||||
|
||||
static void
|
||||
on_monitors_changed (MetaMonitorManager *monitors,
|
||||
MetaCursorRendererNative *native)
|
||||
{
|
||||
/* Our tracking is all messed up, so force an update. */
|
||||
update_hw_cursor (native, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_renderer_native_init (MetaCursorRendererNative *native)
|
||||
{
|
||||
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
|
||||
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
MetaMonitorManager *monitors;
|
||||
|
||||
monitors = meta_monitor_manager_get ();
|
||||
g_signal_connect_object (monitors, "monitors-changed",
|
||||
G_CALLBACK (on_monitors_changed), native, 0);
|
||||
|
||||
#if defined(CLUTTER_WINDOWING_EGL)
|
||||
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
|
||||
{
|
||||
CoglRenderer *cogl_renderer = cogl_display_get_renderer (cogl_context_get_display (ctx));
|
||||
priv->drm_fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
|
||||
priv->gbm = gbm_create_device (priv->drm_fd);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
struct gbm_device *
|
||||
meta_cursor_renderer_native_get_gbm_device (MetaCursorRendererNative *native)
|
||||
{
|
||||
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
|
||||
|
||||
return priv->gbm;
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_renderer_native_force_update (MetaCursorRendererNative *native)
|
||||
{
|
||||
update_hw_cursor (native, TRUE);
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#ifndef META_CURSOR_RENDERER_NATIVE_H
|
||||
#define META_CURSOR_RENDERER_NATIVE_H
|
||||
|
||||
#include "meta-cursor-renderer.h"
|
||||
|
||||
#define META_TYPE_CURSOR_RENDERER_NATIVE (meta_cursor_renderer_native_get_type ())
|
||||
#define META_CURSOR_RENDERER_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CURSOR_RENDERER_NATIVE, MetaCursorRendererNative))
|
||||
#define META_CURSOR_RENDERER_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_CURSOR_RENDERER_NATIVE, MetaCursorRendererNativeClass))
|
||||
#define META_IS_CURSOR_RENDERER_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_CURSOR_RENDERER_NATIVE))
|
||||
#define META_IS_CURSOR_RENDERER_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_CURSOR_RENDERER_NATIVE))
|
||||
#define META_CURSOR_RENDERER_NATIVE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_CURSOR_RENDERER_NATIVE, MetaCursorRendererNativeClass))
|
||||
|
||||
typedef struct _MetaCursorRendererNative MetaCursorRendererNative;
|
||||
typedef struct _MetaCursorRendererNativeClass MetaCursorRendererNativeClass;
|
||||
|
||||
struct _MetaCursorRendererNative
|
||||
{
|
||||
MetaCursorRenderer parent;
|
||||
};
|
||||
|
||||
struct _MetaCursorRendererNativeClass
|
||||
{
|
||||
MetaCursorRendererClass parent_class;
|
||||
};
|
||||
|
||||
GType meta_cursor_renderer_native_get_type (void) G_GNUC_CONST;
|
||||
|
||||
struct gbm_device * meta_cursor_renderer_native_get_gbm_device (MetaCursorRendererNative *renderer);
|
||||
void meta_cursor_renderer_native_force_update (MetaCursorRendererNative *renderer);
|
||||
|
||||
#endif /* META_CURSOR_RENDERER_NATIVE_H */
|
443
src/backends/native/meta-cursor-tracker-native.c
Normal file
443
src/backends/native/meta-cursor-tracker-native.c
Normal file
@ -0,0 +1,443 @@
|
||||
/*
|
||||
* Copyright 2014 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
#include <cogl/cogl-wayland-server.h>
|
||||
#include <clutter/clutter.h>
|
||||
#include <gbm.h>
|
||||
|
||||
#include "display-private.h"
|
||||
#include "meta-cursor-tracker-native.h"
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
#include "meta-monitor-manager.h"
|
||||
#include "meta-cursor-private.h"
|
||||
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
|
||||
struct _MetaCursorTrackerNative
|
||||
{
|
||||
MetaCursorTracker parent;
|
||||
|
||||
gboolean has_hw_cursor;
|
||||
|
||||
int current_x, current_y;
|
||||
MetaRectangle current_rect;
|
||||
MetaRectangle previous_rect;
|
||||
gboolean previous_is_valid;
|
||||
|
||||
CoglPipeline *pipeline;
|
||||
int drm_fd;
|
||||
struct gbm_device *gbm;
|
||||
};
|
||||
|
||||
struct _MetaCursorTrackerNativeClass
|
||||
{
|
||||
MetaCursorTrackerClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaCursorTrackerNative, meta_cursor_tracker_native, META_TYPE_CURSOR_TRACKER);
|
||||
|
||||
static void
|
||||
meta_cursor_tracker_native_load_cursor_pixels (MetaCursorTracker *tracker,
|
||||
MetaCursorReference *cursor,
|
||||
uint8_t *pixels,
|
||||
int width,
|
||||
int height,
|
||||
int rowstride,
|
||||
uint32_t format)
|
||||
{
|
||||
MetaCursorTrackerNative *self = META_CURSOR_TRACKER_NATIVE (tracker);
|
||||
|
||||
if (!self->gbm)
|
||||
return;
|
||||
|
||||
meta_cursor_reference_load_gbm_buffer (cursor,
|
||||
self->gbm,
|
||||
pixels,
|
||||
width, height, rowstride,
|
||||
format);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_tracker_native_load_cursor_buffer (MetaCursorTracker *tracker,
|
||||
MetaCursorReference *cursor,
|
||||
struct wl_resource *buffer)
|
||||
{
|
||||
struct wl_shm_buffer *shm_buffer;
|
||||
int width, height;
|
||||
|
||||
width = cogl_texture_get_width (COGL_TEXTURE (cursor->image.texture));
|
||||
height = cogl_texture_get_height (COGL_TEXTURE (cursor->image.texture));
|
||||
|
||||
shm_buffer = wl_shm_buffer_get (buffer);
|
||||
if (shm_buffer)
|
||||
{
|
||||
uint32_t gbm_format;
|
||||
uint8_t *pixels = wl_shm_buffer_get_data (shm_buffer);
|
||||
int rowstride = wl_shm_buffer_get_stride (shm_buffer);
|
||||
|
||||
switch (wl_shm_buffer_get_format (shm_buffer))
|
||||
{
|
||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
case WL_SHM_FORMAT_ARGB8888:
|
||||
gbm_format = GBM_FORMAT_ARGB8888;
|
||||
break;
|
||||
case WL_SHM_FORMAT_XRGB8888:
|
||||
gbm_format = GBM_FORMAT_XRGB8888;
|
||||
break;
|
||||
#else
|
||||
case WL_SHM_FORMAT_ARGB8888:
|
||||
gbm_format = GBM_FORMAT_ARGB8888;
|
||||
break;
|
||||
case WL_SHM_FORMAT_XRGB8888:
|
||||
gbm_format = GBM_FORMAT_XRGB8888;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
g_warn_if_reached ();
|
||||
gbm_format = GBM_FORMAT_ARGB8888;
|
||||
}
|
||||
|
||||
meta_cursor_tracker_native_load_cursor_pixels (tracker,
|
||||
cursor,
|
||||
pixels,
|
||||
width,
|
||||
height,
|
||||
rowstride,
|
||||
gbm_format);
|
||||
}
|
||||
else
|
||||
{
|
||||
MetaCursorTrackerNative *self = META_CURSOR_TRACKER_NATIVE (tracker);
|
||||
if (!self->gbm)
|
||||
return;
|
||||
meta_cursor_reference_import_gbm_buffer (cursor, self->gbm, buffer, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_crtc_has_hw_cursor (MetaCursorTrackerNative *self,
|
||||
MetaCRTC *crtc,
|
||||
gboolean has)
|
||||
{
|
||||
MetaCursorTracker *tracker = META_CURSOR_TRACKER (self);
|
||||
|
||||
if (has)
|
||||
{
|
||||
MetaCursorReference *displayed_cursor = tracker->displayed_cursor;
|
||||
struct gbm_bo *bo;
|
||||
union gbm_bo_handle handle;
|
||||
int width, height;
|
||||
int hot_x, hot_y;
|
||||
|
||||
bo = meta_cursor_reference_get_gbm_bo (displayed_cursor, &hot_x, &hot_y);
|
||||
|
||||
handle = gbm_bo_get_handle (bo);
|
||||
width = gbm_bo_get_width (bo);
|
||||
height = gbm_bo_get_height (bo);
|
||||
|
||||
drmModeSetCursor2 (self->drm_fd, crtc->crtc_id, handle.u32,
|
||||
width, height, hot_x, hot_y);
|
||||
crtc->has_hw_cursor = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
drmModeSetCursor2 (self->drm_fd, crtc->crtc_id, 0, 0, 0, 0, 0);
|
||||
crtc->has_hw_cursor = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_monitors_changed (MetaMonitorManager *monitors,
|
||||
MetaCursorTrackerNative *self)
|
||||
{
|
||||
MetaCRTC *crtcs;
|
||||
unsigned int i, n_crtcs;
|
||||
|
||||
if (!self->has_hw_cursor)
|
||||
return;
|
||||
|
||||
/* Go through the new list of monitors, find out where the cursor is */
|
||||
meta_monitor_manager_get_resources (monitors, NULL, NULL, &crtcs, &n_crtcs, NULL, NULL);
|
||||
|
||||
for (i = 0; i < n_crtcs; i++)
|
||||
{
|
||||
MetaRectangle *rect = &crtcs[i].rect;
|
||||
gboolean has;
|
||||
|
||||
has = meta_rectangle_overlap (&self->current_rect, rect);
|
||||
|
||||
/* Need to do it unconditionally here, our tracking is
|
||||
wrong because we reloaded the CRTCs */
|
||||
set_crtc_has_hw_cursor (self, &crtcs[i], has);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
should_have_hw_cursor (MetaCursorTrackerNative *self)
|
||||
{
|
||||
MetaCursorTracker *tracker = META_CURSOR_TRACKER (self);
|
||||
|
||||
if (tracker->displayed_cursor)
|
||||
return (meta_cursor_reference_get_gbm_bo (tracker->displayed_cursor, NULL, NULL) != NULL);
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
update_hw_cursor (MetaCursorTrackerNative *self)
|
||||
{
|
||||
MetaMonitorManager *monitors;
|
||||
MetaCRTC *crtcs;
|
||||
unsigned int i, n_crtcs;
|
||||
gboolean enabled;
|
||||
|
||||
enabled = should_have_hw_cursor (self);
|
||||
self->has_hw_cursor = enabled;
|
||||
|
||||
monitors = meta_monitor_manager_get ();
|
||||
meta_monitor_manager_get_resources (monitors, NULL, NULL, &crtcs, &n_crtcs, NULL, NULL);
|
||||
|
||||
for (i = 0; i < n_crtcs; i++)
|
||||
{
|
||||
MetaRectangle *rect = &crtcs[i].rect;
|
||||
gboolean has;
|
||||
|
||||
has = enabled && meta_rectangle_overlap (&self->current_rect, rect);
|
||||
|
||||
if (has || crtcs[i].has_hw_cursor)
|
||||
set_crtc_has_hw_cursor (self, &crtcs[i], has);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
move_hw_cursor (MetaCursorTrackerNative *self)
|
||||
{
|
||||
MetaMonitorManager *monitors;
|
||||
MetaCRTC *crtcs;
|
||||
unsigned int i, n_crtcs;
|
||||
|
||||
monitors = meta_monitor_manager_get ();
|
||||
meta_monitor_manager_get_resources (monitors, NULL, NULL, &crtcs, &n_crtcs, NULL, NULL);
|
||||
|
||||
g_assert (self->has_hw_cursor);
|
||||
|
||||
for (i = 0; i < n_crtcs; i++)
|
||||
{
|
||||
MetaRectangle *rect = &crtcs[i].rect;
|
||||
gboolean has;
|
||||
|
||||
has = meta_rectangle_overlap (&self->current_rect, rect);
|
||||
|
||||
if (has != crtcs[i].has_hw_cursor)
|
||||
set_crtc_has_hw_cursor (self, &crtcs[i], has);
|
||||
if (has)
|
||||
drmModeMoveCursor (self->drm_fd, crtcs[i].crtc_id,
|
||||
self->current_rect.x - rect->x,
|
||||
self->current_rect.y - rect->y);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
queue_redraw (MetaCursorTrackerNative *self)
|
||||
{
|
||||
MetaCursorTracker *tracker = META_CURSOR_TRACKER (self);
|
||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||
ClutterActor *stage = compositor->stage;
|
||||
cairo_rectangle_int_t clip;
|
||||
|
||||
/* Clear the location the cursor was at before, if we need to. */
|
||||
if (self->previous_is_valid)
|
||||
{
|
||||
clip.x = self->previous_rect.x;
|
||||
clip.y = self->previous_rect.y;
|
||||
clip.width = self->previous_rect.width;
|
||||
clip.height = self->previous_rect.height;
|
||||
clutter_actor_queue_redraw_with_clip (stage, &clip);
|
||||
self->previous_is_valid = FALSE;
|
||||
}
|
||||
|
||||
if (self->has_hw_cursor || !tracker->displayed_cursor)
|
||||
return;
|
||||
|
||||
clip.x = self->current_rect.x;
|
||||
clip.y = self->current_rect.y;
|
||||
clip.width = self->current_rect.width;
|
||||
clip.height = self->current_rect.height;
|
||||
clutter_actor_queue_redraw_with_clip (stage, &clip);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_tracker_native_sync_cursor (MetaCursorTracker *tracker)
|
||||
{
|
||||
MetaCursorTrackerNative *self = META_CURSOR_TRACKER_NATIVE (tracker);
|
||||
MetaCursorReference *displayed_cursor;
|
||||
|
||||
displayed_cursor = tracker->displayed_cursor;
|
||||
|
||||
if (displayed_cursor)
|
||||
{
|
||||
CoglTexture *texture;
|
||||
int hot_x, hot_y;
|
||||
|
||||
texture = meta_cursor_reference_get_cogl_texture (displayed_cursor, &hot_x, &hot_y);
|
||||
cogl_pipeline_set_layer_texture (self->pipeline, 0, texture);
|
||||
|
||||
self->current_rect.x = self->current_x - hot_x;
|
||||
self->current_rect.y = self->current_y - hot_y;
|
||||
self->current_rect.width = cogl_texture_get_width (COGL_TEXTURE (texture));
|
||||
self->current_rect.height = cogl_texture_get_height (COGL_TEXTURE (texture));
|
||||
}
|
||||
else
|
||||
{
|
||||
cogl_pipeline_set_layer_texture (self->pipeline, 0, NULL);
|
||||
|
||||
self->current_rect.x = 0;
|
||||
self->current_rect.y = 0;
|
||||
self->current_rect.width = 0;
|
||||
self->current_rect.height = 0;
|
||||
}
|
||||
|
||||
update_hw_cursor (self);
|
||||
|
||||
if (self->has_hw_cursor)
|
||||
move_hw_cursor (self);
|
||||
else
|
||||
queue_redraw (self);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_tracker_native_get_pointer (MetaCursorTracker *tracker,
|
||||
int *x,
|
||||
int *y,
|
||||
ClutterModifierType *mods)
|
||||
{
|
||||
ClutterDeviceManager *cmanager;
|
||||
ClutterInputDevice *cdevice;
|
||||
ClutterPoint point;
|
||||
|
||||
/* On wayland we can't use GDK, because that only sees the events we
|
||||
* forward to xwayland.
|
||||
*/
|
||||
cmanager = clutter_device_manager_get_default ();
|
||||
cdevice = clutter_device_manager_get_core_device (cmanager, CLUTTER_POINTER_DEVICE);
|
||||
|
||||
clutter_input_device_get_coords (cdevice, NULL, &point);
|
||||
if (x)
|
||||
*x = point.x;
|
||||
if (y)
|
||||
*y = point.y;
|
||||
if (mods)
|
||||
*mods = clutter_input_device_get_modifier_state (cdevice);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_tracker_native_finalize (GObject *object)
|
||||
{
|
||||
MetaCursorTrackerNative *self = META_CURSOR_TRACKER_NATIVE (object);
|
||||
|
||||
if (self->pipeline)
|
||||
cogl_object_unref (self->pipeline);
|
||||
if (self->gbm)
|
||||
gbm_device_destroy (self->gbm);
|
||||
|
||||
G_OBJECT_CLASS (meta_cursor_tracker_native_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_tracker_native_class_init (MetaCursorTrackerNativeClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
MetaCursorTrackerClass *cursor_tracker_class = META_CURSOR_TRACKER_CLASS (klass);
|
||||
|
||||
object_class->finalize = meta_cursor_tracker_native_finalize;
|
||||
|
||||
cursor_tracker_class->get_pointer = meta_cursor_tracker_native_get_pointer;
|
||||
cursor_tracker_class->sync_cursor = meta_cursor_tracker_native_sync_cursor;
|
||||
cursor_tracker_class->load_cursor_pixels = meta_cursor_tracker_native_load_cursor_pixels;
|
||||
cursor_tracker_class->load_cursor_buffer = meta_cursor_tracker_native_load_cursor_buffer;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_tracker_native_init (MetaCursorTrackerNative *self)
|
||||
{
|
||||
MetaWaylandCompositor *compositor;
|
||||
CoglContext *ctx;
|
||||
MetaMonitorManager *monitors;
|
||||
|
||||
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
self->pipeline = cogl_pipeline_new (ctx);
|
||||
|
||||
compositor = meta_wayland_compositor_get_default ();
|
||||
compositor->seat->cursor_tracker = META_CURSOR_TRACKER (self);
|
||||
meta_cursor_tracker_native_update_position (self,
|
||||
wl_fixed_to_int (compositor->seat->pointer.x),
|
||||
wl_fixed_to_int (compositor->seat->pointer.y));
|
||||
|
||||
#if defined(CLUTTER_WINDOWING_EGL)
|
||||
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
|
||||
{
|
||||
CoglRenderer *cogl_renderer = cogl_display_get_renderer (cogl_context_get_display (ctx));
|
||||
self->drm_fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
|
||||
self->gbm = gbm_create_device (self->drm_fd);
|
||||
}
|
||||
#endif
|
||||
|
||||
monitors = meta_monitor_manager_get ();
|
||||
g_signal_connect_object (monitors, "monitors-changed",
|
||||
G_CALLBACK (on_monitors_changed), self, 0);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_native_update_position (MetaCursorTrackerNative *self,
|
||||
int new_x,
|
||||
int new_y)
|
||||
{
|
||||
self->current_x = new_x;
|
||||
self->current_y = new_y;
|
||||
|
||||
_meta_cursor_tracker_sync_cursor (META_CURSOR_TRACKER (self));
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_native_paint (MetaCursorTrackerNative *self)
|
||||
{
|
||||
MetaCursorTracker *tracker = META_CURSOR_TRACKER (self);
|
||||
|
||||
if (self->has_hw_cursor || !tracker->displayed_cursor)
|
||||
return;
|
||||
|
||||
cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (),
|
||||
self->pipeline,
|
||||
self->current_rect.x,
|
||||
self->current_rect.y,
|
||||
self->current_rect.x +
|
||||
self->current_rect.width,
|
||||
self->current_rect.y +
|
||||
self->current_rect.height);
|
||||
|
||||
self->previous_rect = self->current_rect;
|
||||
self->previous_is_valid = TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_native_force_update (MetaCursorTrackerNative *self)
|
||||
{
|
||||
_meta_cursor_tracker_sync_cursor (META_CURSOR_TRACKER (self));
|
||||
}
|
43
src/backends/native/meta-cursor-tracker-native.h
Normal file
43
src/backends/native/meta-cursor-tracker-native.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2014 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef META_CURSOR_TRACKER_NATIVE_H
|
||||
#define META_CURSOR_TRACKER_NATIVE_H
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <meta/meta-cursor-tracker.h>
|
||||
|
||||
#define META_TYPE_CURSOR_TRACKER_NATIVE (meta_cursor_tracker_native_get_type ())
|
||||
#define META_CURSOR_TRACKER_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CURSOR_TRACKER_NATIVE, MetaCursorTrackerNative))
|
||||
#define META_CURSOR_TRACKER_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_CURSOR_TRACKER_NATIVE, MetaCursorTrackerNativeClass))
|
||||
#define META_IS_CURSOR_TRACKER_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_CURSOR_TRACKER_NATIVE))
|
||||
#define META_IS_CURSOR_TRACKER_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_CURSOR_TRACKER_NATIVE))
|
||||
#define META_CURSOR_TRACKER_NATIVE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_CURSOR_TRACKER_NATIVE, MetaCursorTrackerNativeClass))
|
||||
|
||||
typedef struct _MetaCursorTrackerNative MetaCursorTrackerNative;
|
||||
typedef struct _MetaCursorTrackerNativeClass MetaCursorTrackerNativeClass;
|
||||
|
||||
GType meta_cursor_tracker_native_get_type (void);
|
||||
|
||||
void meta_cursor_tracker_native_update_position (MetaCursorTrackerNative *tracker,
|
||||
int new_x,
|
||||
int new_y);
|
||||
void meta_cursor_tracker_native_paint (MetaCursorTrackerNative *tracker);
|
||||
|
||||
void meta_cursor_tracker_native_force_update (MetaCursorTrackerNative *tracker);
|
||||
|
||||
#endif /* META_CURSOR_TRACKER_NATIVE_H */
|
@ -17,27 +17,35 @@
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "meta-launcher.h"
|
||||
#include "weston-launch.h"
|
||||
#include <config.h>
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <gio/gunixfdmessage.h>
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <clutter/egl/clutter-egl.h>
|
||||
#include <clutter/evdev/clutter-evdev.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <sys/time.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <drm.h>
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
#include "backends/meta-backend.h"
|
||||
#include "meta-cursor-renderer-native.h"
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
#include "meta-cursor-tracker-native.h"
|
||||
#include "meta-weston-launch.h"
|
||||
|
||||
struct _MetaLauncher
|
||||
{
|
||||
@ -64,11 +72,11 @@ request_vt_switch_idle (gpointer user_data)
|
||||
|
||||
static gboolean
|
||||
send_message_to_wl (MetaLauncher *self,
|
||||
void *message,
|
||||
gsize size,
|
||||
GSocketControlMessage *out_cmsg,
|
||||
GSocketControlMessage **in_cmsg,
|
||||
GError **error)
|
||||
void *message,
|
||||
gsize size,
|
||||
GSocketControlMessage *out_cmsg,
|
||||
GSocketControlMessage **in_cmsg,
|
||||
GError **error)
|
||||
{
|
||||
struct weston_launcher_reply reply;
|
||||
GInputVector in_iov = { &reply, sizeof (reply) };
|
||||
@ -81,21 +89,19 @@ send_message_to_wl (MetaLauncher *self,
|
||||
out_all_cmsg[0] = out_cmsg;
|
||||
out_all_cmsg[1] = NULL;
|
||||
if (g_socket_send_message (self->weston_launch, NULL,
|
||||
&out_iov, 1,
|
||||
out_all_cmsg, -1,
|
||||
flags, NULL, error) != (gssize)size)
|
||||
&out_iov, 1,
|
||||
out_all_cmsg, -1,
|
||||
flags, NULL, error) != (gssize)size)
|
||||
return FALSE;
|
||||
|
||||
if (g_socket_receive_message (self->weston_launch, NULL,
|
||||
&in_iov, 1,
|
||||
&in_all_cmsg, NULL,
|
||||
&flags, NULL, error) != sizeof (reply))
|
||||
&in_iov, 1,
|
||||
&in_all_cmsg, NULL,
|
||||
&flags, NULL, error) != sizeof (reply))
|
||||
return FALSE;
|
||||
|
||||
while (reply.header.opcode != ((struct weston_launcher_message*)message)->opcode)
|
||||
{
|
||||
guint id;
|
||||
|
||||
/* There were events queued */
|
||||
g_assert ((reply.header.opcode & WESTON_LAUNCHER_EVENT) == WESTON_LAUNCHER_EVENT);
|
||||
|
||||
@ -109,34 +115,33 @@ send_message_to_wl (MetaLauncher *self,
|
||||
g_assert (reply.header.opcode != WESTON_LAUNCHER_SERVER_VT_ENTER);
|
||||
|
||||
switch (reply.header.opcode)
|
||||
{
|
||||
case WESTON_LAUNCHER_SERVER_REQUEST_VT_SWITCH:
|
||||
id = g_idle_add (request_vt_switch_idle, self);
|
||||
g_source_set_name_by_id (id, "[mutter] request_vt_switch_idle");
|
||||
break;
|
||||
{
|
||||
case WESTON_LAUNCHER_SERVER_REQUEST_VT_SWITCH:
|
||||
g_idle_add (request_vt_switch_idle, self);
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
if (g_socket_receive_message (self->weston_launch, NULL,
|
||||
&in_iov, 1,
|
||||
NULL, NULL,
|
||||
&flags, NULL, error) != sizeof (reply))
|
||||
return FALSE;
|
||||
&in_iov, 1,
|
||||
NULL, NULL,
|
||||
&flags, NULL, error) != sizeof (reply))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (reply.ret != 0)
|
||||
{
|
||||
if (reply.ret == -1)
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Got failure from weston-launch");
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Got failure from weston-launch");
|
||||
else
|
||||
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-reply.ret),
|
||||
"Got failure from weston-launch: %s", strerror (-reply.ret));
|
||||
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-reply.ret),
|
||||
"Got failure from weston-launch: %s", strerror (-reply.ret));
|
||||
|
||||
for (i = 0; in_all_cmsg && in_all_cmsg[i]; i++)
|
||||
g_object_unref (in_all_cmsg[i]);
|
||||
g_object_unref (in_all_cmsg[i]);
|
||||
g_free (in_all_cmsg);
|
||||
|
||||
return FALSE;
|
||||
@ -145,7 +150,7 @@ send_message_to_wl (MetaLauncher *self,
|
||||
if (in_all_cmsg && in_all_cmsg[0])
|
||||
{
|
||||
for (i = 1; in_all_cmsg[i]; i++)
|
||||
g_object_unref (in_all_cmsg[i]);
|
||||
g_object_unref (in_all_cmsg[i]);
|
||||
*in_cmsg = in_all_cmsg[0];
|
||||
}
|
||||
|
||||
@ -194,7 +199,7 @@ meta_launcher_open_device (MetaLauncher *self,
|
||||
}
|
||||
|
||||
static void
|
||||
session_unpause (void)
|
||||
meta_launcher_enter (MetaLauncher *launcher)
|
||||
{
|
||||
ClutterBackend *backend;
|
||||
CoglContext *cogl_context;
|
||||
@ -209,29 +214,27 @@ session_unpause (void)
|
||||
|
||||
{
|
||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (backend);
|
||||
|
||||
/* When we mode-switch back, we need to immediately queue a redraw
|
||||
* in case nothing else queued one for us, and force the cursor to
|
||||
* update. */
|
||||
|
||||
clutter_actor_queue_redraw (compositor->stage);
|
||||
meta_cursor_renderer_native_force_update (META_CURSOR_RENDERER_NATIVE (renderer));
|
||||
meta_cursor_tracker_native_force_update (META_CURSOR_TRACKER_NATIVE (compositor->seat->cursor_tracker));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
session_pause (void)
|
||||
meta_launcher_leave (MetaLauncher *launcher)
|
||||
{
|
||||
clutter_evdev_release_devices ();
|
||||
}
|
||||
|
||||
static int
|
||||
on_evdev_device_open (const char *path,
|
||||
int flags,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
int flags,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
MetaLauncher *launcher = user_data;
|
||||
|
||||
@ -239,8 +242,8 @@ on_evdev_device_open (const char *path,
|
||||
}
|
||||
|
||||
static void
|
||||
on_evdev_device_close (int fd,
|
||||
gpointer user_data)
|
||||
on_evdev_device_close (int fd,
|
||||
gpointer user_data)
|
||||
{
|
||||
close (fd);
|
||||
}
|
||||
@ -251,8 +254,6 @@ handle_vt_enter (MetaLauncher *launcher)
|
||||
g_assert (launcher->vt_switched);
|
||||
|
||||
g_main_loop_quit (launcher->nested_loop);
|
||||
|
||||
session_unpause ();
|
||||
}
|
||||
|
||||
static void
|
||||
@ -262,7 +263,7 @@ handle_request_vt_switch (MetaLauncher *launcher)
|
||||
GError *error;
|
||||
gboolean ok;
|
||||
|
||||
session_pause ();
|
||||
meta_launcher_leave (launcher);
|
||||
|
||||
message.opcode = WESTON_LAUNCHER_CONFIRM_VT_SWITCH;
|
||||
|
||||
@ -286,13 +287,13 @@ handle_request_vt_switch (MetaLauncher *launcher)
|
||||
g_assert (launcher->vt_switched);
|
||||
launcher->vt_switched = FALSE;
|
||||
|
||||
session_unpause ();
|
||||
meta_launcher_enter (launcher);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_socket_readable (GSocket *socket,
|
||||
GIOCondition condition,
|
||||
gpointer user_data)
|
||||
GIOCondition condition,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaLauncher *launcher = user_data;
|
||||
struct weston_launcher_event event;
|
||||
@ -342,9 +343,7 @@ MetaLauncher *
|
||||
meta_launcher_new (void)
|
||||
{
|
||||
MetaLauncher *self = g_slice_new0 (MetaLauncher);
|
||||
GError *error = NULL;
|
||||
int launch_fd;
|
||||
int kms_fd;
|
||||
|
||||
launch_fd = env_get_fd ("WESTON_LAUNCHER_SOCK");
|
||||
if (launch_fd < 0)
|
||||
@ -365,15 +364,22 @@ meta_launcher_new (void)
|
||||
g_source_attach (self->inner_source, self->nested_context);
|
||||
g_source_unref (self->inner_source);
|
||||
|
||||
kms_fd = meta_launcher_open_device (self, "/dev/dri/card0", O_RDWR, &error);
|
||||
if (error)
|
||||
g_error ("Failed to open /dev/dri/card0: %s", error->message);
|
||||
|
||||
clutter_egl_set_kms_fd (kms_fd);
|
||||
clutter_evdev_set_device_callbacks (on_evdev_device_open,
|
||||
on_evdev_device_close,
|
||||
self);
|
||||
|
||||
#if defined(CLUTTER_WINDOWING_EGL)
|
||||
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
|
||||
{
|
||||
GError *error = NULL;
|
||||
int fd = meta_launcher_open_device (self, "/dev/dri/card0", O_RDWR, &error);
|
||||
if (error)
|
||||
g_error ("Failed to open /dev/dri/card0: %s", error->message);
|
||||
|
||||
clutter_egl_set_kms_fd (fd);
|
||||
}
|
||||
#endif
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@ -391,17 +397,10 @@ meta_launcher_free (MetaLauncher *launcher)
|
||||
g_slice_free (MetaLauncher, launcher);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_launcher_activate_session (MetaLauncher *launcher,
|
||||
GError **error)
|
||||
{
|
||||
return meta_launcher_activate_vt (launcher, -1, error);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_launcher_activate_vt (MetaLauncher *launcher,
|
||||
signed char vt,
|
||||
GError **error)
|
||||
signed char vt,
|
||||
GError **error)
|
||||
{
|
||||
struct weston_launcher_activate_vt message;
|
||||
|
||||
@ -410,3 +409,4 @@ meta_launcher_activate_vt (MetaLauncher *launcher,
|
||||
|
||||
return send_message_to_wl (launcher, &message, sizeof (message), NULL, NULL, error);
|
||||
}
|
||||
|
@ -17,21 +17,18 @@
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef META_LAUNCHER_H
|
||||
#define META_LAUNCHER_H
|
||||
#ifndef META_WESTON_LAUNCH_H
|
||||
#define META_WESTON_LAUNCH_H
|
||||
|
||||
#include <glib-object.h>
|
||||
#include "weston-launch.h"
|
||||
|
||||
typedef struct _MetaLauncher MetaLauncher;
|
||||
|
||||
MetaLauncher *meta_launcher_new (void);
|
||||
void meta_launcher_free (MetaLauncher *self);
|
||||
|
||||
gboolean meta_launcher_activate_session (MetaLauncher *self,
|
||||
GError **error);
|
||||
|
||||
gboolean meta_launcher_activate_vt (MetaLauncher *self,
|
||||
signed char vt,
|
||||
GError **error);
|
||||
|
||||
#endif /* META_LAUNCHER_H */
|
||||
#endif
|
@ -1,385 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "meta-backend-x11.h"
|
||||
|
||||
#include <clutter/x11/clutter-x11.h>
|
||||
|
||||
#include <X11/extensions/sync.h>
|
||||
|
||||
#include "meta-idle-monitor-xsync.h"
|
||||
#include "meta-monitor-manager-xrandr.h"
|
||||
#include "backends/meta-monitor-manager-dummy.h"
|
||||
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
#include "meta-cursor.h"
|
||||
#include <meta/util.h>
|
||||
#include "display-private.h"
|
||||
#include "compositor/compositor-private.h"
|
||||
|
||||
struct _MetaBackendX11Private
|
||||
{
|
||||
/* The host X11 display */
|
||||
Display *xdisplay;
|
||||
GSource *source;
|
||||
|
||||
int xsync_event_base;
|
||||
int xsync_error_base;
|
||||
|
||||
int xinput_opcode;
|
||||
int xinput_event_base;
|
||||
int xinput_error_base;
|
||||
};
|
||||
typedef struct _MetaBackendX11Private MetaBackendX11Private;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaBackendX11, meta_backend_x11, META_TYPE_BACKEND);
|
||||
|
||||
static void
|
||||
handle_alarm_notify (MetaBackend *backend,
|
||||
XEvent *event)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= backend->device_id_max; i++)
|
||||
if (backend->device_monitors[i])
|
||||
meta_idle_monitor_xsync_handle_xevent (backend->device_monitors[i], (XSyncAlarmNotifyEvent*) event);
|
||||
}
|
||||
|
||||
static Window
|
||||
get_stage_window (MetaBackendX11 *x11)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
MetaCompositor *compositor = display->compositor;
|
||||
ClutterStage *stage = CLUTTER_STAGE (compositor->stage);
|
||||
|
||||
return clutter_x11_get_stage_window (stage);
|
||||
}
|
||||
|
||||
static void
|
||||
translate_device_event (MetaBackendX11 *x11,
|
||||
XIDeviceEvent *device_event)
|
||||
{
|
||||
Window stage_window = get_stage_window (x11);
|
||||
|
||||
if (device_event->event != stage_window)
|
||||
{
|
||||
/* This codepath should only ever trigger as an X11 compositor,
|
||||
* and never under nested, as under nested all backend events
|
||||
* should be reported with respect to the stage window. */
|
||||
g_assert (!meta_is_wayland_compositor ());
|
||||
|
||||
device_event->event = stage_window;
|
||||
|
||||
/* As an X11 compositor, the stage window is always at 0,0, so
|
||||
* using root coordinates will give us correct stage coordinates
|
||||
* as well... */
|
||||
device_event->event_x = device_event->root_x;
|
||||
device_event->event_y = device_event->root_y;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clutter makes the assumption that there is only one X window
|
||||
* per stage, which is a valid assumption to make for a generic
|
||||
* application toolkit. As such, it will ignore any events sent
|
||||
* to the a stage that isn't its X window.
|
||||
*
|
||||
* When running as an X window manager, we need to respond to
|
||||
* events from lots of windows. Trick Clutter into translating
|
||||
* these events by pretending we got an event on the stage window.
|
||||
*/
|
||||
static void
|
||||
maybe_spoof_event_as_stage_event (MetaBackendX11 *x11,
|
||||
XEvent *event)
|
||||
{
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
|
||||
if (event->type == GenericEvent &&
|
||||
event->xcookie.extension == priv->xinput_opcode)
|
||||
{
|
||||
XIEvent *input_event = (XIEvent *) event->xcookie.data;
|
||||
|
||||
switch (input_event->evtype)
|
||||
{
|
||||
case XI_Motion:
|
||||
case XI_ButtonPress:
|
||||
case XI_ButtonRelease:
|
||||
case XI_KeyPress:
|
||||
case XI_KeyRelease:
|
||||
translate_device_event (x11, (XIDeviceEvent *) input_event);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
handle_host_xevent (MetaBackend *backend,
|
||||
XEvent *event)
|
||||
{
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
gboolean bypass_clutter = FALSE;
|
||||
|
||||
XGetEventData (priv->xdisplay, &event->xcookie);
|
||||
|
||||
if (event->type == (priv->xsync_event_base + XSyncAlarmNotify))
|
||||
handle_alarm_notify (backend, event);
|
||||
|
||||
{
|
||||
MetaMonitorManager *manager = meta_backend_get_monitor_manager (backend);
|
||||
if (META_IS_MONITOR_MANAGER_XRANDR (manager) &&
|
||||
meta_monitor_manager_xrandr_handle_xevent (META_MONITOR_MANAGER_XRANDR (manager), event))
|
||||
{
|
||||
bypass_clutter = TRUE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
maybe_spoof_event_as_stage_event (x11, event);
|
||||
|
||||
out:
|
||||
if (!bypass_clutter)
|
||||
clutter_x11_handle_event (event);
|
||||
|
||||
XFreeEventData (priv->xdisplay, &event->xcookie);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
GSource base;
|
||||
GPollFD event_poll_fd;
|
||||
MetaBackend *backend;
|
||||
} XEventSource;
|
||||
|
||||
static gboolean
|
||||
x_event_source_prepare (GSource *source,
|
||||
int *timeout)
|
||||
{
|
||||
XEventSource *x_source = (XEventSource *) source;
|
||||
MetaBackend *backend = x_source->backend;
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
|
||||
*timeout = -1;
|
||||
|
||||
return XPending (priv->xdisplay);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
x_event_source_check (GSource *source)
|
||||
{
|
||||
XEventSource *x_source = (XEventSource *) source;
|
||||
MetaBackend *backend = x_source->backend;
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
|
||||
return XPending (priv->xdisplay);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
x_event_source_dispatch (GSource *source,
|
||||
GSourceFunc callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
XEventSource *x_source = (XEventSource *) source;
|
||||
MetaBackend *backend = x_source->backend;
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
|
||||
while (XPending (priv->xdisplay))
|
||||
{
|
||||
XEvent event;
|
||||
|
||||
XNextEvent (priv->xdisplay, &event);
|
||||
|
||||
handle_host_xevent (backend, &event);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GSourceFuncs x_event_funcs = {
|
||||
x_event_source_prepare,
|
||||
x_event_source_check,
|
||||
x_event_source_dispatch,
|
||||
};
|
||||
|
||||
static GSource *
|
||||
x_event_source_new (MetaBackend *backend)
|
||||
{
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
GSource *source;
|
||||
XEventSource *x_source;
|
||||
|
||||
source = g_source_new (&x_event_funcs, sizeof (XEventSource));
|
||||
x_source = (XEventSource *) source;
|
||||
x_source->backend = backend;
|
||||
x_source->event_poll_fd.fd = ConnectionNumber (priv->xdisplay);
|
||||
x_source->event_poll_fd.events = G_IO_IN;
|
||||
g_source_add_poll (source, &x_source->event_poll_fd);
|
||||
|
||||
g_source_attach (source, NULL);
|
||||
return source;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_x11_post_init (MetaBackend *backend)
|
||||
{
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
int major, minor;
|
||||
|
||||
priv->xdisplay = clutter_x11_get_default_display ();
|
||||
|
||||
priv->source = x_event_source_new (backend);
|
||||
|
||||
if (!XSyncQueryExtension (priv->xdisplay, &priv->xsync_event_base, &priv->xsync_error_base) ||
|
||||
!XSyncInitialize (priv->xdisplay, &major, &minor))
|
||||
meta_fatal ("Could not initialize XSync");
|
||||
|
||||
{
|
||||
int major = 2, minor = 3;
|
||||
gboolean has_xi = FALSE;
|
||||
|
||||
if (XQueryExtension (priv->xdisplay,
|
||||
"XInputExtension",
|
||||
&priv->xinput_opcode,
|
||||
&priv->xinput_error_base,
|
||||
&priv->xinput_event_base))
|
||||
{
|
||||
if (XIQueryVersion (priv->xdisplay, &major, &minor) == Success)
|
||||
{
|
||||
int version = (major * 10) + minor;
|
||||
if (version >= 22)
|
||||
has_xi = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_xi)
|
||||
meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer\n");
|
||||
}
|
||||
|
||||
META_BACKEND_CLASS (meta_backend_x11_parent_class)->post_init (backend);
|
||||
}
|
||||
|
||||
static MetaIdleMonitor *
|
||||
meta_backend_x11_create_idle_monitor (MetaBackend *backend,
|
||||
int device_id)
|
||||
{
|
||||
return g_object_new (META_TYPE_IDLE_MONITOR_XSYNC,
|
||||
"device-id", device_id,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static MetaMonitorManager *
|
||||
meta_backend_x11_create_monitor_manager (MetaBackend *backend)
|
||||
{
|
||||
/* If we're a Wayland compositor using the X11 backend,
|
||||
* we're a nested configuration, so return the dummy
|
||||
* monitor setup. */
|
||||
if (meta_is_wayland_compositor ())
|
||||
return g_object_new (META_TYPE_MONITOR_MANAGER_DUMMY, NULL);
|
||||
|
||||
return g_object_new (META_TYPE_MONITOR_MANAGER_XRANDR, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_backend_x11_grab_device (MetaBackend *backend,
|
||||
int device_id,
|
||||
uint32_t timestamp)
|
||||
{
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||
int ret;
|
||||
|
||||
XISetMask (mask.mask, XI_ButtonPress);
|
||||
XISetMask (mask.mask, XI_ButtonRelease);
|
||||
XISetMask (mask.mask, XI_Enter);
|
||||
XISetMask (mask.mask, XI_Leave);
|
||||
XISetMask (mask.mask, XI_Motion);
|
||||
XISetMask (mask.mask, XI_KeyPress);
|
||||
XISetMask (mask.mask, XI_KeyRelease);
|
||||
|
||||
MetaCursorTracker *tracker = meta_cursor_tracker_get_for_screen (NULL);
|
||||
MetaCursorReference *cursor_ref = meta_cursor_tracker_get_displayed_cursor (tracker);
|
||||
MetaCursor cursor = meta_cursor_reference_get_meta_cursor (cursor_ref);
|
||||
|
||||
ret = XIGrabDevice (priv->xdisplay, device_id,
|
||||
get_stage_window (x11),
|
||||
timestamp,
|
||||
meta_cursor_create_x_cursor (priv->xdisplay, cursor),
|
||||
XIGrabModeAsync, XIGrabModeAsync,
|
||||
False, /* owner_events */
|
||||
&mask);
|
||||
|
||||
return (ret == Success);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_backend_x11_ungrab_device (MetaBackend *backend,
|
||||
int device_id,
|
||||
uint32_t timestamp)
|
||||
{
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
int ret;
|
||||
|
||||
ret = XIUngrabDevice (priv->xdisplay, device_id, timestamp);
|
||||
|
||||
return (ret == Success);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_x11_class_init (MetaBackendX11Class *klass)
|
||||
{
|
||||
MetaBackendClass *backend_class = META_BACKEND_CLASS (klass);
|
||||
|
||||
backend_class->post_init = meta_backend_x11_post_init;
|
||||
backend_class->create_idle_monitor = meta_backend_x11_create_idle_monitor;
|
||||
backend_class->create_monitor_manager = meta_backend_x11_create_monitor_manager;
|
||||
|
||||
backend_class->grab_device = meta_backend_x11_grab_device;
|
||||
backend_class->ungrab_device = meta_backend_x11_ungrab_device;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_x11_init (MetaBackendX11 *x11)
|
||||
{
|
||||
/* We do X11 event retrieval ourselves */
|
||||
clutter_x11_disable_event_retrieval ();
|
||||
}
|
||||
|
||||
Display *
|
||||
meta_backend_x11_get_xdisplay (MetaBackendX11 *x11)
|
||||
{
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
|
||||
return priv->xdisplay;
|
||||
}
|
||||
|
@ -1,56 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#ifndef META_BACKEND_X11_H
|
||||
#define META_BACKEND_X11_H
|
||||
|
||||
#include "backends/meta-backend-private.h"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#define META_TYPE_BACKEND_X11 (meta_backend_x11_get_type ())
|
||||
#define META_BACKEND_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BACKEND_X11, MetaBackendX11))
|
||||
#define META_BACKEND_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_BACKEND_X11, MetaBackendX11Class))
|
||||
#define META_IS_BACKEND_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_BACKEND_X11))
|
||||
#define META_IS_BACKEND_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_BACKEND_X11))
|
||||
#define META_BACKEND_X11_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_BACKEND_X11, MetaBackendX11Class))
|
||||
|
||||
typedef struct _MetaBackendX11 MetaBackendX11;
|
||||
typedef struct _MetaBackendX11Class MetaBackendX11Class;
|
||||
|
||||
struct _MetaBackendX11
|
||||
{
|
||||
MetaBackend parent;
|
||||
};
|
||||
|
||||
struct _MetaBackendX11Class
|
||||
{
|
||||
MetaBackendClass parent_class;
|
||||
};
|
||||
|
||||
GType meta_backend_x11_get_type (void) G_GNUC_CONST;
|
||||
|
||||
Display * meta_backend_x11_get_xdisplay (MetaBackendX11 *backend);
|
||||
|
||||
#endif /* META_BACKEND_X11_H */
|
138
src/backends/x11/meta-cursor-tracker-x11.c
Normal file
138
src/backends/x11/meta-cursor-tracker-x11.c
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright 2014 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gdk/gdkx.h>
|
||||
|
||||
#include <meta/errors.h>
|
||||
|
||||
#include "display-private.h"
|
||||
#include "meta-cursor-tracker-x11.h"
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
#include "meta-cursor-private.h"
|
||||
|
||||
struct _MetaCursorTrackerX11
|
||||
{
|
||||
MetaCursorTracker parent;
|
||||
};
|
||||
|
||||
struct _MetaCursorTrackerX11Class
|
||||
{
|
||||
MetaCursorTrackerClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaCursorTrackerX11, meta_cursor_tracker_x11, META_TYPE_CURSOR_TRACKER);
|
||||
|
||||
static void
|
||||
meta_cursor_tracker_x11_get_pointer (MetaCursorTracker *tracker,
|
||||
int *x,
|
||||
int *y,
|
||||
ClutterModifierType *mods)
|
||||
{
|
||||
GdkDeviceManager *gmanager;
|
||||
GdkDevice *gdevice;
|
||||
GdkScreen *gscreen;
|
||||
|
||||
/* We can't use the clutter interface when not running as a wayland
|
||||
* compositor, because we need to query the server, rather than
|
||||
* using the last cached value.
|
||||
*/
|
||||
gmanager = gdk_display_get_device_manager (gdk_display_get_default ());
|
||||
gdevice = gdk_x11_device_manager_lookup (gmanager, META_VIRTUAL_CORE_POINTER_ID);
|
||||
|
||||
gdk_device_get_position (gdevice, &gscreen, x, y);
|
||||
if (mods)
|
||||
gdk_device_get_state (gdevice,
|
||||
gdk_screen_get_root_window (gscreen),
|
||||
NULL, (GdkModifierType*)mods);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_tracker_x11_sync_cursor (MetaCursorTracker *tracker)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
|
||||
meta_error_trap_push (display);
|
||||
if (tracker->is_showing)
|
||||
XFixesShowCursor (display->xdisplay,
|
||||
DefaultRootWindow (display->xdisplay));
|
||||
else
|
||||
XFixesHideCursor (display->xdisplay,
|
||||
DefaultRootWindow (display->xdisplay));
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_tracker_x11_ensure_cursor (MetaCursorTracker *tracker)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
XFixesCursorImage *cursor_image;
|
||||
MetaCursorReference *cursor;
|
||||
|
||||
if (tracker->has_window_cursor)
|
||||
return;
|
||||
|
||||
cursor_image = XFixesGetCursorImage (display->xdisplay);
|
||||
if (!cursor_image)
|
||||
return;
|
||||
|
||||
cursor = meta_cursor_reference_from_xfixes_cursor_image (cursor_image);
|
||||
|
||||
_meta_cursor_tracker_set_window_cursor (tracker, TRUE, cursor);
|
||||
|
||||
XFree (cursor_image);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_tracker_x11_class_init (MetaCursorTrackerX11Class *klass)
|
||||
{
|
||||
MetaCursorTrackerClass *cursor_tracker_class = META_CURSOR_TRACKER_CLASS (klass);
|
||||
|
||||
cursor_tracker_class->get_pointer = meta_cursor_tracker_x11_get_pointer;
|
||||
cursor_tracker_class->sync_cursor = meta_cursor_tracker_x11_sync_cursor;
|
||||
cursor_tracker_class->ensure_cursor = meta_cursor_tracker_x11_ensure_cursor;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_tracker_x11_init (MetaCursorTrackerX11 *self)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
|
||||
XFixesSelectCursorInput (display->xdisplay,
|
||||
DefaultRootWindow (display->xdisplay),
|
||||
XFixesDisplayCursorNotifyMask);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_cursor_tracker_x11_handle_xevent (MetaCursorTrackerX11 *tracker,
|
||||
XEvent *xevent)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
XFixesCursorNotifyEvent *notify_event;
|
||||
|
||||
if (xevent->xany.type != display->xfixes_event_base + XFixesCursorNotify)
|
||||
return FALSE;
|
||||
|
||||
notify_event = (XFixesCursorNotifyEvent *)xevent;
|
||||
if (notify_event->subtype != XFixesDisplayCursorNotify)
|
||||
return FALSE;
|
||||
|
||||
_meta_cursor_tracker_set_window_cursor (META_CURSOR_TRACKER (tracker), FALSE, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
40
src/backends/x11/meta-cursor-tracker-x11.h
Normal file
40
src/backends/x11/meta-cursor-tracker-x11.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2014 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef META_CURSOR_TRACKER_X11_H
|
||||
#define META_CURSOR_TRACKER_X11_H
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <meta/meta-cursor-tracker.h>
|
||||
|
||||
#define META_TYPE_CURSOR_TRACKER_X11 (meta_cursor_tracker_x11_get_type ())
|
||||
#define META_CURSOR_TRACKER_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CURSOR_TRACKER_X11, MetaCursorTrackerX11))
|
||||
#define META_CURSOR_TRACKER_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_CURSOR_TRACKER_X11, MetaCursorTrackerX11Class))
|
||||
#define META_IS_CURSOR_TRACKER_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_CURSOR_TRACKER_X11))
|
||||
#define META_IS_CURSOR_TRACKER_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_CURSOR_TRACKER_X11))
|
||||
#define META_CURSOR_TRACKER_X11_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_CURSOR_TRACKER_X11, MetaCursorTrackerX11Class))
|
||||
|
||||
typedef struct _MetaCursorTrackerX11 MetaCursorTrackerX11;
|
||||
typedef struct _MetaCursorTrackerX11Class MetaCursorTrackerX11Class;
|
||||
|
||||
GType meta_cursor_tracker_x11_get_type (void);
|
||||
|
||||
gboolean
|
||||
meta_cursor_tracker_x11_handle_xevent (MetaCursorTrackerX11 *tracker,
|
||||
XEvent *xevent);
|
||||
|
||||
#endif /* META_CURSOR_TRACKER_X11_H */
|
@ -25,7 +25,8 @@
|
||||
#include "meta-idle-monitor-xsync.h"
|
||||
#include "meta-idle-monitor-private.h"
|
||||
|
||||
#include "meta-backend-x11.h"
|
||||
#include <meta/util.h>
|
||||
#include "display-private.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@ -190,9 +191,10 @@ static void
|
||||
meta_idle_monitor_xsync_constructed (GObject *object)
|
||||
{
|
||||
MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (object);
|
||||
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
|
||||
|
||||
monitor_xsync->display = meta_backend_x11_get_xdisplay (backend);
|
||||
g_assert (!meta_is_wayland_compositor ());
|
||||
|
||||
monitor_xsync->display = meta_get_display ()->xdisplay;
|
||||
init_xsync (monitor_xsync);
|
||||
|
||||
G_OBJECT_CLASS (meta_idle_monitor_xsync_parent_class)->constructed (object);
|
||||
@ -289,10 +291,7 @@ meta_idle_monitor_xsync_make_watch (MetaIdleMonitor *monitor,
|
||||
g_hash_table_add (monitor_xsync->alarms, (gpointer) watch_xsync->xalarm);
|
||||
|
||||
if (meta_idle_monitor_get_idletime (monitor) > (gint64)timeout_msec)
|
||||
{
|
||||
watch->idle_source_id = g_idle_add (fire_watch_idle, watch);
|
||||
g_source_set_name_by_id (watch->idle_source_id, "[mutter] fire_watch_idle");
|
||||
}
|
||||
watch->idle_source_id = g_idle_add (fire_watch_idle, watch);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -44,4 +44,6 @@ GType meta_idle_monitor_xsync_get_type (void);
|
||||
void meta_idle_monitor_xsync_handle_xevent (MetaIdleMonitor *monitor,
|
||||
XSyncAlarmNotifyEvent *xevent);
|
||||
|
||||
void meta_idle_monitor_xsync_handle_xevent_all (XEvent *xevent);
|
||||
|
||||
#endif /* META_IDLE_MONITOR_XSYNC_H */
|
||||
|
@ -36,7 +36,6 @@
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#include <X11/extensions/dpms.h>
|
||||
|
||||
#include "meta-backend-x11.h"
|
||||
#include <meta/main.h>
|
||||
#include <meta/errors.h>
|
||||
#include "edid.h"
|
||||
@ -142,16 +141,16 @@ static gboolean
|
||||
output_get_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
gboolean value;
|
||||
Atom atom, actual_type;
|
||||
Atom actual_type;
|
||||
int actual_format;
|
||||
unsigned long nitems, bytes_after;
|
||||
unsigned char *buffer;
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, "_MUTTER_PRESENTATION_OUTPUT", False);
|
||||
XRRGetOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->output_id,
|
||||
atom,
|
||||
display->atom__MUTTER_PRESENTATION_OUTPUT,
|
||||
0, G_MAXLONG, False, False, XA_CARDINAL,
|
||||
&actual_type, &actual_format,
|
||||
&nitems, &bytes_after, &buffer);
|
||||
@ -178,16 +177,16 @@ static int
|
||||
output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
gboolean value;
|
||||
Atom atom, actual_type;
|
||||
Atom actual_type;
|
||||
int actual_format;
|
||||
unsigned long nitems, bytes_after;
|
||||
unsigned char *buffer;
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
|
||||
XRRGetOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->output_id,
|
||||
atom,
|
||||
display->atom_BACKLIGHT,
|
||||
0, G_MAXLONG, False, False, XA_INTEGER,
|
||||
&actual_type, &actual_format,
|
||||
&nitems, &bytes_after, &buffer);
|
||||
@ -206,13 +205,14 @@ static void
|
||||
output_get_backlight_limits_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output)
|
||||
{
|
||||
Atom atom;
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
XRRPropertyInfo *info;
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
|
||||
meta_error_trap_push (display);
|
||||
info = XRRQueryOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->output_id,
|
||||
atom);
|
||||
display->atom_BACKLIGHT);
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
if (info == NULL)
|
||||
{
|
||||
@ -314,13 +314,14 @@ static gboolean
|
||||
output_get_hotplug_mode_update (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
XID output_id)
|
||||
{
|
||||
Atom atom;
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
XRRPropertyInfo *info;
|
||||
gboolean result = FALSE;
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, "hotplug_mode_update", False);
|
||||
meta_error_trap_push (display);
|
||||
info = XRRQueryOutputProperty (manager_xrandr->xdisplay, output_id,
|
||||
atom);
|
||||
display->atom_hotplug_mode_update);
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
if (info)
|
||||
{
|
||||
@ -349,7 +350,9 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
||||
XRRFreeScreenResources (manager_xrandr->resources);
|
||||
manager_xrandr->resources = NULL;
|
||||
|
||||
meta_error_trap_push (meta_get_display ());
|
||||
dpms_capable = DPMSCapable (manager_xrandr->xdisplay);
|
||||
meta_error_trap_pop (meta_get_display ());
|
||||
|
||||
if (dpms_capable &&
|
||||
DPMSInfo (manager_xrandr->xdisplay, &dpms_state, &dpms_enabled) &&
|
||||
@ -449,8 +452,10 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
||||
XRRFreeCrtcInfo (crtc);
|
||||
}
|
||||
|
||||
meta_error_trap_push (meta_get_display ());
|
||||
primary_output = XRRGetOutputPrimary (manager_xrandr->xdisplay,
|
||||
DefaultRootWindow (manager_xrandr->xdisplay));
|
||||
meta_error_trap_pop (meta_get_display ());
|
||||
|
||||
n_actual_outputs = 0;
|
||||
for (i = 0; i < (unsigned)resources->noutput; i++)
|
||||
@ -632,8 +637,10 @@ meta_monitor_manager_xrandr_set_power_save_mode (MetaMonitorManager *manager,
|
||||
return;
|
||||
}
|
||||
|
||||
meta_error_trap_push (meta_get_display ());
|
||||
DPMSForceLevel (manager_xrandr->xdisplay, state);
|
||||
DPMSSetTimeouts (manager_xrandr->xdisplay, 0, 0, 0);
|
||||
meta_error_trap_pop (meta_get_display ());
|
||||
}
|
||||
|
||||
static Rotation
|
||||
@ -667,13 +674,12 @@ output_set_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output,
|
||||
gboolean presentation)
|
||||
{
|
||||
Atom atom;
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
int value = presentation;
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, "_MUTTER_PRESENTATION_OUTPUT", False);
|
||||
XRRChangeOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->output_id,
|
||||
atom,
|
||||
display->atom__MUTTER_PRESENTATION_OUTPUT,
|
||||
XA_CARDINAL, 32, PropModeReplace,
|
||||
(unsigned char*) &value, 1);
|
||||
}
|
||||
@ -686,10 +692,11 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
unsigned int n_outputs)
|
||||
{
|
||||
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
unsigned i;
|
||||
int width, height, width_mm, height_mm;
|
||||
|
||||
XGrabServer (manager_xrandr->xdisplay);
|
||||
meta_display_grab (display);
|
||||
|
||||
/* First compute the new size of the screen (framebuffer) */
|
||||
width = 0; height = 0;
|
||||
@ -783,8 +790,10 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
*/
|
||||
width_mm = (width / DPI_FALLBACK) * 25.4 + 0.5;
|
||||
height_mm = (height / DPI_FALLBACK) * 25.4 + 0.5;
|
||||
meta_error_trap_push (display);
|
||||
XRRSetScreenSize (manager_xrandr->xdisplay, DefaultRootWindow (manager_xrandr->xdisplay),
|
||||
width, height, width_mm, height_mm);
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
for (i = 0; i < n_crtcs; i++)
|
||||
{
|
||||
@ -841,6 +850,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
goto next;
|
||||
}
|
||||
|
||||
meta_error_trap_push (display);
|
||||
ok = XRRSetCrtcConfig (manager_xrandr->xdisplay,
|
||||
manager_xrandr->resources,
|
||||
(XID)crtc->crtc_id,
|
||||
@ -849,6 +859,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
(XID)mode->mode_id,
|
||||
wl_transform_to_xrandr (crtc_info->transform),
|
||||
outputs, n_outputs);
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
if (ok != Success)
|
||||
{
|
||||
@ -889,9 +900,11 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
|
||||
if (output_info->is_primary)
|
||||
{
|
||||
meta_error_trap_push (display);
|
||||
XRRSetOutputPrimary (manager_xrandr->xdisplay,
|
||||
DefaultRootWindow (manager_xrandr->xdisplay),
|
||||
(XID)output_info->output->output_id);
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
|
||||
output_set_presentation_xrandr (manager_xrandr,
|
||||
@ -917,7 +930,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
output->is_primary = FALSE;
|
||||
}
|
||||
|
||||
XUngrabServer (manager_xrandr->xdisplay);
|
||||
meta_display_ungrab (display);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -926,17 +939,18 @@ meta_monitor_manager_xrandr_change_backlight (MetaMonitorManager *manager,
|
||||
gint value)
|
||||
{
|
||||
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
|
||||
Atom atom;
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
int hw_value;
|
||||
|
||||
hw_value = round ((double)value / 100.0 * output->backlight_max + output->backlight_min);
|
||||
|
||||
atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
|
||||
meta_error_trap_push (display);
|
||||
XRRChangeOutputProperty (manager_xrandr->xdisplay,
|
||||
(XID)output->output_id,
|
||||
atom,
|
||||
display->atom_BACKLIGHT,
|
||||
XA_INTEGER, 32, PropModeReplace,
|
||||
(unsigned char *) &hw_value, 1);
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
/* We're not selecting for property notifies, so update the value immediately */
|
||||
output->backlight = normalize_backlight (output, hw_value);
|
||||
@ -994,65 +1008,11 @@ meta_monitor_manager_xrandr_rebuild_derived (MetaMonitorManager *manager)
|
||||
meta_monitor_manager_rebuild_derived (manager);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr)
|
||||
static gboolean
|
||||
meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManager *manager,
|
||||
XEvent *event)
|
||||
{
|
||||
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
|
||||
|
||||
manager_xrandr->xdisplay = meta_backend_x11_get_xdisplay (backend);
|
||||
|
||||
if (!XRRQueryExtension (manager_xrandr->xdisplay,
|
||||
&manager_xrandr->rr_event_base,
|
||||
&manager_xrandr->rr_error_base))
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We only use ScreenChangeNotify, but GDK uses the others,
|
||||
and we don't want to step on its toes */
|
||||
XRRSelectInput (manager_xrandr->xdisplay,
|
||||
DefaultRootWindow (manager_xrandr->xdisplay),
|
||||
RRScreenChangeNotifyMask
|
||||
| RRCrtcChangeNotifyMask
|
||||
| RROutputPropertyNotifyMask);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_xrandr_finalize (GObject *object)
|
||||
{
|
||||
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (object);
|
||||
|
||||
if (manager_xrandr->resources)
|
||||
XRRFreeScreenResources (manager_xrandr->resources);
|
||||
manager_xrandr->resources = NULL;
|
||||
|
||||
G_OBJECT_CLASS (meta_monitor_manager_xrandr_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass)
|
||||
{
|
||||
MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = meta_monitor_manager_xrandr_finalize;
|
||||
|
||||
manager_class->read_current = meta_monitor_manager_xrandr_read_current;
|
||||
manager_class->read_edid = meta_monitor_manager_xrandr_read_edid;
|
||||
manager_class->apply_configuration = meta_monitor_manager_xrandr_apply_configuration;
|
||||
manager_class->set_power_save_mode = meta_monitor_manager_xrandr_set_power_save_mode;
|
||||
manager_class->change_backlight = meta_monitor_manager_xrandr_change_backlight;
|
||||
manager_class->get_crtc_gamma = meta_monitor_manager_xrandr_get_crtc_gamma;
|
||||
manager_class->set_crtc_gamma = meta_monitor_manager_xrandr_set_crtc_gamma;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
XEvent *event)
|
||||
{
|
||||
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr);
|
||||
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
|
||||
MetaOutput *old_outputs;
|
||||
MetaCRTC *old_crtcs;
|
||||
MetaMonitorMode *old_modes;
|
||||
@ -1113,3 +1073,59 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
|
||||
manager_xrandr->xdisplay = display->xdisplay;
|
||||
|
||||
if (!XRRQueryExtension (manager_xrandr->xdisplay,
|
||||
&manager_xrandr->rr_event_base,
|
||||
&manager_xrandr->rr_error_base))
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We only use ScreenChangeNotify, but GDK uses the others,
|
||||
and we don't want to step on its toes */
|
||||
XRRSelectInput (manager_xrandr->xdisplay,
|
||||
DefaultRootWindow (manager_xrandr->xdisplay),
|
||||
RRScreenChangeNotifyMask
|
||||
| RRCrtcChangeNotifyMask
|
||||
| RROutputPropertyNotifyMask);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_xrandr_finalize (GObject *object)
|
||||
{
|
||||
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (object);
|
||||
|
||||
if (manager_xrandr->resources)
|
||||
XRRFreeScreenResources (manager_xrandr->resources);
|
||||
manager_xrandr->resources = NULL;
|
||||
|
||||
G_OBJECT_CLASS (meta_monitor_manager_xrandr_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass)
|
||||
{
|
||||
MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = meta_monitor_manager_xrandr_finalize;
|
||||
|
||||
manager_class->read_current = meta_monitor_manager_xrandr_read_current;
|
||||
manager_class->read_edid = meta_monitor_manager_xrandr_read_edid;
|
||||
manager_class->apply_configuration = meta_monitor_manager_xrandr_apply_configuration;
|
||||
manager_class->set_power_save_mode = meta_monitor_manager_xrandr_set_power_save_mode;
|
||||
manager_class->change_backlight = meta_monitor_manager_xrandr_change_backlight;
|
||||
manager_class->get_crtc_gamma = meta_monitor_manager_xrandr_get_crtc_gamma;
|
||||
manager_class->set_crtc_gamma = meta_monitor_manager_xrandr_set_crtc_gamma;
|
||||
manager_class->handle_xevent = meta_monitor_manager_xrandr_handle_xevent;
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,4 @@ typedef struct _MetaMonitorManagerXrandr MetaMonitorManagerXrandr;
|
||||
|
||||
GType meta_monitor_manager_xrandr_get_type (void);
|
||||
|
||||
gboolean meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager,
|
||||
XEvent *event);
|
||||
|
||||
#endif /* META_MONITOR_MANAGER_XRANDR_H */
|
||||
|
@ -72,7 +72,6 @@
|
||||
#include <meta/meta-shadow-factory.h>
|
||||
#include "meta-window-actor-private.h"
|
||||
#include "meta-window-group.h"
|
||||
#include "meta-stage.h"
|
||||
#include "window-private.h" /* to check window->hidden */
|
||||
#include "display-private.h" /* for meta_display_lookup_x_window() */
|
||||
#include "util-private.h"
|
||||
@ -80,9 +79,6 @@
|
||||
#include <X11/extensions/shape.h>
|
||||
#include <X11/extensions/Xcomposite.h>
|
||||
|
||||
#include "backends/meta-backend.h"
|
||||
#include "backends/x11/meta-backend-x11.h"
|
||||
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
|
||||
static gboolean
|
||||
@ -151,13 +147,16 @@ process_damage (MetaCompositor *compositor,
|
||||
static Window
|
||||
get_output_window (MetaCompositor *compositor)
|
||||
{
|
||||
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
|
||||
Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
|
||||
Window output;
|
||||
MetaDisplay *display = compositor->display;
|
||||
Display *xdisplay = display->xdisplay;
|
||||
Window output, xroot;
|
||||
XWindowAttributes attr;
|
||||
long event_mask;
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||
|
||||
output = XCompositeGetOverlayWindow (xdisplay, DefaultRootWindow (xdisplay));
|
||||
xroot = display->screen->xroot;
|
||||
output = XCompositeGetOverlayWindow (xdisplay, xroot);
|
||||
|
||||
meta_core_add_old_event_mask (xdisplay, output, &mask);
|
||||
|
||||
@ -172,6 +171,12 @@ get_output_window (MetaCompositor *compositor)
|
||||
XISetMask (mask.mask, XI_Motion);
|
||||
XISelectEvents (xdisplay, output, &mask, 1);
|
||||
|
||||
event_mask = ExposureMask | PropertyChangeMask;
|
||||
if (XGetWindowAttributes (xdisplay, output, &attr))
|
||||
event_mask |= attr.your_event_mask;
|
||||
|
||||
XSelectInput (xdisplay, output, event_mask);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
@ -322,16 +327,38 @@ meta_stage_is_focused (MetaScreen *screen)
|
||||
}
|
||||
|
||||
static gboolean
|
||||
grab_devices (MetaModalOptions options,
|
||||
guint32 timestamp)
|
||||
begin_modal_x11 (MetaCompositor *compositor,
|
||||
MetaPlugin *plugin,
|
||||
MetaModalOptions options,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaBackend *backend = META_BACKEND (meta_get_backend ());
|
||||
gboolean pointer_grabbed = FALSE;
|
||||
gboolean keyboard_grabbed = FALSE;
|
||||
MetaDisplay *display = compositor->display;
|
||||
Display *xdpy = meta_display_get_xdisplay (display);
|
||||
Window grab_window = clutter_x11_get_stage_window (CLUTTER_STAGE (compositor->stage));
|
||||
int result;
|
||||
gboolean pointer_grabbed = FALSE;
|
||||
gboolean keyboard_grabbed = FALSE;
|
||||
|
||||
if ((options & META_MODAL_POINTER_ALREADY_GRABBED) == 0)
|
||||
{
|
||||
if (!meta_backend_grab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp))
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||
|
||||
XISetMask (mask.mask, XI_ButtonPress);
|
||||
XISetMask (mask.mask, XI_ButtonRelease);
|
||||
XISetMask (mask.mask, XI_Enter);
|
||||
XISetMask (mask.mask, XI_Leave);
|
||||
XISetMask (mask.mask, XI_Motion);
|
||||
|
||||
result = XIGrabDevice (xdpy,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
grab_window,
|
||||
timestamp,
|
||||
None,
|
||||
XIGrabModeAsync, XIGrabModeAsync,
|
||||
False, /* owner_events */
|
||||
&mask);
|
||||
if (result != Success)
|
||||
goto fail;
|
||||
|
||||
pointer_grabbed = TRUE;
|
||||
@ -339,7 +366,22 @@ grab_devices (MetaModalOptions options,
|
||||
|
||||
if ((options & META_MODAL_KEYBOARD_ALREADY_GRABBED) == 0)
|
||||
{
|
||||
if (!meta_backend_grab_device (backend, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp))
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||
|
||||
XISetMask (mask.mask, XI_KeyPress);
|
||||
XISetMask (mask.mask, XI_KeyRelease);
|
||||
|
||||
result = XIGrabDevice (xdpy,
|
||||
META_VIRTUAL_CORE_KEYBOARD_ID,
|
||||
grab_window,
|
||||
timestamp,
|
||||
None,
|
||||
XIGrabModeAsync, XIGrabModeAsync,
|
||||
False, /* owner_events */
|
||||
&mask);
|
||||
|
||||
if (result != Success)
|
||||
goto fail;
|
||||
|
||||
keyboard_grabbed = TRUE;
|
||||
@ -349,9 +391,9 @@ grab_devices (MetaModalOptions options,
|
||||
|
||||
fail:
|
||||
if (pointer_grabbed)
|
||||
meta_backend_ungrab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp);
|
||||
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_POINTER_ID, timestamp);
|
||||
if (keyboard_grabbed)
|
||||
meta_backend_ungrab_device (backend, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
|
||||
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@ -371,14 +413,9 @@ meta_begin_modal_for_plugin (MetaCompositor *compositor,
|
||||
if (is_modal (display) || display->grab_op != META_GRAB_OP_NONE)
|
||||
return FALSE;
|
||||
|
||||
/* XXX: why is this needed? */
|
||||
XIUngrabDevice (display->xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
timestamp);
|
||||
XSync (display->xdisplay, False);
|
||||
|
||||
if (!grab_devices (options, timestamp))
|
||||
return FALSE;
|
||||
if (!meta_is_wayland_compositor ())
|
||||
if (!begin_modal_x11 (compositor, plugin, options, timestamp))
|
||||
return FALSE;
|
||||
|
||||
display->grab_op = META_GRAB_OP_COMPOSITOR;
|
||||
display->grab_window = NULL;
|
||||
@ -397,7 +434,7 @@ meta_end_modal_for_plugin (MetaCompositor *compositor,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaDisplay *display = compositor->display;
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
Display *xdpy = meta_display_get_xdisplay (display);
|
||||
|
||||
g_return_if_fail (is_modal (display));
|
||||
|
||||
@ -406,11 +443,15 @@ meta_end_modal_for_plugin (MetaCompositor *compositor,
|
||||
display->grab_have_pointer = FALSE;
|
||||
display->grab_have_keyboard = FALSE;
|
||||
|
||||
meta_backend_ungrab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp);
|
||||
meta_backend_ungrab_device (backend, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
meta_display_sync_wayland_input_focus (display);
|
||||
{
|
||||
meta_display_sync_wayland_input_focus (display);
|
||||
}
|
||||
else
|
||||
{
|
||||
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_POINTER_ID, timestamp);
|
||||
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -450,7 +491,7 @@ redirect_windows (MetaScreen *screen)
|
||||
*/
|
||||
while (TRUE)
|
||||
{
|
||||
meta_error_trap_push (display);
|
||||
meta_error_trap_push_with_return (display);
|
||||
XCompositeRedirectSubwindows (xdisplay, xroot, CompositeRedirectManual);
|
||||
XSync (xdisplay, FALSE);
|
||||
|
||||
@ -478,17 +519,16 @@ meta_compositor_manage (MetaCompositor *compositor)
|
||||
MetaScreen *screen = display->screen;
|
||||
Window xwin = 0;
|
||||
gint width, height;
|
||||
MetaWaylandCompositor *wayland_compositor;
|
||||
|
||||
meta_screen_set_cm_selection (display->screen);
|
||||
|
||||
/* We will have already created a stage if running as a wayland
|
||||
* compositor... */
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
MetaWaylandCompositor *wayland_compositor = meta_wayland_compositor_get_default ();
|
||||
|
||||
compositor->stage = meta_stage_new ();
|
||||
clutter_actor_show (compositor->stage);
|
||||
|
||||
wayland_compositor->stage = compositor->stage;
|
||||
wayland_compositor = meta_wayland_compositor_get_default ();
|
||||
compositor->stage = wayland_compositor->stage;
|
||||
|
||||
meta_screen_get_size (screen, &width, &height);
|
||||
clutter_actor_set_size (compositor->stage, width, height);
|
||||
@ -505,12 +545,12 @@ meta_compositor_manage (MetaCompositor *compositor)
|
||||
XResizeWindow (xdisplay, xwin, width, height);
|
||||
|
||||
{
|
||||
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
|
||||
Display *backend_xdisplay = meta_backend_x11_get_xdisplay (backend);
|
||||
long event_mask;
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||
XWindowAttributes attr;
|
||||
|
||||
meta_core_add_old_event_mask (backend_xdisplay, xwin, &mask);
|
||||
meta_core_add_old_event_mask (xdisplay, xwin, &mask);
|
||||
|
||||
XISetMask (mask.mask, XI_KeyPress);
|
||||
XISetMask (mask.mask, XI_KeyRelease);
|
||||
@ -524,7 +564,13 @@ meta_compositor_manage (MetaCompositor *compositor)
|
||||
XIClearMask (mask.mask, XI_TouchBegin);
|
||||
XIClearMask (mask.mask, XI_TouchEnd);
|
||||
XIClearMask (mask.mask, XI_TouchUpdate);
|
||||
XISelectEvents (backend_xdisplay, xwin, &mask, 1);
|
||||
XISelectEvents (xdisplay, xwin, &mask, 1);
|
||||
|
||||
event_mask = ExposureMask | PropertyChangeMask | StructureNotifyMask;
|
||||
if (XGetWindowAttributes (xdisplay, xwin, &attr))
|
||||
event_mask |= attr.your_event_mask;
|
||||
|
||||
XSelectInput (xdisplay, xwin, event_mask);
|
||||
}
|
||||
}
|
||||
|
||||
@ -708,6 +754,29 @@ meta_compositor_queue_frame_drawn (MetaCompositor *compositor,
|
||||
meta_window_actor_queue_frame_drawn (window_actor, no_delay_frame);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_grabbed_event (MetaDisplay *display,
|
||||
XEvent *event)
|
||||
{
|
||||
if (event->type == GenericEvent &&
|
||||
event->xcookie.extension == display->xinput_opcode)
|
||||
{
|
||||
XIEvent *xev = (XIEvent *) event->xcookie.data;
|
||||
|
||||
switch (xev->evtype)
|
||||
{
|
||||
case XI_Motion:
|
||||
case XI_ButtonPress:
|
||||
case XI_ButtonRelease:
|
||||
case XI_KeyPress:
|
||||
case XI_KeyRelease:
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_window_shape_changed (MetaCompositor *compositor,
|
||||
MetaWindow *window)
|
||||
@ -744,6 +813,82 @@ meta_compositor_window_surface_changed (MetaCompositor *compositor,
|
||||
meta_window_actor_update_surface (window_actor);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
event_is_passive_button_grab (MetaDisplay *display,
|
||||
XIDeviceEvent *device_event)
|
||||
{
|
||||
/* see display.c for which events are passive button
|
||||
grabs (meta_display_grab_window_buttons() and
|
||||
meta_display_handle_events())
|
||||
we need to filter them here because normally they
|
||||
would be sent to gtk+ (they are on gtk+ frame xwindow),
|
||||
but we want to redirect them to clutter
|
||||
*/
|
||||
|
||||
if (device_event->evtype != XI_ButtonPress)
|
||||
return FALSE;
|
||||
|
||||
if (display->window_grab_modifiers == 0)
|
||||
return FALSE;
|
||||
|
||||
if ((device_event->mods.effective & display->window_grab_modifiers) !=
|
||||
display->window_grab_modifiers)
|
||||
return FALSE;
|
||||
|
||||
return device_event->detail < 4;
|
||||
}
|
||||
|
||||
/* Clutter makes the assumption that there is only one X window
|
||||
* per stage, which is a valid assumption to make for a generic
|
||||
* application toolkit. As such, it will ignore any events sent
|
||||
* to the a stage that isn't its X window.
|
||||
*
|
||||
* When running as an X window manager, we need to respond to
|
||||
* events from lots of windows. Trick Clutter into translating
|
||||
* these events by pretending we got an event on the stage window.
|
||||
*/
|
||||
static void
|
||||
maybe_spoof_event_as_stage_event (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
XEvent *event)
|
||||
{
|
||||
MetaDisplay *display = compositor->display;
|
||||
|
||||
if (event->type == GenericEvent &&
|
||||
event->xcookie.extension == display->xinput_opcode)
|
||||
{
|
||||
XIEvent *input_event = (XIEvent *) event->xcookie.data;
|
||||
XIDeviceEvent *device_event = ((XIDeviceEvent *) input_event);
|
||||
|
||||
switch (input_event->evtype)
|
||||
{
|
||||
case XI_Motion:
|
||||
case XI_ButtonPress:
|
||||
case XI_ButtonRelease:
|
||||
/* If this is a window frame, and we think GTK+ needs to handle the event,
|
||||
let GTK+ handle it without mangling */
|
||||
if (window && window->frame && device_event->event == window->frame->xwindow &&
|
||||
(meta_grab_op_is_clicking (display->grab_op) ||
|
||||
(display->grab_op == META_GRAB_OP_NONE && !event_is_passive_button_grab (display, device_event))))
|
||||
break;
|
||||
|
||||
case XI_KeyPress:
|
||||
case XI_KeyRelease:
|
||||
/* If this is a GTK+ widget, like a window menu, let GTK+ handle
|
||||
* it as-is without mangling. */
|
||||
if (meta_ui_window_is_widget (display->screen->ui, device_event->event))
|
||||
break;
|
||||
|
||||
device_event->event = clutter_x11_get_stage_window (CLUTTER_STAGE (compositor->stage));
|
||||
device_event->event_x = device_event->root_x;
|
||||
device_event->event_y = device_event->root_y;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_compositor_process_event: (skip)
|
||||
* @compositor:
|
||||
@ -756,6 +901,20 @@ meta_compositor_process_event (MetaCompositor *compositor,
|
||||
XEvent *event,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaDisplay *display = compositor->display;
|
||||
|
||||
if (is_modal (display) && is_grabbed_event (display, event))
|
||||
{
|
||||
meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event);
|
||||
|
||||
/* We always consume events even if the plugin says it didn't handle them;
|
||||
* exclusive is exclusive */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!meta_is_wayland_compositor ())
|
||||
maybe_spoof_event_as_stage_event (compositor, window, event);
|
||||
|
||||
if (meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event))
|
||||
return TRUE;
|
||||
|
||||
|
@ -81,8 +81,18 @@ _meta_plugin_xevent_filter (MetaPlugin *plugin,
|
||||
{
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
if (klass->xevent_filter)
|
||||
return klass->xevent_filter (plugin, xev);
|
||||
/* When mutter is running as a wayland compositor, things like input
|
||||
* events just come directly from clutter so it won't have disabled
|
||||
* clutter's event retrieval and won't need to forward it events (if
|
||||
* it did it would lead to recursion). Also when running as a
|
||||
* wayland compositor we shouldn't be assuming that we're running
|
||||
* with the clutter x11 backend.
|
||||
*/
|
||||
|
||||
if (klass->xevent_filter && klass->xevent_filter (plugin, xev))
|
||||
return TRUE;
|
||||
else if (!meta_is_wayland_compositor ())
|
||||
return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -1,176 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "meta-stage.h"
|
||||
|
||||
#include "meta-cursor-private.h"
|
||||
#include "meta-backend.h"
|
||||
#include <meta/util.h>
|
||||
|
||||
struct _MetaStagePrivate {
|
||||
CoglPipeline *pipeline;
|
||||
gboolean should_paint_cursor;
|
||||
|
||||
MetaCursorReference *cursor;
|
||||
|
||||
MetaRectangle current_rect;
|
||||
MetaRectangle previous_rect;
|
||||
gboolean previous_is_valid;
|
||||
};
|
||||
typedef struct _MetaStagePrivate MetaStagePrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaStage, meta_stage, CLUTTER_TYPE_STAGE);
|
||||
|
||||
static void
|
||||
update_pipeline (MetaStage *stage)
|
||||
{
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
|
||||
if (priv->cursor)
|
||||
{
|
||||
CoglTexture *texture = meta_cursor_reference_get_cogl_texture (priv->cursor, NULL, NULL);
|
||||
cogl_pipeline_set_layer_texture (priv->pipeline, 0, texture);
|
||||
}
|
||||
else
|
||||
cogl_pipeline_set_layer_texture (priv->pipeline, 0, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_stage_finalize (GObject *object)
|
||||
{
|
||||
MetaStage *stage = META_STAGE (object);
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
|
||||
if (priv->pipeline)
|
||||
cogl_object_unref (priv->pipeline);
|
||||
}
|
||||
|
||||
static void
|
||||
paint_cursor (MetaStage *stage)
|
||||
{
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
if (!priv->cursor)
|
||||
return;
|
||||
|
||||
cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (),
|
||||
priv->pipeline,
|
||||
priv->current_rect.x,
|
||||
priv->current_rect.y,
|
||||
priv->current_rect.x +
|
||||
priv->current_rect.width,
|
||||
priv->current_rect.y +
|
||||
priv->current_rect.height);
|
||||
|
||||
priv->previous_rect = priv->current_rect;
|
||||
priv->previous_is_valid = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_stage_paint (ClutterActor *actor)
|
||||
{
|
||||
MetaStage *stage = META_STAGE (actor);
|
||||
|
||||
CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor);
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
paint_cursor (stage);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_stage_class_init (MetaStageClass *klass)
|
||||
{
|
||||
ClutterActorClass *actor_class = (ClutterActorClass *) klass;
|
||||
GObjectClass *object_class = (GObjectClass *) klass;
|
||||
|
||||
object_class->finalize = meta_stage_finalize;
|
||||
|
||||
actor_class->paint = meta_stage_paint;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_stage_init (MetaStage *stage)
|
||||
{
|
||||
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
|
||||
priv->pipeline = cogl_pipeline_new (ctx);
|
||||
|
||||
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), FALSE);
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
meta_stage_new (void)
|
||||
{
|
||||
return g_object_new (META_TYPE_STAGE,
|
||||
"cursor-visible", FALSE,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
queue_redraw (MetaStage *stage)
|
||||
{
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
cairo_rectangle_int_t clip;
|
||||
|
||||
/* Clear the location the cursor was at before, if we need to. */
|
||||
if (priv->previous_is_valid)
|
||||
{
|
||||
clip.x = priv->previous_rect.x;
|
||||
clip.y = priv->previous_rect.y;
|
||||
clip.width = priv->previous_rect.width;
|
||||
clip.height = priv->previous_rect.height;
|
||||
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &clip);
|
||||
priv->previous_is_valid = FALSE;
|
||||
}
|
||||
|
||||
/* And queue a redraw for the current cursor location. */
|
||||
if (priv->cursor)
|
||||
{
|
||||
clip.x = priv->current_rect.x;
|
||||
clip.y = priv->current_rect.y;
|
||||
clip.width = priv->current_rect.width;
|
||||
clip.height = priv->current_rect.height;
|
||||
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &clip);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_stage_set_cursor (MetaStage *stage,
|
||||
MetaCursorReference *cursor,
|
||||
MetaRectangle *rect)
|
||||
{
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
|
||||
if (priv->cursor != cursor)
|
||||
{
|
||||
priv->cursor = cursor;
|
||||
update_pipeline (stage);
|
||||
}
|
||||
|
||||
priv->current_rect = *rect;
|
||||
queue_redraw (stage);
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Intel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef META_STAGE_H
|
||||
#define META_STAGE_H
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include "meta-cursor.h"
|
||||
#include <meta/boxes.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define META_TYPE_STAGE (meta_stage_get_type ())
|
||||
#define META_STAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_STAGE, MetaStage))
|
||||
#define META_STAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_STAGE, MetaStageClass))
|
||||
#define META_IS_STAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_STAGE))
|
||||
#define META_IS_STAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_STAGE))
|
||||
#define META_STAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_STAGE, MetaStageClass))
|
||||
|
||||
typedef struct _MetaStage MetaStage;
|
||||
typedef struct _MetaStageClass MetaStageClass;
|
||||
|
||||
struct _MetaStageClass
|
||||
{
|
||||
ClutterStageClass parent_class;
|
||||
};
|
||||
|
||||
struct _MetaStage
|
||||
{
|
||||
ClutterStage parent;
|
||||
};
|
||||
|
||||
GType meta_stage_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ClutterActor *meta_stage_new (void);
|
||||
|
||||
void meta_stage_set_cursor (MetaStage *stage,
|
||||
MetaCursorReference *cursor,
|
||||
MetaRectangle *rect);
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* META_STAGE_H */
|
@ -60,7 +60,6 @@ struct _MetaTextureTower
|
||||
CoglTexture *textures[MAX_TEXTURE_LEVELS];
|
||||
CoglOffscreen *fbos[MAX_TEXTURE_LEVELS];
|
||||
Box invalid[MAX_TEXTURE_LEVELS];
|
||||
CoglPipeline *pipeline_template;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -92,9 +91,6 @@ meta_texture_tower_free (MetaTextureTower *tower)
|
||||
{
|
||||
g_return_if_fail (tower != NULL);
|
||||
|
||||
if (tower->pipeline_template != NULL)
|
||||
cogl_object_unref (tower->pipeline_template);
|
||||
|
||||
meta_texture_tower_set_base_texture (tower, NULL);
|
||||
|
||||
g_slice_free (MetaTextureTower, tower);
|
||||
@ -377,7 +373,7 @@ texture_tower_create_texture (MetaTextureTower *tower,
|
||||
tower->invalid[level].y2 = height;
|
||||
}
|
||||
|
||||
static void
|
||||
static gboolean
|
||||
texture_tower_revalidate_fbo (MetaTextureTower *tower,
|
||||
int level)
|
||||
{
|
||||
@ -388,50 +384,174 @@ texture_tower_revalidate_fbo (MetaTextureTower *tower,
|
||||
int dest_texture_width = cogl_texture_get_width (dest_texture);
|
||||
int dest_texture_height = cogl_texture_get_height (dest_texture);
|
||||
Box *invalid = &tower->invalid[level];
|
||||
CoglFramebuffer *fb;
|
||||
CoglError *catch_error = NULL;
|
||||
CoglPipeline *pipeline;
|
||||
CoglMatrix modelview;
|
||||
|
||||
if (tower->fbos[level] == NULL)
|
||||
tower->fbos[level] = cogl_offscreen_new_with_texture (dest_texture);
|
||||
tower->fbos[level] = cogl_offscreen_new_to_texture (dest_texture);
|
||||
|
||||
fb = COGL_FRAMEBUFFER (tower->fbos[level]);
|
||||
if (tower->fbos[level] == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (!cogl_framebuffer_allocate (fb, &catch_error))
|
||||
cogl_push_framebuffer (COGL_FRAMEBUFFER (tower->fbos[level]));
|
||||
|
||||
cogl_ortho (0, dest_texture_width, dest_texture_height, 0, -1., 1.);
|
||||
|
||||
cogl_matrix_init_identity (&modelview);
|
||||
cogl_set_modelview_matrix (&modelview);
|
||||
|
||||
cogl_set_source_texture (tower->textures[level - 1]);
|
||||
cogl_rectangle_with_texture_coords (invalid->x1, invalid->y1,
|
||||
invalid->x2, invalid->y2,
|
||||
(2. * invalid->x1) / source_texture_width,
|
||||
(2. * invalid->y1) / source_texture_height,
|
||||
(2. * invalid->x2) / source_texture_width,
|
||||
(2. * invalid->y2) / source_texture_height);
|
||||
|
||||
cogl_pop_framebuffer ();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
fill_copy (guchar *buf,
|
||||
const guchar *source,
|
||||
int width)
|
||||
{
|
||||
memcpy (buf, source, width * 4);
|
||||
}
|
||||
|
||||
static void
|
||||
fill_scale_down (guchar *buf,
|
||||
const guchar *source,
|
||||
int width)
|
||||
{
|
||||
while (width > 1)
|
||||
{
|
||||
cogl_error_free (catch_error);
|
||||
return;
|
||||
buf[0] = (source[0] + source[4]) / 2;
|
||||
buf[1] = (source[1] + source[5]) / 2;
|
||||
buf[2] = (source[2] + source[6]) / 2;
|
||||
buf[3] = (source[3] + source[7]) / 2;
|
||||
|
||||
buf += 4;
|
||||
source += 8;
|
||||
width -= 2;
|
||||
}
|
||||
|
||||
cogl_framebuffer_orthographic (fb, 0, 0, dest_texture_width, dest_texture_height, -1., 1.);
|
||||
|
||||
if (!tower->pipeline_template)
|
||||
if (width > 0)
|
||||
{
|
||||
CoglContext *ctx =
|
||||
clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
tower->pipeline_template = cogl_pipeline_new (ctx);
|
||||
cogl_pipeline_set_blend (tower->pipeline_template, "RGBA = ADD (SRC_COLOR, 0)", NULL);
|
||||
buf[0] = source[0] / 2;
|
||||
buf[1] = source[1] / 2;
|
||||
buf[2] = source[2] / 2;
|
||||
buf[3] = source[3] / 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
texture_tower_revalidate_client (MetaTextureTower *tower,
|
||||
int level)
|
||||
{
|
||||
CoglTexture *source_texture = tower->textures[level - 1];
|
||||
int source_texture_width = cogl_texture_get_width (source_texture);
|
||||
int source_texture_height = cogl_texture_get_height (source_texture);
|
||||
guint source_rowstride;
|
||||
guchar *source_data;
|
||||
CoglTexture *dest_texture = tower->textures[level];
|
||||
int dest_texture_width = cogl_texture_get_width (dest_texture);
|
||||
int dest_texture_height = cogl_texture_get_height (dest_texture);
|
||||
int dest_x = tower->invalid[level].x1;
|
||||
int dest_y = tower->invalid[level].y1;
|
||||
int dest_width = tower->invalid[level].x2 - tower->invalid[level].x1;
|
||||
int dest_height = tower->invalid[level].y2 - tower->invalid[level].y1;
|
||||
guchar *dest_data;
|
||||
guchar *source_tmp1 = NULL, *source_tmp2 = NULL;
|
||||
int i, j;
|
||||
|
||||
source_rowstride = source_texture_width * 4;
|
||||
|
||||
source_data = g_malloc (source_texture_height * source_rowstride);
|
||||
cogl_texture_get_data (source_texture, TEXTURE_FORMAT, source_rowstride,
|
||||
source_data);
|
||||
|
||||
dest_data = g_malloc (dest_height * dest_width * 4);
|
||||
|
||||
if (dest_texture_height < source_texture_height)
|
||||
{
|
||||
source_tmp1 = g_malloc (dest_width * 4);
|
||||
source_tmp2 = g_malloc (dest_width * 4);
|
||||
}
|
||||
|
||||
pipeline = cogl_pipeline_copy (tower->pipeline_template);
|
||||
cogl_pipeline_set_layer_texture (pipeline, 0, tower->textures[level - 1]);
|
||||
for (i = 0; i < dest_height; i++)
|
||||
{
|
||||
guchar *dest_row = dest_data + i * dest_width * 4;
|
||||
if (dest_texture_height < source_texture_height)
|
||||
{
|
||||
guchar *source1, *source2;
|
||||
guchar *dest;
|
||||
|
||||
cogl_framebuffer_draw_textured_rectangle (fb, pipeline,
|
||||
invalid->x1, invalid->y1,
|
||||
invalid->x2, invalid->y2,
|
||||
(2. * invalid->x1) / source_texture_width,
|
||||
(2. * invalid->y1) / source_texture_height,
|
||||
(2. * invalid->x2) / source_texture_width,
|
||||
(2. * invalid->y2) / source_texture_height);
|
||||
if (dest_texture_width < source_texture_width)
|
||||
{
|
||||
fill_scale_down (source_tmp1,
|
||||
source_data + ((i + dest_y) * 2) * source_rowstride + dest_x * 2 * 4,
|
||||
dest_width * 2);
|
||||
fill_scale_down (source_tmp2,
|
||||
source_data + ((i + dest_y) * 2 + 1) * source_rowstride + dest_x * 2 * 4,
|
||||
dest_width * 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
fill_copy (source_tmp1,
|
||||
source_data + ((i + dest_y) * 2) * source_rowstride + dest_x * 4,
|
||||
dest_width);
|
||||
fill_copy (source_tmp2,
|
||||
source_data + ((i + dest_y) * 2 + 1) * source_rowstride + dest_x * 4,
|
||||
dest_width);
|
||||
}
|
||||
|
||||
cogl_object_unref (pipeline);
|
||||
source1 = source_tmp1;
|
||||
source2 = source_tmp2;
|
||||
|
||||
dest = dest_row;
|
||||
for (j = 0; j < dest_width * 4; j++)
|
||||
*(dest++) = (*(source1++) + *(source2++)) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dest_texture_width < source_texture_width)
|
||||
fill_scale_down (dest_row,
|
||||
source_data + (i + dest_y) * source_rowstride + dest_x * 2 * 4,
|
||||
dest_width * 2);
|
||||
else
|
||||
fill_copy (dest_row,
|
||||
source_data + (i + dest_y) * source_rowstride,
|
||||
dest_width);
|
||||
}
|
||||
}
|
||||
|
||||
cogl_texture_set_region (dest_texture,
|
||||
0, 0,
|
||||
dest_x, dest_y,
|
||||
dest_width, dest_height,
|
||||
dest_width, dest_height,
|
||||
TEXTURE_FORMAT,
|
||||
4 * dest_width,
|
||||
dest_data);
|
||||
|
||||
if (dest_texture_height < source_texture_height)
|
||||
{
|
||||
g_free (source_tmp1);
|
||||
g_free (source_tmp2);
|
||||
}
|
||||
|
||||
g_free (source_data);
|
||||
g_free (dest_data);
|
||||
}
|
||||
|
||||
static void
|
||||
texture_tower_revalidate (MetaTextureTower *tower,
|
||||
int level)
|
||||
{
|
||||
texture_tower_revalidate_fbo (tower, level);
|
||||
if (!texture_tower_revalidate_fbo (tower, level))
|
||||
texture_tower_revalidate_client (tower, level);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -855,7 +855,6 @@ queue_send_frame_messages_timeout (MetaWindowActor *self)
|
||||
* to be drawn when the timer expires.
|
||||
*/
|
||||
priv->send_frame_messages_timer = g_timeout_add_full (META_PRIORITY_REDRAW, offset, send_frame_messages_timeout, self, NULL);
|
||||
g_source_set_name_by_id (priv->send_frame_messages_timer, "[mutter] send_frame_messages_timeout");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -34,6 +34,7 @@
|
||||
|
||||
#define DESTROY_TIMEOUT 100
|
||||
#define MINIMIZE_TIMEOUT 250
|
||||
#define MAXIMIZE_TIMEOUT 250
|
||||
#define MAP_TIMEOUT 250
|
||||
#define SWITCH_TIMEOUT 500
|
||||
|
||||
@ -76,6 +77,18 @@ static void map (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor);
|
||||
static void destroy (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor);
|
||||
static void maximize (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height);
|
||||
static void unmaximize (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor,
|
||||
gint x,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height);
|
||||
|
||||
static void switch_workspace (MetaPlugin *plugin,
|
||||
gint from,
|
||||
@ -122,8 +135,12 @@ typedef struct _ActorPrivate
|
||||
ClutterActor *orig_parent;
|
||||
|
||||
ClutterTimeline *tml_minimize;
|
||||
ClutterTimeline *tml_maximize;
|
||||
ClutterTimeline *tml_destroy;
|
||||
ClutterTimeline *tml_map;
|
||||
|
||||
gboolean is_minimized : 1;
|
||||
gboolean is_maximized : 1;
|
||||
} ActorPrivate;
|
||||
|
||||
/* callback data for when animations complete */
|
||||
@ -199,6 +216,8 @@ meta_default_plugin_class_init (MetaDefaultPluginClass *klass)
|
||||
plugin_class->start = start;
|
||||
plugin_class->map = map;
|
||||
plugin_class->minimize = minimize;
|
||||
plugin_class->maximize = maximize;
|
||||
plugin_class->unmaximize = unmaximize;
|
||||
plugin_class->destroy = destroy;
|
||||
plugin_class->switch_workspace = switch_workspace;
|
||||
plugin_class->show_tile_preview = show_tile_preview;
|
||||
@ -503,6 +522,8 @@ minimize (MetaPlugin *plugin, MetaWindowActor *window_actor)
|
||||
EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
|
||||
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||
|
||||
apriv->is_minimized = TRUE;
|
||||
|
||||
animation = clutter_actor_animate (actor,
|
||||
CLUTTER_EASE_IN_SINE,
|
||||
MINIMIZE_TIMEOUT,
|
||||
@ -523,6 +544,115 @@ minimize (MetaPlugin *plugin, MetaWindowActor *window_actor)
|
||||
meta_plugin_minimize_completed (plugin, window_actor);
|
||||
}
|
||||
|
||||
/*
|
||||
* Minimize effect completion callback; this function restores actor state, and
|
||||
* calls the manager callback function.
|
||||
*/
|
||||
static void
|
||||
on_maximize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data)
|
||||
{
|
||||
/*
|
||||
* Must reverse the effect of the effect.
|
||||
*/
|
||||
MetaPlugin *plugin = data->plugin;
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (data->actor);
|
||||
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||
|
||||
apriv->tml_maximize = NULL;
|
||||
|
||||
/* FIXME - don't assume the original scale was 1.0 */
|
||||
clutter_actor_set_scale (data->actor, 1.0, 1.0);
|
||||
|
||||
/* Now notify the manager that we are done with this effect */
|
||||
meta_plugin_maximize_completed (plugin, window_actor);
|
||||
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
/*
|
||||
* The Nature of Maximize operation is such that it is difficult to do a visual
|
||||
* effect that would work well. Scaling, the obvious effect, does not work that
|
||||
* well, because at the end of the effect we end up with window content bigger
|
||||
* and differently laid out than in the real window; this is a proof concept.
|
||||
*
|
||||
* (Something like a sound would be more appropriate.)
|
||||
*/
|
||||
static void
|
||||
maximize (MetaPlugin *plugin,
|
||||
MetaWindowActor *window_actor,
|
||||
gint end_x, gint end_y, gint end_width, gint end_height)
|
||||
{
|
||||
MetaWindowType type;
|
||||
ClutterActor *actor = CLUTTER_ACTOR (window_actor);
|
||||
MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
|
||||
|
||||
gdouble scale_x = 1.0;
|
||||
gdouble scale_y = 1.0;
|
||||
|
||||
type = meta_window_get_window_type (meta_window);
|
||||
|
||||
if (type == META_WINDOW_NORMAL)
|
||||
{
|
||||
ClutterAnimation *animation;
|
||||
EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
|
||||
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||
gfloat width, height;
|
||||
gfloat x, y;
|
||||
|
||||
apriv->is_maximized = TRUE;
|
||||
|
||||
clutter_actor_get_size (actor, &width, &height);
|
||||
clutter_actor_get_position (actor, &x, &y);
|
||||
|
||||
/*
|
||||
* Work out the scale and anchor point so that the window is expanding
|
||||
* smoothly into the target size.
|
||||
*/
|
||||
scale_x = (gdouble)end_width / (gdouble) width;
|
||||
scale_y = (gdouble)end_height / (gdouble) height;
|
||||
|
||||
animation = clutter_actor_animate (actor,
|
||||
CLUTTER_EASE_IN_SINE,
|
||||
MAXIMIZE_TIMEOUT,
|
||||
"scale-x", scale_x,
|
||||
"scale-y", scale_y,
|
||||
NULL);
|
||||
apriv->tml_maximize = clutter_animation_get_timeline (animation);
|
||||
data->plugin = plugin;
|
||||
data->actor = actor;
|
||||
g_signal_connect (apriv->tml_maximize, "completed",
|
||||
G_CALLBACK (on_maximize_effect_complete),
|
||||
data);
|
||||
return;
|
||||
}
|
||||
|
||||
meta_plugin_maximize_completed (plugin, window_actor);
|
||||
}
|
||||
|
||||
/*
|
||||
* See comments on the maximize() function.
|
||||
*
|
||||
* (Just a skeleton code.)
|
||||
*/
|
||||
static void
|
||||
unmaximize (MetaPlugin *plugin,
|
||||
MetaWindowActor *window_actor,
|
||||
gint end_x, gint end_y, gint end_width, gint end_height)
|
||||
{
|
||||
MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
|
||||
MetaWindowType type = meta_window_get_window_type (meta_window);
|
||||
|
||||
if (type == META_WINDOW_NORMAL)
|
||||
{
|
||||
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||
|
||||
apriv->is_maximized = FALSE;
|
||||
}
|
||||
|
||||
/* Do this conditionally, if the effect requires completion callback. */
|
||||
meta_plugin_unmaximize_completed (plugin, window_actor);
|
||||
}
|
||||
|
||||
static void
|
||||
on_map_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data)
|
||||
{
|
||||
@ -578,6 +708,9 @@ map (MetaPlugin *plugin, MetaWindowActor *window_actor)
|
||||
g_signal_connect (apriv->tml_map, "completed",
|
||||
G_CALLBACK (on_map_effect_complete),
|
||||
data);
|
||||
|
||||
apriv->is_minimized = FALSE;
|
||||
|
||||
}
|
||||
else
|
||||
meta_plugin_map_completed (plugin, window_actor);
|
||||
@ -738,6 +871,12 @@ kill_window_effects (MetaPlugin *plugin,
|
||||
g_signal_emit_by_name (apriv->tml_minimize, "completed", NULL);
|
||||
}
|
||||
|
||||
if (apriv->tml_maximize)
|
||||
{
|
||||
clutter_timeline_stop (apriv->tml_maximize);
|
||||
g_signal_emit_by_name (apriv->tml_maximize, "completed", NULL);
|
||||
}
|
||||
|
||||
if (apriv->tml_map)
|
||||
{
|
||||
clutter_timeline_stop (apriv->tml_map);
|
||||
|
241
src/core/above-tab-keycode.c
Normal file
241
src/core/above-tab-keycode.c
Normal file
@ -0,0 +1,241 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Find the keycode for the key above the tab key */
|
||||
/*
|
||||
* Copyright 2010 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* The standard cycle-windows keybinding should be the key above the
|
||||
* tab key. This will have a different keysym on different keyboards -
|
||||
* it's the ` (grave) key on US keyboards but something else on many
|
||||
* other national layouts. So we need to figure out the keycode for
|
||||
* this key without reference to key symbol.
|
||||
*
|
||||
* The "correct" way to do this is to get the XKB geometry from the
|
||||
* X server, find the Tab key, find the key above the Tab key in the
|
||||
* same section and use the keycode for that key. This is what I
|
||||
* implemented here, but unfortunately, fetching the geometry is rather
|
||||
* slow (It could take 20ms or more.)
|
||||
*
|
||||
* If you looking for a way to optimize Mutter startup performance:
|
||||
* On all Linux systems using evdev the key above TAB will have
|
||||
* keycode 49. (KEY_GRAVE=41 + the 8 code point offset between
|
||||
* evdev keysyms and X keysyms.) So a configure option
|
||||
* --with-above-tab-keycode=49 could be added that bypassed this
|
||||
* code. It wouldn't work right for displaying Mutter remotely
|
||||
* to a non-Linux X server, but that is pretty rare.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "display-private.h"
|
||||
|
||||
#include <X11/keysym.h>
|
||||
|
||||
#ifdef HAVE_XKB
|
||||
#include <X11/XKBlib.h>
|
||||
#include <X11/extensions/XKBgeom.h>
|
||||
|
||||
static guint
|
||||
compute_above_tab_keycode (Display *xdisplay)
|
||||
{
|
||||
XkbDescPtr keyboard;
|
||||
XkbGeometryPtr geometry;
|
||||
int i, j, k;
|
||||
int tab_keycode;
|
||||
char *tab_name;
|
||||
XkbSectionPtr tab_section;
|
||||
XkbBoundsRec tab_bounds;
|
||||
XkbKeyPtr best_key = NULL;
|
||||
guint best_keycode = (guint)-1;
|
||||
int best_x_dist = G_MAXINT;
|
||||
int best_y_dist = G_MAXINT;
|
||||
|
||||
/* We need only the Names and the Geometry, but asking for these results
|
||||
* in the Keyboard information retrieval failing for unknown reasons.
|
||||
* (Testing with xorg-1.9.1.) So we ask for a part that we don't need
|
||||
* as well.
|
||||
*/
|
||||
keyboard = XkbGetKeyboard (xdisplay,
|
||||
XkbGBN_ClientSymbolsMask | XkbGBN_KeyNamesMask | XkbGBN_GeometryMask,
|
||||
XkbUseCoreKbd);
|
||||
if (!keyboard)
|
||||
return best_keycode;
|
||||
|
||||
geometry = keyboard->geom;
|
||||
|
||||
/* There could potentially be multiple keys with the Tab keysym on the keyboard;
|
||||
* but XKeysymToKeycode() returns us the one that the alt-Tab binding will
|
||||
* use which is good enough
|
||||
*/
|
||||
tab_keycode = XKeysymToKeycode (xdisplay, XK_Tab);
|
||||
if (tab_keycode == 0 || tab_keycode < keyboard->min_key_code || tab_keycode > keyboard->max_key_code)
|
||||
goto out;
|
||||
|
||||
/* The keyboard geometry is stored by key "name" rather than keycode.
|
||||
* (Key names are 4-character strings like like TAB or AE01.) We use the
|
||||
* 'names' part of the keyboard description to map keycode to key name.
|
||||
*
|
||||
* XKB has a "key aliases" feature where a single keyboard key can have
|
||||
* multiple names (with separate sets of aliases in the 'names' part and
|
||||
* in the 'geometry' part), but I don't really understand it or how it is used,
|
||||
* so I'm ignoring it here.
|
||||
*/
|
||||
|
||||
tab_name = keyboard->names->keys[tab_keycode].name; /* Not NULL terminated! */
|
||||
|
||||
/* First, iterate through the keyboard geometry to find the tab key; the keyboard
|
||||
* geometry has a three-level heirarchy of section > row > key
|
||||
*/
|
||||
for (i = 0; i < geometry->num_sections; i++)
|
||||
{
|
||||
XkbSectionPtr section = &geometry->sections[i];
|
||||
for (j = 0; j < section->num_rows; j++)
|
||||
{
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
XkbRowPtr row = §ion->rows[j];
|
||||
for (k = 0; k < row->num_keys; k++)
|
||||
{
|
||||
XkbKeyPtr key = &row->keys[k];
|
||||
XkbShapePtr shape = XkbKeyShape (geometry, key);
|
||||
|
||||
if (row->vertical)
|
||||
y += key->gap;
|
||||
else
|
||||
x += key->gap;
|
||||
|
||||
if (strncmp (key->name.name, tab_name, XkbKeyNameLength) == 0)
|
||||
{
|
||||
tab_section = section;
|
||||
tab_bounds = shape->bounds;
|
||||
tab_bounds.x1 += row->left + x;
|
||||
tab_bounds.x2 += row->left + x;
|
||||
tab_bounds.y1 += row->top + y;
|
||||
tab_bounds.y2 += row->top + y;
|
||||
|
||||
goto found_tab;
|
||||
}
|
||||
|
||||
if (row->vertical)
|
||||
y += (shape->bounds.y2 - shape->bounds.y1);
|
||||
else
|
||||
x += (shape->bounds.x2 - shape->bounds.x1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* No tab key found */
|
||||
goto out;
|
||||
|
||||
found_tab:
|
||||
|
||||
/* Now find the key that:
|
||||
* - Is in the same section as the Tab key
|
||||
* - Has a horizontal center in the Tab key's horizonal bounds
|
||||
* - Is above the Tab key at a distance closer than any other key
|
||||
* - In case of ties, has its horizontal center as close as possible
|
||||
* to the Tab key's horizontal center
|
||||
*/
|
||||
for (j = 0; j < tab_section->num_rows; j++)
|
||||
{
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
XkbRowPtr row = &tab_section->rows[j];
|
||||
for (k = 0; k < row->num_keys; k++)
|
||||
{
|
||||
XkbKeyPtr key = &row->keys[k];
|
||||
XkbShapePtr shape = XkbKeyShape(geometry, key);
|
||||
XkbBoundsRec bounds = shape->bounds;
|
||||
int x_center;
|
||||
int x_dist, y_dist;
|
||||
|
||||
if (row->vertical)
|
||||
y += key->gap;
|
||||
else
|
||||
x += key->gap;
|
||||
|
||||
bounds.x1 += row->left + x;
|
||||
bounds.x2 += row->left + x;
|
||||
bounds.y1 += row->top + y;
|
||||
bounds.y2 += row->top + y;
|
||||
|
||||
y_dist = tab_bounds.y1 - bounds.y2;
|
||||
if (y_dist < 0)
|
||||
continue;
|
||||
|
||||
x_center = (bounds.x1 + bounds.x2) / 2;
|
||||
if (x_center < tab_bounds.x1 || x_center > tab_bounds.x2)
|
||||
continue;
|
||||
|
||||
x_dist = ABS (x_center - (tab_bounds.x1 + tab_bounds.x2) / 2);
|
||||
|
||||
if (y_dist < best_y_dist ||
|
||||
(y_dist == best_y_dist && x_dist < best_x_dist))
|
||||
{
|
||||
best_key = key;
|
||||
best_x_dist = x_dist;
|
||||
best_y_dist = y_dist;
|
||||
}
|
||||
|
||||
if (row->vertical)
|
||||
y += (shape->bounds.y2 - shape->bounds.y1);
|
||||
else
|
||||
x += (shape->bounds.x2 - shape->bounds.x1);
|
||||
}
|
||||
}
|
||||
|
||||
if (best_key == NULL)
|
||||
goto out;
|
||||
|
||||
/* Now we need to resolve the name of the best key back to a keycode */
|
||||
for (i = keyboard->min_key_code; i < keyboard->max_key_code; i++)
|
||||
{
|
||||
if (strncmp (best_key->name.name, keyboard->names->keys[i].name, XkbKeyNameLength) == 0)
|
||||
{
|
||||
best_keycode = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
XkbFreeKeyboard (keyboard, 0, True);
|
||||
|
||||
return best_keycode;
|
||||
}
|
||||
#else /* !HAVE_XKB */
|
||||
static guint
|
||||
compute_above_tab_keycode (Display *xdisplay)
|
||||
{
|
||||
return XKeysymToKeycode (xdisplay, XK_grave);
|
||||
}
|
||||
#endif /* HAVE_XKB */
|
||||
|
||||
guint
|
||||
meta_display_get_above_tab_keycode (MetaDisplay *display)
|
||||
{
|
||||
if (display->above_tab_keycode == 0) /* not yet computed */
|
||||
display->above_tab_keycode = compute_above_tab_keycode (display->xdisplay);
|
||||
|
||||
if (display->above_tab_keycode == (guint)-1) /* failed to compute */
|
||||
return 0;
|
||||
else
|
||||
return display->above_tab_keycode;
|
||||
}
|
@ -120,7 +120,6 @@ bell_unflash_frame (gpointer data)
|
||||
static void
|
||||
bell_flash_window_frame (MetaWindow *window)
|
||||
{
|
||||
guint id;
|
||||
g_assert (window->frame != NULL);
|
||||
window->frame->is_flashing = 1;
|
||||
meta_frame_queue_draw (window->frame);
|
||||
@ -129,9 +128,8 @@ bell_flash_window_frame (MetaWindow *window)
|
||||
* we are guaranteed to get at least one frame drawn in the
|
||||
* flashed state, no matter how loaded we are.
|
||||
*/
|
||||
id = g_timeout_add_full (META_PRIORITY_REDRAW, 100,
|
||||
bell_unflash_frame, window->frame, NULL);
|
||||
g_source_set_name_by_id (id, "[mutter] bell_unflash_frame");
|
||||
g_timeout_add_full (META_PRIORITY_REDRAW, 100,
|
||||
bell_unflash_frame, window->frame, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -199,6 +199,14 @@ static void place_window_if_needed (MetaWindow *window,
|
||||
ConstraintInfo *info);
|
||||
static void update_onscreen_requirements (MetaWindow *window,
|
||||
ConstraintInfo *info);
|
||||
static void extend_by_frame (MetaWindow *window,
|
||||
MetaRectangle *rect);
|
||||
static void unextend_by_frame (MetaWindow *window,
|
||||
MetaRectangle *rect);
|
||||
static inline void get_size_limits (MetaWindow *window,
|
||||
gboolean include_frame,
|
||||
MetaRectangle *min_size,
|
||||
MetaRectangle *max_size);
|
||||
|
||||
typedef gboolean (* ConstraintFunc) (MetaWindow *window,
|
||||
ConstraintInfo *info,
|
||||
@ -492,6 +500,7 @@ place_window_if_needed(MetaWindow *window,
|
||||
meta_window_get_frame_rect (window, &placed_rect);
|
||||
|
||||
orig_rect = info->orig;
|
||||
extend_by_frame (window, &orig_rect);
|
||||
|
||||
meta_window_place (window, orig_rect.x, orig_rect.y,
|
||||
&placed_rect.x, &placed_rect.y);
|
||||
@ -613,6 +622,11 @@ update_onscreen_requirements (MetaWindow *window,
|
||||
* problematic case but this may need to be revisited.
|
||||
*/
|
||||
|
||||
/* The require onscreen/on-single-monitor and titlebar_visible
|
||||
* stuff is relative to the outer window, not the inner
|
||||
*/
|
||||
extend_by_frame (window, &info->current);
|
||||
|
||||
/* Update whether we want future constraint runs to require the
|
||||
* window to be on fully onscreen.
|
||||
*/
|
||||
@ -661,10 +675,28 @@ update_onscreen_requirements (MetaWindow *window,
|
||||
window->desc,
|
||||
window->require_titlebar_visible ? "TRUE" : "FALSE");
|
||||
}
|
||||
|
||||
/* Don't forget to restore the position of the window */
|
||||
unextend_by_frame (window, &info->current);
|
||||
}
|
||||
|
||||
static void
|
||||
extend_by_frame (MetaWindow *window,
|
||||
MetaRectangle *rect)
|
||||
{
|
||||
meta_window_client_rect_to_frame_rect (window, rect, rect);
|
||||
}
|
||||
|
||||
static void
|
||||
unextend_by_frame (MetaWindow *window,
|
||||
MetaRectangle *rect)
|
||||
{
|
||||
meta_window_frame_rect_to_client_rect (window, rect, rect);
|
||||
}
|
||||
|
||||
static inline void
|
||||
get_size_limits (MetaWindow *window,
|
||||
gboolean include_frame,
|
||||
MetaRectangle *min_size,
|
||||
MetaRectangle *max_size)
|
||||
{
|
||||
@ -677,8 +709,11 @@ get_size_limits (MetaWindow *window,
|
||||
max_size->width = window->size_hints.max_width;
|
||||
max_size->height = window->size_hints.max_height;
|
||||
|
||||
meta_window_client_rect_to_frame_rect (window, min_size, min_size);
|
||||
meta_window_client_rect_to_frame_rect (window, max_size, max_size);
|
||||
if (include_frame)
|
||||
{
|
||||
meta_window_client_rect_to_frame_rect (window, min_size, min_size);
|
||||
meta_window_client_rect_to_frame_rect (window, max_size, max_size);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -702,11 +737,13 @@ constrain_modal_dialog (MetaWindow *window,
|
||||
*/
|
||||
|
||||
child_rect = info->current;
|
||||
extend_by_frame (window, &child_rect);
|
||||
|
||||
meta_window_get_frame_rect (parent, &parent_rect);
|
||||
|
||||
child_rect.x = parent_rect.x + (parent_rect.width / 2 - child_rect.width / 2);
|
||||
child_rect.y = parent_rect.y + (parent_rect.height / 2 - child_rect.height / 2);
|
||||
unextend_by_frame (window, &child_rect);
|
||||
x = child_rect.x;
|
||||
y = child_rect.y;
|
||||
|
||||
@ -773,16 +810,19 @@ constrain_maximization (MetaWindow *window,
|
||||
active_workspace_struts = window->screen->active_workspace->all_struts;
|
||||
|
||||
target_size = info->current;
|
||||
extend_by_frame (window, &target_size);
|
||||
meta_rectangle_expand_to_avoiding_struts (&target_size,
|
||||
&info->entire_monitor,
|
||||
direction,
|
||||
active_workspace_struts);
|
||||
}
|
||||
/* Now make target_size = maximized size of client window */
|
||||
unextend_by_frame (window, &target_size);
|
||||
|
||||
/* Check min size constraints; max size constraints are ignored for maximized
|
||||
* windows, as per bug 327543.
|
||||
*/
|
||||
get_size_limits (window, &min_size, &max_size);
|
||||
get_size_limits (window, FALSE, &min_size, &max_size);
|
||||
hminbad = target_size.width < min_size.width && window->maximized_horizontally;
|
||||
vminbad = target_size.height < min_size.height && window->maximized_vertically;
|
||||
if (hminbad || vminbad)
|
||||
@ -836,11 +876,12 @@ constrain_tiling (MetaWindow *window,
|
||||
* use an external function for the actual calculation
|
||||
*/
|
||||
meta_window_get_current_tile_area (window, &target_size);
|
||||
unextend_by_frame (window, &target_size);
|
||||
|
||||
/* Check min size constraints; max size constraints are ignored as for
|
||||
* maximized windows.
|
||||
*/
|
||||
get_size_limits (window, &min_size, &max_size);
|
||||
get_size_limits (window, FALSE, &min_size, &max_size);
|
||||
hminbad = target_size.width < min_size.width;
|
||||
vminbad = target_size.height < min_size.height;
|
||||
if (hminbad || vminbad)
|
||||
@ -883,7 +924,7 @@ constrain_fullscreen (MetaWindow *window,
|
||||
|
||||
monitor = info->entire_monitor;
|
||||
|
||||
get_size_limits (window, &min_size, &max_size);
|
||||
get_size_limits (window, FALSE, &min_size, &max_size);
|
||||
too_big = !meta_rectangle_could_fit_rect (&monitor, &min_size);
|
||||
too_small = !meta_rectangle_could_fit_rect (&max_size, &monitor);
|
||||
if (too_big || too_small)
|
||||
@ -992,7 +1033,7 @@ constrain_size_limits (MetaWindow *window,
|
||||
return TRUE;
|
||||
|
||||
/* Determine whether constraint is already satisfied; exit if it is */
|
||||
get_size_limits (window, &min_size, &max_size);
|
||||
get_size_limits (window, FALSE, &min_size, &max_size);
|
||||
/* We ignore max-size limits for maximized windows; see #327543 */
|
||||
if (window->maximized_horizontally)
|
||||
max_size.width = MAX (max_size.width, info->current.width);
|
||||
@ -1184,7 +1225,8 @@ do_screen_and_monitor_relative_constraints (
|
||||
|
||||
/* Determine whether constraint applies; exit if it doesn't */
|
||||
how_far_it_can_be_smushed = info->current;
|
||||
get_size_limits (window, &min_size, &max_size);
|
||||
get_size_limits (window, TRUE, &min_size, &max_size);
|
||||
extend_by_frame (window, &info->current);
|
||||
|
||||
if (info->action_type != ACTION_MOVE)
|
||||
{
|
||||
@ -1203,7 +1245,10 @@ do_screen_and_monitor_relative_constraints (
|
||||
meta_rectangle_contained_in_region (region_spanning_rectangles,
|
||||
&info->current);
|
||||
if (exit_early || constraint_satisfied || check_only)
|
||||
return constraint_satisfied;
|
||||
{
|
||||
unextend_by_frame (window, &info->current);
|
||||
return constraint_satisfied;
|
||||
}
|
||||
|
||||
/* Enforce constraint */
|
||||
|
||||
@ -1225,6 +1270,7 @@ do_screen_and_monitor_relative_constraints (
|
||||
info->fixed_directions,
|
||||
&info->current);
|
||||
|
||||
unextend_by_frame (window, &info->current);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -261,6 +261,45 @@ meta_core_user_lower_and_unfocus (Display *xdisplay,
|
||||
timestamp);
|
||||
}
|
||||
|
||||
void
|
||||
meta_core_lower_beneath_grab_window (Display *xdisplay,
|
||||
Window xwindow,
|
||||
guint32 timestamp)
|
||||
{
|
||||
XWindowChanges changes;
|
||||
MetaDisplay *display;
|
||||
MetaScreen *screen;
|
||||
MetaWindow *grab_window;
|
||||
MetaStackWindow stack_window;
|
||||
MetaStackWindow stack_sibling;
|
||||
|
||||
display = meta_display_for_x_display (xdisplay);
|
||||
screen = display->screen;
|
||||
grab_window = display->grab_window;
|
||||
|
||||
if (grab_window == NULL)
|
||||
return;
|
||||
|
||||
changes.stack_mode = Below;
|
||||
changes.sibling = meta_window_get_toplevel_xwindow (grab_window);
|
||||
|
||||
stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
|
||||
stack_window.x11.xwindow = xwindow;
|
||||
stack_sibling.any.type = META_WINDOW_CLIENT_TYPE_X11;
|
||||
stack_sibling.x11.xwindow = changes.sibling;
|
||||
meta_stack_tracker_record_lower_below (screen->stack_tracker,
|
||||
&stack_window,
|
||||
&stack_sibling,
|
||||
XNextRequest (screen->display->xdisplay));
|
||||
|
||||
meta_error_trap_push (display);
|
||||
XConfigureWindow (xdisplay,
|
||||
xwindow,
|
||||
CWSibling | CWStackMode,
|
||||
&changes);
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
|
||||
void
|
||||
meta_core_user_focus (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
@ -620,6 +659,36 @@ meta_core_get_grab_op (Display *xdisplay)
|
||||
return display->grab_op;
|
||||
}
|
||||
|
||||
Window
|
||||
meta_core_get_grab_frame (Display *xdisplay)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
|
||||
display = meta_display_for_x_display (xdisplay);
|
||||
|
||||
g_assert (display != NULL);
|
||||
|
||||
if (display->grab_op != META_GRAB_OP_NONE &&
|
||||
display->grab_window &&
|
||||
display->grab_window->frame)
|
||||
return display->grab_window->frame->xwindow;
|
||||
else
|
||||
return None;
|
||||
}
|
||||
|
||||
int
|
||||
meta_core_get_grab_button (Display *xdisplay)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
|
||||
display = meta_display_for_x_display (xdisplay);
|
||||
|
||||
if (display->grab_op == META_GRAB_OP_NONE)
|
||||
return -1;
|
||||
|
||||
return display->grab_button;
|
||||
}
|
||||
|
||||
void
|
||||
meta_core_grab_buttons (Display *xdisplay,
|
||||
Window frame_xwindow)
|
||||
|
@ -114,6 +114,10 @@ void meta_core_user_focus (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
guint32 timestamp);
|
||||
|
||||
void meta_core_lower_beneath_grab_window (Display *xdisplay,
|
||||
Window xwindow,
|
||||
guint32 timestamp);
|
||||
|
||||
void meta_core_minimize (Display *xdisplay,
|
||||
Window frame_xwindow);
|
||||
void meta_core_toggle_maximize (Display *xdisplay,
|
||||
@ -178,6 +182,8 @@ gboolean meta_core_begin_grab_op (Display *xdisplay,
|
||||
void meta_core_end_grab_op (Display *xdisplay,
|
||||
guint32 timestamp);
|
||||
MetaGrabOp meta_core_get_grab_op (Display *xdisplay);
|
||||
Window meta_core_get_grab_frame (Display *xdisplay);
|
||||
int meta_core_get_grab_button (Display *xdisplay);
|
||||
|
||||
|
||||
void meta_core_grab_buttons (Display *xdisplay,
|
||||
|
@ -31,6 +31,7 @@
|
||||
|
||||
#include <glib.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xcursor/Xcursor.h>
|
||||
#include <meta/common.h>
|
||||
#include <meta/boxes.h>
|
||||
#include <meta/display.h>
|
||||
@ -43,7 +44,9 @@
|
||||
#include <libsn/sn.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_XSYNC
|
||||
#include <X11/extensions/sync.h>
|
||||
#endif
|
||||
|
||||
typedef struct _MetaStack MetaStack;
|
||||
typedef struct _MetaUISlave MetaUISlave;
|
||||
@ -145,10 +148,13 @@ struct _MetaDisplay
|
||||
guint focused_by_us : 1;
|
||||
|
||||
/*< private-ish >*/
|
||||
guint error_trap_synced_at_last_pop : 1;
|
||||
MetaScreen *screen;
|
||||
GHashTable *xids;
|
||||
GHashTable *wayland_windows;
|
||||
|
||||
int error_traps;
|
||||
int (* error_trap_handler) (Display *display,
|
||||
XErrorEvent *error);
|
||||
int server_grab_count;
|
||||
|
||||
/* serials of leave/unmap events that may
|
||||
@ -194,6 +200,7 @@ struct _MetaDisplay
|
||||
int grab_tile_monitor_number;
|
||||
int grab_latest_motion_x;
|
||||
int grab_latest_motion_y;
|
||||
gulong grab_mask;
|
||||
guint grab_have_pointer : 1;
|
||||
guint grab_have_keyboard : 1;
|
||||
guint grab_frame_action : 1;
|
||||
@ -203,7 +210,9 @@ struct _MetaDisplay
|
||||
MetaRectangle grab_initial_window_pos;
|
||||
int grab_initial_x, grab_initial_y; /* These are only relevant for */
|
||||
gboolean grab_threshold_movement_reached; /* raise_on_click == FALSE. */
|
||||
MetaResizePopup *grab_resize_popup;
|
||||
GTimeVal grab_last_moveresize_time;
|
||||
GList* grab_old_window_stacking;
|
||||
MetaEdgeResistanceData *grab_edge_resistance_data;
|
||||
unsigned int grab_last_user_action_was_snap;
|
||||
guint32 grab_timestamp;
|
||||
@ -226,7 +235,11 @@ struct _MetaDisplay
|
||||
int max_keycode;
|
||||
KeySym *keymap;
|
||||
int keysyms_per_keycode;
|
||||
XModifierKeymap *modmap;
|
||||
unsigned int above_tab_keycode;
|
||||
unsigned int ignored_modifier_mask;
|
||||
unsigned int num_lock_mask;
|
||||
unsigned int scroll_lock_mask;
|
||||
unsigned int hyper_mask;
|
||||
unsigned int super_mask;
|
||||
unsigned int meta_mask;
|
||||
@ -262,6 +275,9 @@ struct _MetaDisplay
|
||||
/* Managed by compositor.c */
|
||||
MetaCompositor *compositor;
|
||||
|
||||
int render_event_base;
|
||||
int render_error_base;
|
||||
|
||||
int composite_event_base;
|
||||
int composite_error_base;
|
||||
int composite_major_version;
|
||||
@ -277,14 +293,28 @@ struct _MetaDisplay
|
||||
#ifdef HAVE_STARTUP_NOTIFICATION
|
||||
SnDisplay *sn_display;
|
||||
#endif
|
||||
#ifdef HAVE_XSYNC
|
||||
int xsync_event_base;
|
||||
int xsync_error_base;
|
||||
#endif
|
||||
#ifdef HAVE_SHAPE
|
||||
int shape_event_base;
|
||||
int shape_error_base;
|
||||
#endif
|
||||
#ifdef HAVE_XSYNC
|
||||
unsigned int have_xsync : 1;
|
||||
#define META_DISPLAY_HAS_XSYNC(display) ((display)->have_xsync)
|
||||
#else
|
||||
#define META_DISPLAY_HAS_XSYNC(display) FALSE
|
||||
#endif
|
||||
#ifdef HAVE_SHAPE
|
||||
unsigned int have_shape : 1;
|
||||
#define META_DISPLAY_HAS_SHAPE(display) ((display)->have_shape)
|
||||
#else
|
||||
#define META_DISPLAY_HAS_SHAPE(display) FALSE
|
||||
#endif
|
||||
unsigned int have_render : 1;
|
||||
#define META_DISPLAY_HAS_RENDER(display) ((display)->have_render)
|
||||
unsigned int have_composite : 1;
|
||||
unsigned int have_damage : 1;
|
||||
#define META_DISPLAY_HAS_COMPOSITE(display) ((display)->have_composite)
|
||||
@ -347,6 +377,7 @@ void meta_display_register_wayland_window (MetaDisplay *display,
|
||||
void meta_display_unregister_wayland_window (MetaDisplay *display,
|
||||
MetaWindow *window);
|
||||
|
||||
#ifdef HAVE_XSYNC
|
||||
MetaWindow* meta_display_lookup_sync_alarm (MetaDisplay *display,
|
||||
XSyncAlarm alarm);
|
||||
void meta_display_register_sync_alarm (MetaDisplay *display,
|
||||
@ -354,6 +385,7 @@ void meta_display_register_sync_alarm (MetaDisplay *display,
|
||||
MetaWindow *window);
|
||||
void meta_display_unregister_sync_alarm (MetaDisplay *display,
|
||||
XSyncAlarm alarm);
|
||||
#endif /* HAVE_XSYNC */
|
||||
|
||||
void meta_display_notify_window_created (MetaDisplay *display,
|
||||
MetaWindow *window);
|
||||
@ -366,9 +398,13 @@ MetaDisplay* meta_get_display (void);
|
||||
|
||||
Cursor meta_display_create_x_cursor (MetaDisplay *display,
|
||||
MetaCursor cursor);
|
||||
XcursorImage *meta_display_load_x_cursor (MetaDisplay *display,
|
||||
MetaCursor cursor);
|
||||
|
||||
void meta_display_set_grab_op_cursor (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
MetaGrabOp op,
|
||||
Window grab_xwindow,
|
||||
guint32 timestamp);
|
||||
|
||||
void meta_display_check_threshold_reached (MetaDisplay *display,
|
||||
@ -399,6 +435,9 @@ const char* meta_event_detail_to_string (int d);
|
||||
void meta_display_queue_retheme_all_windows (MetaDisplay *display);
|
||||
void meta_display_retheme_all (void);
|
||||
|
||||
void meta_display_set_cursor_theme (const char *theme,
|
||||
int size);
|
||||
|
||||
void meta_display_ping_window (MetaWindow *window,
|
||||
guint32 timestamp,
|
||||
MetaWindowPingFunc ping_reply_func,
|
||||
@ -411,10 +450,10 @@ int meta_resize_gravity_from_grab_op (MetaGrabOp op);
|
||||
|
||||
gboolean meta_grab_op_is_moving (MetaGrabOp op);
|
||||
gboolean meta_grab_op_is_resizing (MetaGrabOp op);
|
||||
gboolean meta_grab_op_is_moving_or_resizing (MetaGrabOp op);
|
||||
gboolean meta_grab_op_is_mouse (MetaGrabOp op);
|
||||
gboolean meta_grab_op_is_clicking (MetaGrabOp op);
|
||||
gboolean meta_grab_op_is_wayland (MetaGrabOp op);
|
||||
gboolean meta_grab_op_is_keyboard (MetaGrabOp op);
|
||||
gboolean meta_grab_op_should_block_wayland (MetaGrabOp op);
|
||||
|
||||
void meta_display_devirtualize_modifiers (MetaDisplay *display,
|
||||
MetaVirtualModifier modifiers,
|
||||
@ -434,6 +473,9 @@ void meta_display_accelerator_activate (MetaDisplay *display,
|
||||
ClutterKeyEvent *event);
|
||||
gboolean meta_display_modifiers_accelerator_activate (MetaDisplay *display);
|
||||
|
||||
/* In above-tab-keycode.c */
|
||||
guint meta_display_get_above_tab_keycode (MetaDisplay *display);
|
||||
|
||||
#ifdef HAVE_XI23
|
||||
gboolean meta_display_process_barrier_event (MetaDisplay *display,
|
||||
XIEvent *event);
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include <meta/errors.h>
|
||||
#include "keybindings-private.h"
|
||||
#include <meta/prefs.h>
|
||||
#include "resizepopup.h"
|
||||
#include "workspace-private.h"
|
||||
#include "bell.h"
|
||||
#include <meta/compositor.h>
|
||||
@ -49,14 +50,15 @@
|
||||
#include "mutter-enum-types.h"
|
||||
#include "meta-idle-monitor-dbus.h"
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
#include "meta-backend.h"
|
||||
#include "backends/x11/meta-backend-x11.h"
|
||||
|
||||
#ifdef HAVE_RANDR
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#endif
|
||||
#ifdef HAVE_SHAPE
|
||||
#include <X11/extensions/shape.h>
|
||||
#endif
|
||||
#include <X11/Xcursor/Xcursor.h>
|
||||
#include <X11/extensions/Xrender.h>
|
||||
#include <X11/extensions/Xcomposite.h>
|
||||
#include <X11/extensions/Xdamage.h>
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
@ -143,12 +145,10 @@ static MetaDisplay *the_display = NULL;
|
||||
static const char *gnome_wm_keybindings = "Mutter";
|
||||
static const char *net_wm_name = "Mutter";
|
||||
|
||||
static void update_cursor_theme (void);
|
||||
static void update_window_grab_modifiers (MetaDisplay *display);
|
||||
|
||||
static void prefs_changed_callback (MetaPreference pref,
|
||||
void *data);
|
||||
|
||||
static void
|
||||
meta_display_get_property(GObject *object,
|
||||
guint prop_id,
|
||||
@ -363,10 +363,12 @@ static void
|
||||
enable_compositor (MetaDisplay *display)
|
||||
{
|
||||
if (!META_DISPLAY_HAS_COMPOSITE (display) ||
|
||||
!META_DISPLAY_HAS_DAMAGE (display))
|
||||
!META_DISPLAY_HAS_DAMAGE (display) ||
|
||||
!META_DISPLAY_HAS_RENDER (display))
|
||||
{
|
||||
meta_warning ("Missing %s extension required for compositing",
|
||||
!META_DISPLAY_HAS_COMPOSITE (display) ? "composite" : "damage");
|
||||
!META_DISPLAY_HAS_COMPOSITE (display) ? "composite" :
|
||||
!META_DISPLAY_HAS_DAMAGE (display) ? "damage" : "render");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -470,6 +472,9 @@ meta_display_open (void)
|
||||
*/
|
||||
the_display->name = g_strdup (XDisplayName (NULL));
|
||||
the_display->xdisplay = xdisplay;
|
||||
the_display->error_trap_synced_at_last_pop = TRUE;
|
||||
the_display->error_traps = 0;
|
||||
the_display->error_trap_handler = NULL;
|
||||
the_display->server_grab_count = 0;
|
||||
the_display->display_opening = TRUE;
|
||||
|
||||
@ -480,6 +485,7 @@ meta_display_open (void)
|
||||
the_display->focus_serial = 0;
|
||||
the_display->server_focus_window = None;
|
||||
the_display->server_focus_serial = 0;
|
||||
the_display->grab_old_window_stacking = NULL;
|
||||
|
||||
the_display->mouse_mode = TRUE; /* Only relevant for mouse or sloppy focus */
|
||||
the_display->allow_terminal_deactivation = TRUE; /* Only relevant for when a
|
||||
@ -556,11 +562,13 @@ meta_display_open (void)
|
||||
|
||||
the_display->grab_op = META_GRAB_OP_NONE;
|
||||
the_display->grab_window = NULL;
|
||||
the_display->grab_resize_popup = NULL;
|
||||
the_display->grab_tile_mode = META_TILE_NONE;
|
||||
the_display->grab_tile_monitor_number = -1;
|
||||
|
||||
the_display->grab_edge_resistance_data = NULL;
|
||||
|
||||
#ifdef HAVE_XSYNC
|
||||
{
|
||||
int major, minor;
|
||||
|
||||
@ -593,7 +601,12 @@ meta_display_open (void)
|
||||
the_display->xsync_error_base,
|
||||
the_display->xsync_event_base);
|
||||
}
|
||||
#else /* HAVE_XSYNC */
|
||||
meta_verbose ("Not compiled with Xsync support\n");
|
||||
#endif /* !HAVE_XSYNC */
|
||||
|
||||
|
||||
#ifdef HAVE_SHAPE
|
||||
{
|
||||
the_display->have_shape = FALSE;
|
||||
|
||||
@ -614,6 +627,30 @@ meta_display_open (void)
|
||||
the_display->shape_error_base,
|
||||
the_display->shape_event_base);
|
||||
}
|
||||
#else /* HAVE_SHAPE */
|
||||
meta_verbose ("Not compiled with Shape support\n");
|
||||
#endif /* !HAVE_SHAPE */
|
||||
|
||||
{
|
||||
the_display->have_render = FALSE;
|
||||
|
||||
the_display->render_error_base = 0;
|
||||
the_display->render_event_base = 0;
|
||||
|
||||
if (!XRenderQueryExtension (the_display->xdisplay,
|
||||
&the_display->render_event_base,
|
||||
&the_display->render_error_base))
|
||||
{
|
||||
the_display->render_error_base = 0;
|
||||
the_display->render_event_base = 0;
|
||||
}
|
||||
else
|
||||
the_display->have_render = TRUE;
|
||||
|
||||
meta_verbose ("Attempted to init Render, found error base %d event base %d\n",
|
||||
the_display->render_error_base,
|
||||
the_display->render_event_base);
|
||||
}
|
||||
|
||||
{
|
||||
the_display->have_composite = FALSE;
|
||||
@ -722,7 +759,10 @@ meta_display_open (void)
|
||||
meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer\n");
|
||||
}
|
||||
|
||||
update_cursor_theme ();
|
||||
{
|
||||
XcursorSetTheme (the_display->xdisplay, meta_prefs_get_cursor_theme ());
|
||||
XcursorSetDefaultSize (the_display->xdisplay, meta_prefs_get_cursor_size ());
|
||||
}
|
||||
|
||||
/* Create the leader window here. Set its properties and
|
||||
* use the timestamp from one of the PropertyNotify events
|
||||
@ -976,6 +1016,9 @@ meta_display_close (MetaDisplay *display,
|
||||
return;
|
||||
}
|
||||
|
||||
if (display->error_traps > 0)
|
||||
meta_bug ("Display closed with error traps pending\n");
|
||||
|
||||
display->closing += 1;
|
||||
|
||||
meta_prefs_remove_listener (prefs_changed_callback, display);
|
||||
@ -986,6 +1029,9 @@ meta_display_close (MetaDisplay *display,
|
||||
g_source_remove (display->focus_timeout_id);
|
||||
display->focus_timeout_id = 0;
|
||||
|
||||
if (display->grab_old_window_stacking)
|
||||
g_list_free (display->grab_old_window_stacking);
|
||||
|
||||
/* Stop caring about events */
|
||||
meta_display_free_events (display);
|
||||
|
||||
@ -1108,6 +1154,27 @@ meta_get_display (void)
|
||||
return the_display;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
grab_op_is_mouse_only (MetaGrabOp op)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case META_GRAB_OP_MOVING:
|
||||
case META_GRAB_OP_RESIZING_SE:
|
||||
case META_GRAB_OP_RESIZING_S:
|
||||
case META_GRAB_OP_RESIZING_SW:
|
||||
case META_GRAB_OP_RESIZING_N:
|
||||
case META_GRAB_OP_RESIZING_NE:
|
||||
case META_GRAB_OP_RESIZING_NW:
|
||||
case META_GRAB_OP_RESIZING_W:
|
||||
case META_GRAB_OP_RESIZING_E:
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_grab_op_is_mouse (MetaGrabOp op)
|
||||
{
|
||||
@ -1122,6 +1189,17 @@ meta_grab_op_is_mouse (MetaGrabOp op)
|
||||
case META_GRAB_OP_RESIZING_NW:
|
||||
case META_GRAB_OP_RESIZING_W:
|
||||
case META_GRAB_OP_RESIZING_E:
|
||||
case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN:
|
||||
case META_GRAB_OP_KEYBOARD_RESIZING_S:
|
||||
case META_GRAB_OP_KEYBOARD_RESIZING_N:
|
||||
case META_GRAB_OP_KEYBOARD_RESIZING_W:
|
||||
case META_GRAB_OP_KEYBOARD_RESIZING_E:
|
||||
case META_GRAB_OP_KEYBOARD_RESIZING_SE:
|
||||
case META_GRAB_OP_KEYBOARD_RESIZING_NE:
|
||||
case META_GRAB_OP_KEYBOARD_RESIZING_SW:
|
||||
case META_GRAB_OP_KEYBOARD_RESIZING_NW:
|
||||
case META_GRAB_OP_KEYBOARD_MOVING:
|
||||
case META_GRAB_OP_COMPOSITOR:
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
@ -1144,6 +1222,7 @@ meta_grab_op_is_keyboard (MetaGrabOp op)
|
||||
case META_GRAB_OP_KEYBOARD_RESIZING_NE:
|
||||
case META_GRAB_OP_KEYBOARD_RESIZING_SW:
|
||||
case META_GRAB_OP_KEYBOARD_RESIZING_NW:
|
||||
case META_GRAB_OP_COMPOSITOR:
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
@ -1195,31 +1274,32 @@ meta_grab_op_is_moving (MetaGrabOp op)
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_grab_op_is_moving_or_resizing (MetaGrabOp op)
|
||||
meta_grab_op_is_clicking (MetaGrabOp grab_op)
|
||||
{
|
||||
return (meta_grab_op_is_moving (op) ||
|
||||
meta_grab_op_is_resizing (op));
|
||||
switch (grab_op)
|
||||
{
|
||||
case META_GRAB_OP_CLICKING_MINIMIZE:
|
||||
case META_GRAB_OP_CLICKING_MAXIMIZE:
|
||||
case META_GRAB_OP_CLICKING_UNMAXIMIZE:
|
||||
case META_GRAB_OP_CLICKING_DELETE:
|
||||
case META_GRAB_OP_CLICKING_MENU:
|
||||
case META_GRAB_OP_CLICKING_SHADE:
|
||||
case META_GRAB_OP_CLICKING_UNSHADE:
|
||||
case META_GRAB_OP_CLICKING_ABOVE:
|
||||
case META_GRAB_OP_CLICKING_UNABOVE:
|
||||
case META_GRAB_OP_CLICKING_STICK:
|
||||
case META_GRAB_OP_CLICKING_UNSTICK:
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_grab_op_should_block_wayland:
|
||||
* @op: A #MetaGrabOp
|
||||
*
|
||||
* Starting a grab with one of these grab operations means
|
||||
* that we will remove key / pointer focus from the current
|
||||
* Wayland focus.
|
||||
*/
|
||||
gboolean
|
||||
meta_grab_op_should_block_wayland (MetaGrabOp op)
|
||||
meta_grab_op_is_wayland (MetaGrabOp op)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case META_GRAB_OP_WAYLAND_POPUP:
|
||||
case META_GRAB_OP_NONE:
|
||||
return FALSE;
|
||||
default:
|
||||
return TRUE;
|
||||
}
|
||||
return (op != META_GRAB_OP_NONE && !meta_grab_op_is_clicking (op));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1303,6 +1383,19 @@ meta_display_get_current_time_roundtrip (MetaDisplay *display)
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_display_get_ignored_modifier_mask:
|
||||
* @display: a #MetaDisplay
|
||||
*
|
||||
* Returns: a mask of modifiers that should be ignored
|
||||
* when matching keybindings to events
|
||||
*/
|
||||
unsigned int
|
||||
meta_display_get_ignored_modifier_mask (MetaDisplay *display)
|
||||
{
|
||||
return display->ignored_modifier_mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_display_add_ignored_crossing_serial:
|
||||
* @display: a #MetaDisplay
|
||||
@ -1392,17 +1485,54 @@ meta_display_queue_autoraise_callback (MetaDisplay *display,
|
||||
meta_prefs_get_auto_raise_delay (),
|
||||
window_raise_with_delay_callback,
|
||||
window, NULL);
|
||||
g_source_set_name_by_id (display->autoraise_timeout_id, "[mutter] window_raise_with_delay_callback");
|
||||
display->autoraise_window = window;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
handle_net_restack_window (MetaDisplay* display,
|
||||
XEvent *event)
|
||||
{
|
||||
MetaWindow *window;
|
||||
|
||||
window = meta_display_lookup_x_window (display,
|
||||
event->xclient.window);
|
||||
|
||||
if (window)
|
||||
{
|
||||
/* FIXME: The EWMH includes a sibling for the restack request, but we
|
||||
* (stupidly) don't currently support these types of raises.
|
||||
*
|
||||
* Also, unconditionally following these is REALLY stupid--we should
|
||||
* combine this code with the stuff in
|
||||
* meta_window_x11_configure_request() which is smart about whether to
|
||||
* follow the request or do something else (though not smart enough
|
||||
* and is also too stupid to handle the sibling stuff).
|
||||
*/
|
||||
switch (event->xclient.data.l[2])
|
||||
{
|
||||
case Above:
|
||||
meta_window_raise (window);
|
||||
break;
|
||||
case Below:
|
||||
meta_window_lower (window);
|
||||
break;
|
||||
case TopIf:
|
||||
case BottomIf:
|
||||
case Opposite:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
meta_display_sync_wayland_input_focus (MetaDisplay *display)
|
||||
{
|
||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||
MetaWindow *focus_window = NULL;
|
||||
|
||||
if (meta_grab_op_should_block_wayland (display->grab_op))
|
||||
if (meta_grab_op_is_wayland (display->grab_op))
|
||||
focus_window = NULL;
|
||||
else if (meta_display_xwindow_is_a_no_focus_window (display, display->focus_xwindow))
|
||||
focus_window = NULL;
|
||||
@ -1413,7 +1543,10 @@ meta_display_sync_wayland_input_focus (MetaDisplay *display)
|
||||
|
||||
meta_wayland_compositor_set_input_focus (compositor, focus_window);
|
||||
|
||||
meta_wayland_seat_repick (compositor->seat);
|
||||
if (meta_grab_op_is_wayland (display->grab_op))
|
||||
meta_wayland_pointer_set_focus (&compositor->seat->pointer, NULL);
|
||||
else
|
||||
meta_wayland_seat_repick (compositor->seat, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1591,6 +1724,7 @@ meta_display_unregister_wayland_window (MetaDisplay *display,
|
||||
g_hash_table_remove (display->wayland_windows, window);
|
||||
}
|
||||
|
||||
#ifdef HAVE_XSYNC
|
||||
/* We store sync alarms in the window ID hash table, because they are
|
||||
* just more types of XIDs in the same global space, but we have
|
||||
* typesafe functions to register/unregister for readability.
|
||||
@ -1621,6 +1755,7 @@ meta_display_unregister_sync_alarm (MetaDisplay *display,
|
||||
|
||||
g_hash_table_remove (display->xids, &alarm);
|
||||
}
|
||||
#endif /* HAVE_XSYNC */
|
||||
|
||||
void
|
||||
meta_display_notify_window_created (MetaDisplay *display,
|
||||
@ -1696,34 +1831,51 @@ meta_cursor_for_grab_op (MetaGrabOp op)
|
||||
|
||||
void
|
||||
meta_display_set_grab_op_cursor (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
MetaGrabOp op,
|
||||
Window grab_xwindow,
|
||||
guint32 timestamp)
|
||||
{
|
||||
/* Set root cursor */
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaCursorTracker *tracker = meta_cursor_tracker_get_for_screen (display->screen);
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||
MetaCursor cursor = meta_cursor_for_grab_op (op);
|
||||
MetaCursorReference *cursor_ref;
|
||||
|
||||
cursor_ref = meta_cursor_reference_from_theme (cursor);
|
||||
meta_cursor_tracker_set_grab_cursor (tracker, cursor_ref);
|
||||
if (cursor_ref)
|
||||
meta_cursor_reference_unref (cursor_ref);
|
||||
XISetMask (mask.mask, XI_ButtonPress);
|
||||
XISetMask (mask.mask, XI_ButtonRelease);
|
||||
XISetMask (mask.mask, XI_Enter);
|
||||
XISetMask (mask.mask, XI_Leave);
|
||||
XISetMask (mask.mask, XI_Motion);
|
||||
|
||||
if (meta_backend_grab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp))
|
||||
display->grab_have_pointer = TRUE;
|
||||
}
|
||||
g_assert (screen != NULL);
|
||||
|
||||
static MetaWindow *
|
||||
get_toplevel_transient_for (MetaWindow *window)
|
||||
{
|
||||
while (TRUE)
|
||||
meta_error_trap_push (display);
|
||||
if (XIGrabDevice (display->xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
grab_xwindow,
|
||||
timestamp,
|
||||
meta_display_create_x_cursor (display, cursor),
|
||||
XIGrabModeAsync, XIGrabModeAsync,
|
||||
False, /* owner_events */
|
||||
&mask) == Success)
|
||||
{
|
||||
MetaWindow *parent = meta_window_get_transient_for (window);
|
||||
if (parent == NULL)
|
||||
return window;
|
||||
window = parent;
|
||||
display->grab_have_pointer = TRUE;
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"XIGrabDevice() returned GrabSuccess time %u\n",
|
||||
timestamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"XIGrabDevice() failed time %u\n",
|
||||
timestamp);
|
||||
}
|
||||
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
cursor_ref = meta_cursor_tracker_get_cursor_from_theme (screen->cursor_tracker, cursor);
|
||||
meta_cursor_tracker_set_grab_cursor (screen->cursor_tracker, cursor_ref);
|
||||
meta_cursor_reference_unref (cursor_ref);
|
||||
}
|
||||
|
||||
gboolean
|
||||
@ -1734,18 +1886,19 @@ meta_display_begin_grab_op (MetaDisplay *display,
|
||||
gboolean pointer_already_grabbed,
|
||||
gboolean frame_action,
|
||||
int button,
|
||||
gulong modmask, /* XXX - ignored */
|
||||
gulong modmask,
|
||||
guint32 timestamp,
|
||||
int root_x,
|
||||
int root_y)
|
||||
{
|
||||
MetaWindow *grab_window = NULL;
|
||||
|
||||
Window grab_xwindow;
|
||||
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Doing grab op %u on window %s button %d pointer already grabbed: %d pointer pos %d,%d\n",
|
||||
op, window ? window->desc : "none", button, pointer_already_grabbed,
|
||||
root_x, root_y);
|
||||
|
||||
|
||||
if (display->grab_op != META_GRAB_OP_NONE)
|
||||
{
|
||||
if (window)
|
||||
@ -1768,66 +1921,87 @@ meta_display_begin_grab_op (MetaDisplay *display,
|
||||
}
|
||||
}
|
||||
|
||||
grab_window = window;
|
||||
|
||||
/* If window is a modal dialog attached to its parent,
|
||||
* grab the parent instead for moving.
|
||||
*/
|
||||
if (meta_grab_op_is_moving (op))
|
||||
grab_window = get_toplevel_transient_for (window);
|
||||
if (window && meta_window_is_attached_dialog (window) &&
|
||||
meta_grab_op_is_moving (op))
|
||||
grab_window = meta_window_get_transient_for (window);
|
||||
|
||||
g_assert (grab_window != NULL);
|
||||
g_assert (op != META_GRAB_OP_NONE);
|
||||
if (grab_window == NULL)
|
||||
grab_window = window;
|
||||
|
||||
/* FIXME:
|
||||
* If we have no MetaWindow we do our best
|
||||
* and try to do the grab on the RootWindow.
|
||||
* This will fail if anyone else has any
|
||||
* key grab on the RootWindow.
|
||||
*/
|
||||
if (grab_window)
|
||||
grab_xwindow = meta_window_get_toplevel_xwindow (grab_window);
|
||||
else
|
||||
grab_xwindow = screen->xroot;
|
||||
|
||||
display->grab_have_pointer = FALSE;
|
||||
|
||||
|
||||
if (pointer_already_grabbed)
|
||||
display->grab_have_pointer = TRUE;
|
||||
|
||||
/* Since grab operations often happen as a result of implicit
|
||||
* pointer operations on the display X11 connection, we need
|
||||
* to ungrab here to ensure that the backend's X11 can take
|
||||
* the device grab. */
|
||||
XIUngrabDevice (display->xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
timestamp);
|
||||
XSync (display->xdisplay, False);
|
||||
|
||||
meta_display_set_grab_op_cursor (display, op, timestamp);
|
||||
|
||||
meta_display_set_grab_op_cursor (display, screen, op, grab_xwindow, timestamp);
|
||||
|
||||
if (!display->grab_have_pointer && !meta_grab_op_is_keyboard (op))
|
||||
{
|
||||
meta_topic (META_DEBUG_WINDOW_OPS, "XIGrabDevice() failed\n");
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"XIGrabDevice() failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Grab keys for keyboard ops and mouse move/resizes; see #126497 */
|
||||
if (meta_grab_op_is_moving_or_resizing (op))
|
||||
if (meta_grab_op_is_keyboard (op) || grab_op_is_mouse_only (op))
|
||||
{
|
||||
display->grab_have_keyboard = meta_window_grab_all_keys (grab_window, timestamp);
|
||||
if (grab_window)
|
||||
display->grab_have_keyboard =
|
||||
meta_window_grab_all_keys (grab_window, timestamp);
|
||||
|
||||
else
|
||||
display->grab_have_keyboard =
|
||||
meta_screen_grab_all_keys (screen, timestamp);
|
||||
|
||||
if (!display->grab_have_keyboard)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
meta_topic (META_DEBUG_WINDOW_OPS, "grabbing all keys failed, ungrabbing pointer\n");
|
||||
meta_backend_ungrab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp);
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"grabbing all keys failed, ungrabbing pointer\n");
|
||||
XIUngrabDevice (display->xdisplay, META_VIRTUAL_CORE_POINTER_ID, timestamp);
|
||||
display->grab_have_pointer = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
display->grab_op = op;
|
||||
display->grab_window = grab_window;
|
||||
display->grab_xwindow = grab_xwindow;
|
||||
display->grab_button = button;
|
||||
display->grab_tile_mode = grab_window->tile_mode;
|
||||
display->grab_tile_monitor_number = grab_window->tile_monitor_number;
|
||||
display->grab_mask = modmask;
|
||||
if (window)
|
||||
{
|
||||
display->grab_tile_mode = window->tile_mode;
|
||||
display->grab_tile_monitor_number = window->tile_monitor_number;
|
||||
}
|
||||
else
|
||||
{
|
||||
display->grab_tile_mode = META_TILE_NONE;
|
||||
display->grab_tile_monitor_number = -1;
|
||||
}
|
||||
display->grab_anchor_root_x = root_x;
|
||||
display->grab_anchor_root_y = root_y;
|
||||
display->grab_latest_motion_x = root_x;
|
||||
display->grab_latest_motion_y = root_y;
|
||||
display->grab_last_moveresize_time.tv_sec = 0;
|
||||
display->grab_last_moveresize_time.tv_usec = 0;
|
||||
display->grab_old_window_stacking = NULL;
|
||||
#ifdef HAVE_XSYNC
|
||||
display->grab_last_user_action_was_snap = FALSE;
|
||||
#endif
|
||||
display->grab_frame_action = frame_action;
|
||||
display->grab_resize_unmaximize = 0;
|
||||
display->grab_timestamp = timestamp;
|
||||
@ -1837,23 +2011,40 @@ meta_display_begin_grab_op (MetaDisplay *display,
|
||||
g_source_remove (display->grab_resize_timeout_id);
|
||||
display->grab_resize_timeout_id = 0;
|
||||
}
|
||||
|
||||
if (display->grab_window)
|
||||
{
|
||||
meta_window_get_client_root_coords (display->grab_window,
|
||||
&display->grab_initial_window_pos);
|
||||
display->grab_anchor_window_pos = display->grab_initial_window_pos;
|
||||
|
||||
#ifdef HAVE_XSYNC
|
||||
if ( meta_grab_op_is_resizing (display->grab_op) &&
|
||||
display->grab_window->sync_request_counter != None)
|
||||
{
|
||||
meta_window_create_sync_request_alarm (display->grab_window);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Grab op %u on window %s successful\n",
|
||||
display->grab_op, window ? window->desc : "(null)");
|
||||
|
||||
meta_window_get_client_root_coords (display->grab_window,
|
||||
&display->grab_initial_window_pos);
|
||||
display->grab_anchor_window_pos = display->grab_initial_window_pos;
|
||||
g_assert (display->grab_window != NULL);
|
||||
g_assert (display->grab_op != META_GRAB_OP_NONE);
|
||||
|
||||
if (display->grab_window)
|
||||
{
|
||||
meta_window_refresh_resize_popup (display->grab_window);
|
||||
}
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
meta_display_sync_wayland_input_focus (display);
|
||||
|
||||
g_signal_emit (display, display_signals[GRAB_OP_BEGIN], 0,
|
||||
screen, display->grab_window, display->grab_op);
|
||||
|
||||
meta_window_grab_op_began (display->grab_window, display->grab_op);
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -1861,57 +2052,83 @@ void
|
||||
meta_display_end_grab_op (MetaDisplay *display,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaCursorTracker *tracker;
|
||||
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Ending grab op %u at time %u\n", display->grab_op, timestamp);
|
||||
|
||||
|
||||
if (display->grab_op == META_GRAB_OP_NONE)
|
||||
return;
|
||||
|
||||
g_signal_emit (display, display_signals[GRAB_OP_END], 0,
|
||||
display->screen, display->grab_window, display->grab_op);
|
||||
|
||||
meta_window_grab_op_ended (display->grab_window, display->grab_op);
|
||||
|
||||
if (meta_grab_op_is_moving_or_resizing (display->grab_op))
|
||||
if (display->grab_window != NULL)
|
||||
display->grab_window->shaken_loose = FALSE;
|
||||
|
||||
if (display->grab_window != NULL &&
|
||||
!meta_prefs_get_raise_on_click () &&
|
||||
(meta_grab_op_is_moving (display->grab_op) ||
|
||||
meta_grab_op_is_resizing (display->grab_op)))
|
||||
{
|
||||
/* Clear out the edge cache */
|
||||
meta_display_cleanup_edges (display);
|
||||
|
||||
/* Only raise the window in orthogonal raise
|
||||
* ('do-not-raise-on-click') mode if the user didn't try to move
|
||||
* or resize the given window by at least a threshold amount.
|
||||
* For raise on click mode, the window was raised at the
|
||||
* beginning of the grab_op.
|
||||
*/
|
||||
if (!meta_prefs_get_raise_on_click () &&
|
||||
display->grab_threshold_movement_reached)
|
||||
if (!display->grab_threshold_movement_reached)
|
||||
meta_window_raise (display->grab_window);
|
||||
}
|
||||
|
||||
/* If this was a move or resize clear out the edge cache */
|
||||
if (meta_grab_op_is_resizing (display->grab_op) ||
|
||||
meta_grab_op_is_moving (display->grab_op))
|
||||
{
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Clearing out the edges for resistance/snapping");
|
||||
meta_display_cleanup_edges (display);
|
||||
}
|
||||
|
||||
if (display->grab_old_window_stacking != NULL)
|
||||
{
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Clearing out the old stack position, which was %p.\n",
|
||||
display->grab_old_window_stacking);
|
||||
g_list_free (display->grab_old_window_stacking);
|
||||
display->grab_old_window_stacking = NULL;
|
||||
}
|
||||
|
||||
if (display->grab_have_pointer)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
meta_backend_ungrab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp);
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Ungrabbing pointer with timestamp %u\n", timestamp);
|
||||
XIUngrabDevice (display->xdisplay, META_VIRTUAL_CORE_POINTER_ID, timestamp);
|
||||
}
|
||||
|
||||
if (display->grab_have_keyboard)
|
||||
{
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Ungrabbing all keys timestamp %u\n", timestamp);
|
||||
meta_window_ungrab_all_keys (display->grab_window, timestamp);
|
||||
if (display->grab_window)
|
||||
meta_window_ungrab_all_keys (display->grab_window, timestamp);
|
||||
else
|
||||
meta_screen_ungrab_all_keys (display->screen, timestamp);
|
||||
}
|
||||
|
||||
tracker = meta_cursor_tracker_get_for_screen (display->screen);
|
||||
meta_cursor_tracker_set_grab_cursor (tracker, NULL);
|
||||
meta_cursor_tracker_set_grab_cursor (display->screen->cursor_tracker, NULL);
|
||||
|
||||
display->grab_timestamp = 0;
|
||||
display->grab_window = NULL;
|
||||
display->grab_xwindow = None;
|
||||
display->grab_tile_mode = META_TILE_NONE;
|
||||
display->grab_tile_monitor_number = -1;
|
||||
display->grab_op = META_GRAB_OP_NONE;
|
||||
|
||||
if (display->grab_resize_popup)
|
||||
{
|
||||
meta_ui_resize_popup_free (display->grab_resize_popup);
|
||||
display->grab_resize_popup = NULL;
|
||||
}
|
||||
|
||||
if (display->grab_resize_timeout_id)
|
||||
{
|
||||
g_source_remove (display->grab_resize_timeout_id);
|
||||
@ -1962,10 +2179,8 @@ meta_change_button_grab (MetaDisplay *display,
|
||||
int button,
|
||||
int modmask)
|
||||
{
|
||||
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
|
||||
Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
|
||||
|
||||
unsigned int ignored_mask;
|
||||
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||
|
||||
@ -1973,6 +2188,13 @@ meta_change_button_grab (MetaDisplay *display,
|
||||
XISetMask (mask.mask, XI_ButtonRelease);
|
||||
XISetMask (mask.mask, XI_Motion);
|
||||
|
||||
meta_verbose ("%s 0x%lx sync = %d button = %d modmask 0x%x\n",
|
||||
grab ? "Grabbing" : "Ungrabbing",
|
||||
xwindow,
|
||||
sync, button, modmask);
|
||||
|
||||
meta_error_trap_push (display);
|
||||
|
||||
ignored_mask = 0;
|
||||
while (ignored_mask <= display->ignored_modifier_mask)
|
||||
{
|
||||
@ -1989,34 +2211,45 @@ meta_change_button_grab (MetaDisplay *display,
|
||||
|
||||
mods = (XIGrabModifiers) { modmask | ignored_mask, 0 };
|
||||
|
||||
if (meta_is_debugging ())
|
||||
meta_error_trap_push_with_return (display);
|
||||
|
||||
/* GrabModeSync means freeze until XAllowEvents */
|
||||
|
||||
if (grab)
|
||||
XIGrabButton (xdisplay,
|
||||
XIGrabButton (display->xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
button, xwindow, None,
|
||||
sync ? XIGrabModeSync : XIGrabModeAsync,
|
||||
XIGrabModeAsync, False,
|
||||
&mask, 1, &mods);
|
||||
else
|
||||
XIUngrabButton (xdisplay,
|
||||
XIUngrabButton (display->xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
button, xwindow, 1, &mods);
|
||||
|
||||
if (meta_is_debugging ())
|
||||
{
|
||||
int result;
|
||||
|
||||
result = meta_error_trap_pop_with_return (display);
|
||||
|
||||
if (result != Success)
|
||||
meta_verbose ("Failed to %s button %d with mask 0x%x for window 0x%lx error code %d\n",
|
||||
grab ? "grab" : "ungrab",
|
||||
button, modmask | ignored_mask, xwindow, result);
|
||||
}
|
||||
|
||||
++ignored_mask;
|
||||
}
|
||||
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
|
||||
void
|
||||
meta_display_grab_window_buttons (MetaDisplay *display,
|
||||
Window xwindow)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
|
||||
/* Do nothing under non-X11 backends */
|
||||
if (!META_IS_BACKEND_X11 (backend))
|
||||
return;
|
||||
|
||||
/* Grab Alt + button1 for moving window.
|
||||
* Grab Alt + button2 for resizing window.
|
||||
* Grab Alt + button3 for popping up window menu.
|
||||
@ -2067,12 +2300,6 @@ void
|
||||
meta_display_ungrab_window_buttons (MetaDisplay *display,
|
||||
Window xwindow)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
|
||||
/* Do nothing under non-X11 backends */
|
||||
if (!META_IS_BACKEND_X11 (backend))
|
||||
return;
|
||||
|
||||
gboolean debug;
|
||||
int i;
|
||||
|
||||
@ -2101,12 +2328,6 @@ void
|
||||
meta_display_grab_focus_window_button (MetaDisplay *display,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
|
||||
/* Do nothing under non-X11 backends */
|
||||
if (!META_IS_BACKEND_X11 (backend))
|
||||
return;
|
||||
|
||||
/* Grab button 1 for activating unfocused windows */
|
||||
meta_verbose ("Grabbing unfocused window buttons for %s\n", window->desc);
|
||||
|
||||
@ -2156,12 +2377,6 @@ void
|
||||
meta_display_ungrab_focus_window_button (MetaDisplay *display,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
|
||||
/* Do nothing under non-X11 backends */
|
||||
if (!META_IS_BACKEND_X11 (backend))
|
||||
return;
|
||||
|
||||
meta_verbose ("Ungrabbing unfocused window buttons for %s\n", window->desc);
|
||||
|
||||
if (!window->have_focus_click_grab)
|
||||
@ -2238,32 +2453,16 @@ meta_display_retheme_all (void)
|
||||
meta_display_queue_retheme_all_windows (meta_get_display ());
|
||||
}
|
||||
|
||||
static void
|
||||
set_cursor_theme (Display *xdisplay)
|
||||
void
|
||||
meta_display_set_cursor_theme (const char *theme,
|
||||
int size)
|
||||
{
|
||||
XcursorSetTheme (xdisplay, meta_prefs_get_cursor_theme ());
|
||||
XcursorSetDefaultSize (xdisplay, meta_prefs_get_cursor_size ());
|
||||
}
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
|
||||
static void
|
||||
update_cursor_theme (void)
|
||||
{
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
set_cursor_theme (display->xdisplay);
|
||||
XcursorSetTheme (display->xdisplay, theme);
|
||||
XcursorSetDefaultSize (display->xdisplay, size);
|
||||
|
||||
if (display->screen)
|
||||
meta_screen_update_cursor (display->screen);
|
||||
}
|
||||
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
if (META_IS_BACKEND_X11 (backend))
|
||||
{
|
||||
Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
|
||||
set_cursor_theme (xdisplay);
|
||||
}
|
||||
}
|
||||
meta_screen_update_cursor (display->screen);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2401,7 +2600,6 @@ meta_display_ping_window (MetaWindow *window,
|
||||
ping_data->ping_timeout_id = g_timeout_add (PING_TIMEOUT_DELAY,
|
||||
meta_display_ping_timeout,
|
||||
ping_data);
|
||||
g_source_set_name_by_id (ping_data->ping_timeout_id, "[mutter] meta_display_ping_timeout");
|
||||
|
||||
display->pending_pings = g_slist_prepend (display->pending_pings, ping_data);
|
||||
|
||||
@ -2883,6 +3081,7 @@ meta_display_devirtualize_modifiers (MetaDisplay *display,
|
||||
|
||||
static void
|
||||
update_window_grab_modifiers (MetaDisplay *display)
|
||||
|
||||
{
|
||||
MetaVirtualModifier virtual_mods;
|
||||
unsigned int mods;
|
||||
@ -2946,11 +3145,6 @@ prefs_changed_callback (MetaPreference pref,
|
||||
{
|
||||
meta_bell_set_audible (display, meta_prefs_bell_is_audible ());
|
||||
}
|
||||
else if (pref == META_PREF_CURSOR_THEME ||
|
||||
pref == META_PREF_CURSOR_SIZE)
|
||||
{
|
||||
update_cursor_theme ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -3193,11 +3387,13 @@ meta_display_get_damage_event_base (MetaDisplay *display)
|
||||
return display->damage_event_base;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SHAPE
|
||||
int
|
||||
meta_display_get_shape_event_base (MetaDisplay *display)
|
||||
{
|
||||
return display->shape_event_base;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* meta_display_clear_mouse_mode:
|
||||
@ -3213,10 +3409,3 @@ meta_display_clear_mouse_mode (MetaDisplay *display)
|
||||
{
|
||||
display->mouse_mode = FALSE;
|
||||
}
|
||||
|
||||
Cursor
|
||||
meta_display_create_x_cursor (MetaDisplay *display,
|
||||
MetaCursor cursor)
|
||||
{
|
||||
return meta_cursor_create_x_cursor (display->xdisplay, cursor);
|
||||
}
|
||||
|
@ -437,8 +437,6 @@ apply_edge_resistance (MetaWindow *window,
|
||||
g_timeout_add (timeout_length_ms,
|
||||
edge_resistance_timeout,
|
||||
resistance_data);
|
||||
g_source_set_name_by_id (resistance_data->timeout_id,
|
||||
"[mutter] edge_resistance_timeout");
|
||||
resistance_data->timeout_setup = TRUE;
|
||||
resistance_data->timeout_edge_pos = compare;
|
||||
resistance_data->timeout_over = FALSE;
|
||||
|
@ -55,6 +55,12 @@ meta_error_trap_pop (MetaDisplay *display)
|
||||
gdk_error_trap_pop_ignored ();
|
||||
}
|
||||
|
||||
void
|
||||
meta_error_trap_push_with_return (MetaDisplay *display)
|
||||
{
|
||||
gdk_error_trap_push ();
|
||||
}
|
||||
|
||||
int
|
||||
meta_error_trap_pop_with_return (MetaDisplay *display)
|
||||
{
|
||||
|
@ -25,20 +25,20 @@
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/extensions/Xdamage.h>
|
||||
#ifdef HAVE_SHAPE
|
||||
#include <X11/extensions/shape.h>
|
||||
#endif
|
||||
|
||||
#include <meta/errors.h>
|
||||
#include "display-private.h"
|
||||
#include "window-private.h"
|
||||
#include "bell.h"
|
||||
#include "workspace-private.h"
|
||||
#include "backends/meta-backend.h"
|
||||
#include "backends/x11/meta-idle-monitor-xsync.h"
|
||||
#include "backends/native/meta-idle-monitor-native.h"
|
||||
#include "backends/x11/meta-backend-x11.h"
|
||||
|
||||
#include "x11/window-x11.h"
|
||||
#include "x11/xprops.h"
|
||||
#include "wayland/meta-xwayland.h"
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
#include "meta-surface-actor-wayland.h"
|
||||
|
||||
@ -213,12 +213,14 @@ event_get_modified_window (MetaDisplay *display,
|
||||
return None;
|
||||
|
||||
default:
|
||||
#ifdef HAVE_SHAPE
|
||||
if (META_DISPLAY_HAS_SHAPE (display) &&
|
||||
event->type == (display->shape_event_base + ShapeNotify))
|
||||
{
|
||||
XShapeEvent *sev = (XShapeEvent*) event;
|
||||
return sev->window;
|
||||
}
|
||||
#endif
|
||||
|
||||
return None;
|
||||
}
|
||||
@ -348,6 +350,7 @@ stack_mode_to_string (int mode)
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
#ifdef HAVE_XSYNC
|
||||
G_GNUC_UNUSED static gint64
|
||||
sync_value_to_64 (const XSyncValue *value)
|
||||
{
|
||||
@ -374,6 +377,7 @@ alarm_state_to_string (XSyncAlarmState state)
|
||||
return "(unknown)";
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_XSYNC */
|
||||
|
||||
G_GNUC_UNUSED static void
|
||||
meta_spew_xi2_event (MetaDisplay *display,
|
||||
@ -607,6 +611,7 @@ meta_spew_core_event (MetaDisplay *display,
|
||||
name = "MappingNotify";
|
||||
break;
|
||||
default:
|
||||
#ifdef HAVE_XSYNC
|
||||
if (META_DISPLAY_HAS_XSYNC (display) &&
|
||||
event->type == (display->xsync_event_base + XSyncAlarmNotify))
|
||||
{
|
||||
@ -625,6 +630,8 @@ meta_spew_core_event (MetaDisplay *display,
|
||||
alarm_state_to_string (aevent->state));
|
||||
}
|
||||
else
|
||||
#endif /* HAVE_XSYNC */
|
||||
#ifdef HAVE_SHAPE
|
||||
if (META_DISPLAY_HAS_SHAPE (display) &&
|
||||
event->type == (display->shape_event_base + ShapeNotify))
|
||||
{
|
||||
@ -644,6 +651,7 @@ meta_spew_core_event (MetaDisplay *display,
|
||||
sev->shaped);
|
||||
}
|
||||
else
|
||||
#endif /* HAVE_SHAPE */
|
||||
{
|
||||
name = "(Unknown event)";
|
||||
extra = g_strdup_printf ("type: %d", event->xany.type);
|
||||
@ -851,24 +859,9 @@ handle_input_xevent (MetaDisplay *display,
|
||||
if (input_event == NULL)
|
||||
return FALSE;
|
||||
|
||||
switch (input_event->evtype)
|
||||
{
|
||||
case XI_Enter:
|
||||
case XI_Leave:
|
||||
case XI_FocusIn:
|
||||
case XI_FocusOut:
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
modified = xievent_get_modified_window (display, input_event);
|
||||
window = modified != None ? meta_display_lookup_x_window (display, modified) : NULL;
|
||||
|
||||
/* If this is an event for a GTK+ widget, let GTK+ handle it. */
|
||||
if (meta_ui_window_is_widget (display->screen->ui, modified))
|
||||
return FALSE;
|
||||
|
||||
switch (input_event->evtype)
|
||||
{
|
||||
case XI_Enter:
|
||||
@ -940,15 +933,12 @@ handle_input_xevent (MetaDisplay *display,
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
/* Don't send FocusIn / FocusOut to Clutter */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Don't eat events for GTK frames (we need to update the :hover state on buttons) */
|
||||
if (window && window->frame && modified == window->frame->xwindow)
|
||||
return FALSE;
|
||||
|
||||
/* Don't pass these events through to Clutter / GTK+ */
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1050,7 +1040,7 @@ convert_property (MetaDisplay *display,
|
||||
conversion_targets[2] = display->atom_TIMESTAMP;
|
||||
conversion_targets[3] = display->atom_VERSION;
|
||||
|
||||
meta_error_trap_push (display);
|
||||
meta_error_trap_push_with_return (display);
|
||||
if (target == display->atom_TARGETS)
|
||||
XChangeProperty (display->xdisplay, w, property,
|
||||
XA_ATOM, 32, PropModeReplace,
|
||||
@ -1125,7 +1115,7 @@ process_selection_request (MetaDisplay *display,
|
||||
unsigned long num, rest;
|
||||
unsigned char *data;
|
||||
|
||||
meta_error_trap_push (display);
|
||||
meta_error_trap_push_with_return (display);
|
||||
if (XGetWindowProperty (display->xdisplay,
|
||||
event->xselectionrequest.requestor,
|
||||
event->xselectionrequest.property, 0, 256, False,
|
||||
@ -1239,6 +1229,7 @@ handle_other_xevent (MetaDisplay *display,
|
||||
window = NULL;
|
||||
}
|
||||
|
||||
#ifdef HAVE_XSYNC
|
||||
if (META_DISPLAY_HAS_XSYNC (display) &&
|
||||
event->type == (display->xsync_event_base + XSyncAlarmNotify))
|
||||
{
|
||||
@ -1250,13 +1241,17 @@ handle_other_xevent (MetaDisplay *display,
|
||||
XSyncValue value = ((XSyncAlarmNotifyEvent*)event)->counter_value;
|
||||
gint64 new_counter_value;
|
||||
new_counter_value = XSyncValueLow32 (value) + ((gint64)XSyncValueHigh32 (value) << 32);
|
||||
meta_window_x11_update_sync_request_counter (alarm_window, new_counter_value);
|
||||
meta_window_update_sync_request_counter (alarm_window, new_counter_value);
|
||||
bypass_gtk = TRUE; /* GTK doesn't want to see this really */
|
||||
}
|
||||
else
|
||||
meta_idle_monitor_xsync_handle_xevent_all (event);
|
||||
|
||||
goto out;
|
||||
}
|
||||
#endif /* HAVE_XSYNC */
|
||||
|
||||
#ifdef HAVE_SHAPE
|
||||
if (META_DISPLAY_HAS_SHAPE (display) &&
|
||||
event->type == (display->shape_event_base + ShapeNotify))
|
||||
{
|
||||
@ -1281,6 +1276,7 @@ handle_other_xevent (MetaDisplay *display,
|
||||
|
||||
goto out;
|
||||
}
|
||||
#endif /* HAVE_SHAPE */
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
@ -1497,6 +1493,11 @@ handle_other_xevent (MetaDisplay *display,
|
||||
event->xproperty.atom ==
|
||||
display->atom__XKB_RULES_NAMES)
|
||||
reload_xkb_rules (display->screen);
|
||||
#if 0
|
||||
else if (event->xproperty.atom ==
|
||||
display->atom__NET_RESTACK_WINDOW)
|
||||
handle_net_restack_window (display, event);
|
||||
#endif
|
||||
|
||||
/* we just use this property as a sentinel to avoid
|
||||
* certain race conditions. See the comment for the
|
||||
@ -1510,6 +1511,21 @@ handle_other_xevent (MetaDisplay *display,
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SelectionClear:
|
||||
/* do this here instead of at end of function
|
||||
* so we can return
|
||||
*/
|
||||
|
||||
/* FIXME: Clearing display->current_time here makes no sense to
|
||||
* me; who put this here and why?
|
||||
*/
|
||||
display->current_time = CurrentTime;
|
||||
|
||||
process_selection_clear (display, event);
|
||||
/* Note that processing that may have resulted in
|
||||
* closing the display... so return right away.
|
||||
*/
|
||||
return FALSE;
|
||||
case SelectionRequest:
|
||||
process_selection_request (display, event);
|
||||
break;
|
||||
@ -1520,12 +1536,7 @@ handle_other_xevent (MetaDisplay *display,
|
||||
case ClientMessage:
|
||||
if (window)
|
||||
{
|
||||
if (event->xclient.message_type == display->atom_WL_SURFACE_ID)
|
||||
{
|
||||
guint32 surface_id = event->xclient.data.l[0];
|
||||
meta_xwayland_handle_wl_surface_id (window, surface_id);
|
||||
}
|
||||
else if (!frame_was_receiver)
|
||||
if (!frame_was_receiver)
|
||||
meta_window_x11_client_message (window, event);
|
||||
}
|
||||
else
|
||||
@ -1688,7 +1699,7 @@ grab_op_should_block_mouse_events (MetaGrabOp op)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case META_GRAB_OP_WAYLAND_POPUP:
|
||||
case META_GRAB_OP_WAYLAND_CLIENT:
|
||||
case META_GRAB_OP_COMPOSITOR:
|
||||
return TRUE;
|
||||
|
||||
@ -1730,19 +1741,28 @@ meta_display_handle_xevent (MetaDisplay *display,
|
||||
Window modified;
|
||||
gboolean bypass_compositor = FALSE, bypass_gtk = FALSE;
|
||||
XIEvent *input_event;
|
||||
MetaMonitorManager *monitor;
|
||||
|
||||
#if 0
|
||||
meta_spew_event (display, event);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STARTUP_NOTIFICATION
|
||||
if (sn_display_process_event (display->sn_display, event))
|
||||
{
|
||||
bypass_gtk = bypass_compositor = TRUE;
|
||||
goto out;
|
||||
}
|
||||
sn_display_process_event (display->sn_display, event);
|
||||
#endif
|
||||
|
||||
/* Intercept XRandR events early and don't attempt any
|
||||
processing for them. We still let them through to Gdk though,
|
||||
so it can update its own internal state.
|
||||
*/
|
||||
monitor = meta_monitor_manager_get ();
|
||||
if (meta_monitor_manager_handle_xevent (monitor, event))
|
||||
{
|
||||
bypass_compositor = TRUE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
display->current_time = event_get_time (display, event);
|
||||
display->monitor_cache_invalidated = TRUE;
|
||||
|
||||
if (display->focused_by_us &&
|
||||
@ -1818,17 +1838,6 @@ meta_display_handle_xevent (MetaDisplay *display,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (event->type == SelectionClear)
|
||||
{
|
||||
/* Do this here so we can return without any further
|
||||
* processing. */
|
||||
process_selection_clear (display, event);
|
||||
/* Note that processing that may have resulted in
|
||||
* closing the display... */
|
||||
bypass_gtk = bypass_compositor = TRUE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
if (!bypass_compositor)
|
||||
{
|
||||
@ -1838,7 +1847,7 @@ meta_display_handle_xevent (MetaDisplay *display,
|
||||
bypass_gtk = TRUE;
|
||||
}
|
||||
|
||||
display->current_time = event_get_time (display, event);
|
||||
display->current_time = CurrentTime;
|
||||
return bypass_gtk;
|
||||
}
|
||||
|
||||
@ -1850,10 +1859,8 @@ handle_idletime_for_event (const ClutterEvent *event)
|
||||
int device_id;
|
||||
|
||||
/* This is handled by XSync under X11. */
|
||||
#if defined(CLUTTER_WINDOWING_X11)
|
||||
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_X11))
|
||||
if (!meta_is_wayland_compositor ())
|
||||
return;
|
||||
#endif
|
||||
|
||||
device = clutter_event_get_device (event);
|
||||
if (device == NULL)
|
||||
@ -1916,17 +1923,6 @@ meta_display_handle_event (MetaDisplay *display,
|
||||
}
|
||||
}
|
||||
|
||||
if (display->grab_window == window &&
|
||||
meta_grab_op_is_moving_or_resizing (display->grab_op))
|
||||
{
|
||||
if (meta_window_handle_mouse_grab_op_event (window, event))
|
||||
{
|
||||
bypass_clutter = TRUE;
|
||||
bypass_wayland = TRUE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
@ -1935,7 +1931,24 @@ meta_display_handle_event (MetaDisplay *display,
|
||||
|
||||
display->overlay_key_only_pressed = FALSE;
|
||||
|
||||
if (window && display->grab_op == META_GRAB_OP_NONE)
|
||||
if ((window &&
|
||||
meta_grab_op_is_mouse (display->grab_op) &&
|
||||
(event->button.modifier_state & display->window_grab_modifiers) &&
|
||||
display->grab_button != (int) event->button.button &&
|
||||
display->grab_window == window) ||
|
||||
meta_grab_op_is_keyboard (display->grab_op))
|
||||
{
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Ending grab op %u on window %s due to button press\n",
|
||||
display->grab_op,
|
||||
(display->grab_window ?
|
||||
display->grab_window->desc :
|
||||
"none"));
|
||||
meta_display_end_grab_op (display, event->any.time);
|
||||
bypass_clutter = TRUE;
|
||||
bypass_wayland = TRUE;
|
||||
}
|
||||
else if (window && display->grab_op == META_GRAB_OP_NONE)
|
||||
{
|
||||
ClutterModifierType grab_mask;
|
||||
gboolean unmodified;
|
||||
@ -1996,16 +2009,8 @@ meta_display_handle_event (MetaDisplay *display,
|
||||
meta_verbose ("Allowing events time %u\n",
|
||||
(unsigned int)event->button.time);
|
||||
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
if (META_IS_BACKEND_X11 (backend))
|
||||
{
|
||||
Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
|
||||
XIAllowEvents (xdisplay, clutter_input_device_get_device_id (event->button.device),
|
||||
XIReplayDevice, event->button.time);
|
||||
}
|
||||
}
|
||||
|
||||
XIAllowEvents (display->xdisplay, clutter_input_device_get_device_id (event->button.device),
|
||||
XIReplayDevice, event->button.time);
|
||||
bypass_clutter = TRUE;
|
||||
}
|
||||
else if (fully_modified && (int) event->button.button == meta_prefs_get_mouse_button_resize ())
|
||||
@ -2092,12 +2097,31 @@ meta_display_handle_event (MetaDisplay *display,
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
if (grab_op_should_block_mouse_events (display->grab_op))
|
||||
break;
|
||||
|
||||
display->overlay_key_only_pressed = FALSE;
|
||||
|
||||
if (display->grab_window == window &&
|
||||
meta_grab_op_is_mouse (display->grab_op))
|
||||
{
|
||||
meta_window_handle_mouse_grab_op_event (window, event);
|
||||
bypass_clutter = TRUE;
|
||||
bypass_wayland = TRUE;
|
||||
}
|
||||
break;
|
||||
case CLUTTER_MOTION:
|
||||
if (grab_op_should_block_mouse_events (display->grab_op))
|
||||
break;
|
||||
|
||||
if (display->grab_window == window &&
|
||||
meta_grab_op_is_mouse (display->grab_op))
|
||||
{
|
||||
meta_window_handle_mouse_grab_op_event (window, event);
|
||||
bypass_clutter = TRUE;
|
||||
bypass_wayland = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case CLUTTER_KEY_PRESS:
|
||||
@ -2113,19 +2137,17 @@ meta_display_handle_event (MetaDisplay *display,
|
||||
bypass_clutter = TRUE;
|
||||
bypass_wayland = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
/* If the compositor has a grab, don't pass that through to Wayland */
|
||||
if (display->grab_op == META_GRAB_OP_COMPOSITOR)
|
||||
bypass_wayland = TRUE;
|
||||
|
||||
/* If a Wayland client has a grab, don't pass that through to Clutter */
|
||||
if (display->grab_op == META_GRAB_OP_WAYLAND_POPUP)
|
||||
if (display->grab_op == META_GRAB_OP_WAYLAND_CLIENT)
|
||||
bypass_clutter = TRUE;
|
||||
|
||||
if (compositor && !bypass_wayland)
|
||||
|
@ -27,6 +27,8 @@
|
||||
#include <meta/errors.h>
|
||||
#include "keybindings-private.h"
|
||||
|
||||
#include <X11/extensions/Xrender.h>
|
||||
|
||||
#define EVENT_MASK (SubstructureRedirectMask | \
|
||||
StructureNotifyMask | SubstructureNotifyMask | \
|
||||
ExposureMask | \
|
||||
|
@ -94,6 +94,10 @@ void meta_display_init_keys (MetaDisplay *display);
|
||||
void meta_display_shutdown_keys (MetaDisplay *display);
|
||||
void meta_screen_grab_keys (MetaScreen *screen);
|
||||
void meta_screen_ungrab_keys (MetaScreen *screen);
|
||||
gboolean meta_screen_grab_all_keys (MetaScreen *screen,
|
||||
guint32 timestamp);
|
||||
void meta_screen_ungrab_all_keys (MetaScreen *screen,
|
||||
guint32 timestamp);
|
||||
void meta_window_grab_keys (MetaWindow *window);
|
||||
void meta_window_ungrab_keys (MetaWindow *window);
|
||||
gboolean meta_window_grab_all_keys (MetaWindow *window,
|
||||
|
@ -41,23 +41,18 @@
|
||||
#include "screen-private.h"
|
||||
#include <meta/prefs.h>
|
||||
#include "util-private.h"
|
||||
#include "meta-accel-parse.h"
|
||||
|
||||
#include <X11/keysym.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <linux/input.h>
|
||||
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
#ifdef HAVE_XKB
|
||||
#include <X11/XKBlib.h>
|
||||
#endif
|
||||
|
||||
#include "wayland/meta-wayland.h"
|
||||
#include "backends/x11/meta-backend-x11.h"
|
||||
#include "backends/native/meta-backend-native.h"
|
||||
#include "meta-backend.h"
|
||||
|
||||
#define SCHEMA_COMMON_KEYBINDINGS "org.gnome.desktop.wm.keybindings"
|
||||
#define SCHEMA_MUTTER_KEYBINDINGS "org.gnome.mutter.keybindings"
|
||||
@ -187,6 +182,10 @@ reload_keymap (MetaDisplay *display)
|
||||
if (display->keymap)
|
||||
meta_XFree (display->keymap);
|
||||
|
||||
/* This is expensive to compute, so we'll lazily load if and when we first
|
||||
* need it */
|
||||
display->above_tab_keycode = 0;
|
||||
|
||||
display->keymap = XGetKeyboardMapping (display->xdisplay,
|
||||
display->min_keycode,
|
||||
display->max_keycode -
|
||||
@ -194,27 +193,24 @@ reload_keymap (MetaDisplay *display)
|
||||
&display->keysyms_per_keycode);
|
||||
}
|
||||
|
||||
static const char *
|
||||
keysym_name (xkb_keysym_t keysym)
|
||||
{
|
||||
static char name[32] = "";
|
||||
xkb_keysym_get_name (keysym, name, sizeof (name));
|
||||
return name;
|
||||
}
|
||||
|
||||
static void
|
||||
reload_modmap (MetaDisplay *display)
|
||||
{
|
||||
XModifierKeymap *modmap;
|
||||
int map_size;
|
||||
int i;
|
||||
int num_lock_mask = 0;
|
||||
int scroll_lock_mask = 0;
|
||||
|
||||
if (display->modmap)
|
||||
XFreeModifiermap (display->modmap);
|
||||
|
||||
modmap = XGetModifierMapping (display->xdisplay);
|
||||
display->modmap = modmap;
|
||||
|
||||
display->ignored_modifier_mask = 0;
|
||||
|
||||
/* Multiple bits may get set in each of these */
|
||||
display->num_lock_mask = 0;
|
||||
display->scroll_lock_mask = 0;
|
||||
display->meta_mask = 0;
|
||||
display->hyper_mask = 0;
|
||||
display->super_mask = 0;
|
||||
@ -242,37 +238,40 @@ reload_modmap (MetaDisplay *display)
|
||||
{
|
||||
if (syms[j] != 0)
|
||||
{
|
||||
const char *str;
|
||||
|
||||
str = XKeysymToString (syms[j]);
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"Keysym %s bound to modifier 0x%x\n",
|
||||
keysym_name (syms[j]),
|
||||
str ? str : "none",
|
||||
(1 << ( i / modmap->max_keypermod)));
|
||||
}
|
||||
|
||||
if (syms[j] == XKB_KEY_Num_Lock)
|
||||
if (syms[j] == XK_Num_Lock)
|
||||
{
|
||||
/* Mod1Mask is 1 << 3 for example, i.e. the
|
||||
* fourth modifier, i / keyspermod is the modifier
|
||||
* index
|
||||
*/
|
||||
|
||||
num_lock_mask |= (1 << ( i / modmap->max_keypermod));
|
||||
display->num_lock_mask |= (1 << ( i / modmap->max_keypermod));
|
||||
}
|
||||
else if (syms[j] == XKB_KEY_Scroll_Lock)
|
||||
else if (syms[j] == XK_Scroll_Lock)
|
||||
{
|
||||
scroll_lock_mask |= (1 << ( i / modmap->max_keypermod));
|
||||
display->scroll_lock_mask |= (1 << ( i / modmap->max_keypermod));
|
||||
}
|
||||
else if (syms[j] == XKB_KEY_Super_L ||
|
||||
syms[j] == XKB_KEY_Super_R)
|
||||
else if (syms[j] == XK_Super_L ||
|
||||
syms[j] == XK_Super_R)
|
||||
{
|
||||
display->super_mask |= (1 << ( i / modmap->max_keypermod));
|
||||
}
|
||||
else if (syms[j] == XKB_KEY_Hyper_L ||
|
||||
syms[j] == XKB_KEY_Hyper_R)
|
||||
else if (syms[j] == XK_Hyper_L ||
|
||||
syms[j] == XK_Hyper_R)
|
||||
{
|
||||
display->hyper_mask |= (1 << ( i / modmap->max_keypermod));
|
||||
}
|
||||
else if (syms[j] == XKB_KEY_Meta_L ||
|
||||
syms[j] == XKB_KEY_Meta_R)
|
||||
else if (syms[j] == XK_Meta_L ||
|
||||
syms[j] == XK_Meta_R)
|
||||
{
|
||||
display->meta_mask |= (1 << ( i / modmap->max_keypermod));
|
||||
}
|
||||
@ -284,20 +283,18 @@ reload_modmap (MetaDisplay *display)
|
||||
++i;
|
||||
}
|
||||
|
||||
display->ignored_modifier_mask = (num_lock_mask |
|
||||
scroll_lock_mask |
|
||||
display->ignored_modifier_mask = (display->num_lock_mask |
|
||||
display->scroll_lock_mask |
|
||||
LockMask);
|
||||
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"Ignoring modmask 0x%x num lock 0x%x scroll lock 0x%x hyper 0x%x super 0x%x meta 0x%x\n",
|
||||
display->ignored_modifier_mask,
|
||||
num_lock_mask,
|
||||
scroll_lock_mask,
|
||||
display->num_lock_mask,
|
||||
display->scroll_lock_mask,
|
||||
display->hyper_mask,
|
||||
display->super_mask,
|
||||
display->meta_mask);
|
||||
|
||||
XFreeModifiermap (modmap);
|
||||
}
|
||||
|
||||
/* Original code from gdk_x11_keymap_get_entries_for_keyval() in
|
||||
@ -313,14 +310,6 @@ get_keycodes_for_keysym (MetaDisplay *display,
|
||||
|
||||
retval = g_array_new (FALSE, FALSE, sizeof (int));
|
||||
|
||||
/* Special-case: Fake mutter keysym */
|
||||
if (keysym == META_KEY_ABOVE_TAB)
|
||||
{
|
||||
keycode = KEY_GRAVE + 8;
|
||||
g_array_append_val (retval, keycode);
|
||||
goto out;
|
||||
}
|
||||
|
||||
keycode = display->min_keycode;
|
||||
while (keycode <= display->max_keycode)
|
||||
{
|
||||
@ -338,31 +327,12 @@ get_keycodes_for_keysym (MetaDisplay *display,
|
||||
++keycode;
|
||||
}
|
||||
|
||||
out:
|
||||
n_keycodes = retval->len;
|
||||
*keycodes = (int*) g_array_free (retval, n_keycodes == 0 ? TRUE : FALSE);
|
||||
|
||||
return n_keycodes;
|
||||
}
|
||||
|
||||
static guint
|
||||
get_first_keycode_for_keysym (MetaDisplay *display,
|
||||
guint keysym)
|
||||
{
|
||||
int *keycodes;
|
||||
int n_keycodes;
|
||||
int keycode;
|
||||
|
||||
n_keycodes = get_keycodes_for_keysym (display, keysym, &keycodes);
|
||||
|
||||
if (n_keycodes > 0)
|
||||
keycode = keycodes[0];
|
||||
else
|
||||
keycode = 0;
|
||||
|
||||
g_free (keycodes);
|
||||
return keycode;
|
||||
}
|
||||
|
||||
static void
|
||||
reload_iso_next_group_combos (MetaDisplay *display)
|
||||
{
|
||||
@ -380,7 +350,7 @@ reload_iso_next_group_combos (MetaDisplay *display)
|
||||
if (iso_next_group_option == NULL)
|
||||
return;
|
||||
|
||||
n_keycodes = get_keycodes_for_keysym (display, XKB_KEY_ISO_Next_Group, &keycodes);
|
||||
n_keycodes = get_keycodes_for_keysym (display, XK_ISO_Next_Group, &keycodes);
|
||||
|
||||
if (g_str_equal (iso_next_group_option, "toggle") ||
|
||||
g_str_equal (iso_next_group_option, "lalt_toggle") ||
|
||||
@ -399,7 +369,7 @@ reload_iso_next_group_combos (MetaDisplay *display)
|
||||
|
||||
for (i = 0; i < n_keycodes; ++i)
|
||||
{
|
||||
combos[i].keysym = XKB_KEY_ISO_Next_Group;
|
||||
combos[i].keysym = XK_ISO_Next_Group;
|
||||
combos[i].keycode = keycodes[i];
|
||||
combos[i].modifiers = 0;
|
||||
}
|
||||
@ -412,7 +382,7 @@ reload_iso_next_group_combos (MetaDisplay *display)
|
||||
|
||||
for (i = 0; i < n_keycodes; ++i)
|
||||
{
|
||||
combos[i].keysym = XKB_KEY_ISO_Next_Group;
|
||||
combos[i].keysym = XK_ISO_Next_Group;
|
||||
combos[i].keycode = keycodes[i];
|
||||
combos[i].modifiers = ShiftMask;
|
||||
}
|
||||
@ -425,7 +395,7 @@ reload_iso_next_group_combos (MetaDisplay *display)
|
||||
|
||||
for (i = 0; i < n_keycodes; ++i)
|
||||
{
|
||||
combos[i].keysym = XKB_KEY_ISO_Next_Group;
|
||||
combos[i].keysym = XK_ISO_Next_Group;
|
||||
combos[i].keycode = keycodes[i];
|
||||
combos[i].modifiers = Mod1Mask;
|
||||
}
|
||||
@ -439,11 +409,11 @@ reload_iso_next_group_combos (MetaDisplay *display)
|
||||
|
||||
for (i = 0; i < n_keycodes; ++i)
|
||||
{
|
||||
combos[i].keysym = XKB_KEY_ISO_Next_Group;
|
||||
combos[i].keysym = XK_ISO_Next_Group;
|
||||
combos[i].keycode = keycodes[i];
|
||||
combos[i].modifiers = ShiftMask;
|
||||
|
||||
combos[i + n_keycodes].keysym = XKB_KEY_ISO_Next_Group;
|
||||
combos[i + n_keycodes].keysym = XK_ISO_Next_Group;
|
||||
combos[i + n_keycodes].keycode = keycodes[i];
|
||||
combos[i + n_keycodes].modifiers = ControlMask;
|
||||
}
|
||||
@ -455,11 +425,11 @@ reload_iso_next_group_combos (MetaDisplay *display)
|
||||
|
||||
for (i = 0; i < n_keycodes; ++i)
|
||||
{
|
||||
combos[i].keysym = XKB_KEY_ISO_Next_Group;
|
||||
combos[i].keysym = XK_ISO_Next_Group;
|
||||
combos[i].keycode = keycodes[i];
|
||||
combos[i].modifiers = Mod1Mask;
|
||||
|
||||
combos[i + n_keycodes].keysym = XKB_KEY_ISO_Next_Group;
|
||||
combos[i + n_keycodes].keysym = XK_ISO_Next_Group;
|
||||
combos[i + n_keycodes].keycode = keycodes[i];
|
||||
combos[i + n_keycodes].modifiers = ControlMask;
|
||||
}
|
||||
@ -472,11 +442,11 @@ reload_iso_next_group_combos (MetaDisplay *display)
|
||||
|
||||
for (i = 0; i < n_keycodes; ++i)
|
||||
{
|
||||
combos[i].keysym = XKB_KEY_ISO_Next_Group;
|
||||
combos[i].keysym = XK_ISO_Next_Group;
|
||||
combos[i].keycode = keycodes[i];
|
||||
combos[i].modifiers = Mod1Mask;
|
||||
|
||||
combos[i + n_keycodes].keysym = XKB_KEY_ISO_Next_Group;
|
||||
combos[i + n_keycodes].keysym = XK_ISO_Next_Group;
|
||||
combos[i + n_keycodes].keycode = keycodes[i];
|
||||
combos[i + n_keycodes].modifiers = ShiftMask;
|
||||
}
|
||||
@ -493,6 +463,16 @@ reload_iso_next_group_combos (MetaDisplay *display)
|
||||
display->iso_next_group_combos = combos;
|
||||
}
|
||||
|
||||
static guint
|
||||
keysym_to_keycode (MetaDisplay *display,
|
||||
guint keysym)
|
||||
{
|
||||
if (keysym == META_KEY_ABOVE_TAB)
|
||||
return meta_display_get_above_tab_keycode (display);
|
||||
else
|
||||
return XKeysymToKeycode (display->xdisplay, keysym);
|
||||
}
|
||||
|
||||
static void
|
||||
binding_reload_keycode_foreach (gpointer key,
|
||||
gpointer value,
|
||||
@ -502,7 +482,7 @@ binding_reload_keycode_foreach (gpointer key,
|
||||
MetaKeyBinding *binding = value;
|
||||
|
||||
if (binding->keysym)
|
||||
binding->keycode = get_first_keycode_for_keysym (display, binding->keysym);
|
||||
binding->keycode = keysym_to_keycode (display, binding->keysym);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -514,7 +494,7 @@ reload_keycodes (MetaDisplay *display)
|
||||
if (display->overlay_key_combo.keysym != 0)
|
||||
{
|
||||
display->overlay_key_combo.keycode =
|
||||
get_first_keycode_for_keysym (display, display->overlay_key_combo.keysym);
|
||||
keysym_to_keycode (display, display->overlay_key_combo.keysym);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -704,6 +684,8 @@ ungrab_key_bindings (MetaDisplay *display)
|
||||
GSList *tmp;
|
||||
GSList *windows;
|
||||
|
||||
meta_error_trap_push (display); /* for efficiency push outer trap */
|
||||
|
||||
meta_screen_ungrab_keys (display->screen);
|
||||
|
||||
windows = meta_display_list_windows (display, META_LIST_DEFAULT);
|
||||
@ -716,6 +698,7 @@ ungrab_key_bindings (MetaDisplay *display)
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
g_slist_free (windows);
|
||||
}
|
||||
@ -726,6 +709,8 @@ grab_key_bindings (MetaDisplay *display)
|
||||
GSList *tmp;
|
||||
GSList *windows;
|
||||
|
||||
meta_error_trap_push (display); /* for efficiency push outer trap */
|
||||
|
||||
meta_screen_grab_keys (display->screen);
|
||||
|
||||
windows = meta_display_list_windows (display, META_LIST_DEFAULT);
|
||||
@ -738,6 +723,7 @@ grab_key_bindings (MetaDisplay *display)
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
g_slist_free (windows);
|
||||
}
|
||||
@ -756,8 +742,7 @@ display_get_keybinding (MetaDisplay *display,
|
||||
}
|
||||
|
||||
static guint
|
||||
next_dynamic_keybinding_action (void)
|
||||
{
|
||||
next_dynamic_keybinding_action () {
|
||||
static guint num_dynamic_bindings = 0;
|
||||
return META_KEYBINDING_ACTION_LAST + (++num_dynamic_bindings);
|
||||
}
|
||||
@ -1006,15 +991,32 @@ bindings_changed_callback (MetaPreference pref,
|
||||
void
|
||||
meta_display_shutdown_keys (MetaDisplay *display)
|
||||
{
|
||||
/* Note that display->xdisplay is invalid in this function */
|
||||
|
||||
meta_prefs_remove_listener (bindings_changed_callback, display);
|
||||
|
||||
if (display->keymap)
|
||||
meta_XFree (display->keymap);
|
||||
|
||||
if (display->modmap)
|
||||
XFreeModifiermap (display->modmap);
|
||||
|
||||
g_hash_table_destroy (display->key_bindings_index);
|
||||
g_hash_table_destroy (display->key_bindings);
|
||||
}
|
||||
|
||||
static const char*
|
||||
keysym_name (int keysym)
|
||||
{
|
||||
const char *name;
|
||||
|
||||
name = XKeysymToString (keysym);
|
||||
if (name == NULL)
|
||||
name = "(unknown)";
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
/* Grab/ungrab, ignoring all annoying modifiers like NumLock etc. */
|
||||
static void
|
||||
meta_change_keygrab (MetaDisplay *display,
|
||||
@ -1032,9 +1034,6 @@ meta_change_keygrab (MetaDisplay *display,
|
||||
XISetMask (mask.mask, XI_KeyPress);
|
||||
XISetMask (mask.mask, XI_KeyRelease);
|
||||
|
||||
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
|
||||
Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
|
||||
|
||||
/* Grab keycode/modmask, together with
|
||||
* all combinations of ignored modifiers.
|
||||
* X provides no better way to do this.
|
||||
@ -1046,6 +1045,9 @@ meta_change_keygrab (MetaDisplay *display,
|
||||
keysym_name (keysym), keycode,
|
||||
modmask, xwindow);
|
||||
|
||||
/* efficiency, avoid so many XSync() */
|
||||
meta_error_trap_push (display);
|
||||
|
||||
ignored_mask = 0;
|
||||
while (ignored_mask <= display->ignored_modifier_mask)
|
||||
{
|
||||
@ -1062,19 +1064,40 @@ meta_change_keygrab (MetaDisplay *display,
|
||||
|
||||
mods = (XIGrabModifiers) { modmask | ignored_mask, 0 };
|
||||
|
||||
if (meta_is_debugging ())
|
||||
meta_error_trap_push_with_return (display);
|
||||
if (grab)
|
||||
XIGrabKeycode (xdisplay,
|
||||
XIGrabKeycode (display->xdisplay,
|
||||
META_VIRTUAL_CORE_KEYBOARD_ID,
|
||||
keycode, xwindow,
|
||||
XIGrabModeSync, XIGrabModeAsync,
|
||||
False, &mask, 1, &mods);
|
||||
else
|
||||
XIUngrabKeycode (xdisplay,
|
||||
XIUngrabKeycode (display->xdisplay,
|
||||
META_VIRTUAL_CORE_KEYBOARD_ID,
|
||||
keycode, xwindow, 1, &mods);
|
||||
|
||||
if (meta_is_debugging ())
|
||||
{
|
||||
int result;
|
||||
|
||||
result = meta_error_trap_pop_with_return (display);
|
||||
|
||||
if (grab && result != Success)
|
||||
{
|
||||
if (result == BadAccess)
|
||||
meta_warning ("Some other program is already using the key %s with modifiers %x as a binding\n", keysym_name (keysym), modmask | ignored_mask);
|
||||
else
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"Failed to grab key %s with modifiers %x\n",
|
||||
keysym_name (keysym), modmask | ignored_mask);
|
||||
}
|
||||
}
|
||||
|
||||
++ignored_mask;
|
||||
}
|
||||
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
@ -1117,7 +1140,9 @@ change_binding_keygrabs (MetaDisplay *display,
|
||||
data.binding_per_window = binding_per_window;
|
||||
data.grab = grab;
|
||||
|
||||
meta_error_trap_push (display);
|
||||
g_hash_table_foreach (display->key_bindings, change_keygrab_foreach, &data);
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1154,9 +1179,7 @@ meta_screen_change_keygrabs (MetaScreen *screen,
|
||||
void
|
||||
meta_screen_grab_keys (MetaScreen *screen)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
|
||||
if (!META_IS_BACKEND_X11 (backend))
|
||||
if (screen->all_keys_grabbed)
|
||||
return;
|
||||
|
||||
if (screen->keys_grabbed)
|
||||
@ -1189,11 +1212,6 @@ meta_window_change_keygrabs (MetaWindow *window,
|
||||
void
|
||||
meta_window_grab_keys (MetaWindow *window)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
|
||||
if (!META_IS_BACKEND_X11 (backend))
|
||||
return;
|
||||
|
||||
if (window->all_keys_grabbed)
|
||||
return;
|
||||
|
||||
@ -1266,7 +1284,7 @@ meta_display_grab_accelerator (MetaDisplay *display,
|
||||
guint mask = 0;
|
||||
MetaVirtualModifier modifiers = 0;
|
||||
|
||||
if (!meta_parse_accelerator (accelerator, &keysym, &keycode, &modifiers))
|
||||
if (!meta_ui_parse_accelerator (accelerator, &keysym, &keycode, &modifiers))
|
||||
{
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"Failed to parse accelerator\n");
|
||||
@ -1276,7 +1294,7 @@ meta_display_grab_accelerator (MetaDisplay *display,
|
||||
}
|
||||
|
||||
meta_display_devirtualize_modifiers (display, modifiers, &mask);
|
||||
keycode = get_first_keycode_for_keysym (display, keysym);
|
||||
keycode = keysym_to_keycode (display, keysym);
|
||||
|
||||
if (keycode == 0)
|
||||
return META_KEYBINDING_ACTION_NONE;
|
||||
@ -1328,7 +1346,7 @@ meta_display_ungrab_accelerator (MetaDisplay *display,
|
||||
return FALSE;
|
||||
|
||||
meta_display_devirtualize_modifiers (display, grab->combo->modifiers, &mask);
|
||||
keycode = get_first_keycode_for_keysym (display, grab->combo->keysym);
|
||||
keycode = keysym_to_keycode (display, grab->combo->keysym);
|
||||
|
||||
binding = display_get_keybinding (display, keycode, mask);
|
||||
if (binding)
|
||||
@ -1352,12 +1370,35 @@ meta_display_ungrab_accelerator (MetaDisplay *display,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
static const char*
|
||||
grab_status_to_string (int status)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case AlreadyGrabbed:
|
||||
return "AlreadyGrabbed";
|
||||
case GrabSuccess:
|
||||
return "GrabSuccess";
|
||||
case GrabNotViewable:
|
||||
return "GrabNotViewable";
|
||||
case GrabFrozen:
|
||||
return "GrabFrozen";
|
||||
case GrabInvalidTime:
|
||||
return "GrabInvalidTime";
|
||||
default:
|
||||
return "(unknown)";
|
||||
}
|
||||
}
|
||||
#endif /* WITH_VERBOSE_MODE */
|
||||
|
||||
static gboolean
|
||||
grab_keyboard (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
guint32 timestamp,
|
||||
int grab_mode)
|
||||
{
|
||||
int result;
|
||||
int grab_status;
|
||||
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
@ -1369,9 +1410,7 @@ grab_keyboard (MetaDisplay *display,
|
||||
/* Grab the keyboard, so we get key releases and all key
|
||||
* presses
|
||||
*/
|
||||
|
||||
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
|
||||
Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
|
||||
meta_error_trap_push_with_return (display);
|
||||
|
||||
/* Strictly, we only need to set grab_mode on the keyboard device
|
||||
* while the pointer should always be XIGrabModeAsync. Unfortunately
|
||||
@ -1382,7 +1421,7 @@ grab_keyboard (MetaDisplay *display,
|
||||
*
|
||||
* http://cgit.freedesktop.org/xorg/xserver/commit/?id=9003399708936481083424b4ff8f18a16b88b7b3
|
||||
*/
|
||||
grab_status = XIGrabDevice (xdisplay,
|
||||
grab_status = XIGrabDevice (display->xdisplay,
|
||||
META_VIRTUAL_CORE_KEYBOARD_ID,
|
||||
xwindow,
|
||||
timestamp,
|
||||
@ -1391,16 +1430,82 @@ grab_keyboard (MetaDisplay *display,
|
||||
False, /* owner_events */
|
||||
&mask);
|
||||
|
||||
return (grab_status == Success);
|
||||
if (grab_status != Success)
|
||||
{
|
||||
meta_error_trap_pop_with_return (display);
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"XIGrabDevice() returned failure status %s time %u\n",
|
||||
grab_status_to_string (grab_status),
|
||||
timestamp);
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = meta_error_trap_pop_with_return (display);
|
||||
if (result != Success)
|
||||
{
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"XIGrabDevice() resulted in an error\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
meta_topic (META_DEBUG_KEYBINDINGS, "Grabbed all keys\n");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
ungrab_keyboard (MetaDisplay *display, guint32 timestamp)
|
||||
{
|
||||
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
|
||||
Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
|
||||
meta_error_trap_push (display);
|
||||
|
||||
XIUngrabDevice (xdisplay, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"Ungrabbing keyboard with timestamp %u\n",
|
||||
timestamp);
|
||||
XIUngrabDevice (display->xdisplay, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_screen_grab_all_keys (MetaScreen *screen, guint32 timestamp)
|
||||
{
|
||||
gboolean retval;
|
||||
|
||||
if (screen->all_keys_grabbed)
|
||||
return FALSE;
|
||||
|
||||
if (screen->keys_grabbed)
|
||||
meta_screen_ungrab_keys (screen);
|
||||
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"Grabbing all keys on RootWindow\n");
|
||||
retval = grab_keyboard (screen->display, screen->xroot, timestamp, XIGrabModeAsync);
|
||||
if (retval)
|
||||
{
|
||||
screen->all_keys_grabbed = TRUE;
|
||||
g_object_notify (G_OBJECT (screen), "keyboard-grabbed");
|
||||
}
|
||||
else
|
||||
meta_screen_grab_keys (screen);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_ungrab_all_keys (MetaScreen *screen, guint32 timestamp)
|
||||
{
|
||||
if (screen->all_keys_grabbed)
|
||||
{
|
||||
ungrab_keyboard (screen->display, timestamp);
|
||||
|
||||
screen->all_keys_grabbed = FALSE;
|
||||
screen->keys_grabbed = FALSE;
|
||||
|
||||
/* Re-establish our standard bindings */
|
||||
meta_screen_grab_keys (screen);
|
||||
g_object_notify (G_OBJECT (screen), "keyboard-grabbed");
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
@ -1409,9 +1514,9 @@ meta_window_grab_all_keys (MetaWindow *window,
|
||||
{
|
||||
Window grabwindow;
|
||||
gboolean retval;
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
|
||||
if (!META_IS_BACKEND_X11 (backend))
|
||||
/* We don't need to grab Wayland clients */
|
||||
if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
|
||||
return TRUE;
|
||||
|
||||
if (window->all_keys_grabbed)
|
||||
@ -1474,45 +1579,40 @@ meta_display_ungrab_keyboard (MetaDisplay *display, guint32 timestamp)
|
||||
void
|
||||
meta_display_unfreeze_keyboard (MetaDisplay *display, guint32 timestamp)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
|
||||
if (!META_IS_BACKEND_X11 (backend))
|
||||
return;
|
||||
|
||||
Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
|
||||
|
||||
XIAllowEvents (xdisplay, META_VIRTUAL_CORE_KEYBOARD_ID,
|
||||
meta_error_trap_push (display);
|
||||
XIAllowEvents (display->xdisplay, META_VIRTUAL_CORE_KEYBOARD_ID,
|
||||
XIAsyncDevice, timestamp);
|
||||
/* We shouldn't need to unfreeze the pointer device here, however we
|
||||
* have to, due to the workaround we do in grab_keyboard().
|
||||
*/
|
||||
XIAllowEvents (xdisplay, META_VIRTUAL_CORE_POINTER_ID,
|
||||
XIAllowEvents (display->xdisplay, META_VIRTUAL_CORE_POINTER_ID,
|
||||
XIAsyncDevice, timestamp);
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_modifier (xkb_keysym_t keysym)
|
||||
is_modifier (MetaDisplay *display,
|
||||
unsigned int keycode)
|
||||
{
|
||||
switch (keysym)
|
||||
int i;
|
||||
int map_size;
|
||||
gboolean retval = FALSE;
|
||||
|
||||
g_assert (display->modmap);
|
||||
|
||||
map_size = 8 * display->modmap->max_keypermod;
|
||||
i = 0;
|
||||
while (i < map_size)
|
||||
{
|
||||
case XKB_KEY_Shift_L:
|
||||
case XKB_KEY_Shift_R:
|
||||
case XKB_KEY_Control_L:
|
||||
case XKB_KEY_Control_R:
|
||||
case XKB_KEY_Caps_Lock:
|
||||
case XKB_KEY_Shift_Lock:
|
||||
case XKB_KEY_Meta_L:
|
||||
case XKB_KEY_Meta_R:
|
||||
case XKB_KEY_Alt_L:
|
||||
case XKB_KEY_Alt_R:
|
||||
case XKB_KEY_Super_L:
|
||||
case XKB_KEY_Super_R:
|
||||
case XKB_KEY_Hyper_L:
|
||||
case XKB_KEY_Hyper_R:
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
if (keycode == display->modmap->modifiermap[i])
|
||||
{
|
||||
retval = TRUE;
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1593,13 +1693,6 @@ process_overlay_key (MetaDisplay *display,
|
||||
ClutterKeyEvent *event,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
|
||||
if (!META_IS_BACKEND_X11 (backend))
|
||||
return FALSE;
|
||||
|
||||
Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
|
||||
|
||||
if (display->overlay_key_only_pressed)
|
||||
{
|
||||
if (event->hardware_keycode != (int)display->overlay_key_combo.keycode)
|
||||
@ -1624,7 +1717,7 @@ process_overlay_key (MetaDisplay *display,
|
||||
* binding, we unfreeze the keyboard but keep the grab
|
||||
* (this is important for something like cycling
|
||||
* windows */
|
||||
XIAllowEvents (xdisplay,
|
||||
XIAllowEvents (display->xdisplay,
|
||||
clutter_input_device_get_device_id (event->device),
|
||||
XIAsyncDevice, event->time);
|
||||
}
|
||||
@ -1632,7 +1725,7 @@ process_overlay_key (MetaDisplay *display,
|
||||
{
|
||||
/* Replay the event so it gets delivered to our
|
||||
* per-window key bindings or to the application */
|
||||
XIAllowEvents (xdisplay,
|
||||
XIAllowEvents (display->xdisplay,
|
||||
clutter_input_device_get_device_id (event->device),
|
||||
XIReplayDevice, event->time);
|
||||
}
|
||||
@ -1645,13 +1738,13 @@ process_overlay_key (MetaDisplay *display,
|
||||
|
||||
/* We want to unfreeze events, but keep the grab so that if the user
|
||||
* starts typing into the overlay we get all the keys */
|
||||
XIAllowEvents (xdisplay,
|
||||
XIAllowEvents (display->xdisplay,
|
||||
clutter_input_device_get_device_id (event->device),
|
||||
XIAsyncDevice, event->time);
|
||||
|
||||
binding = display_get_keybinding (display,
|
||||
display->overlay_key_combo.keycode,
|
||||
0);
|
||||
display->grab_mask);
|
||||
if (binding &&
|
||||
meta_compositor_filter_keybinding (display->compositor, binding))
|
||||
return TRUE;
|
||||
@ -1671,7 +1764,7 @@ process_overlay_key (MetaDisplay *display,
|
||||
*
|
||||
* https://bugzilla.gnome.org/show_bug.cgi?id=666101
|
||||
*/
|
||||
XIAllowEvents (xdisplay,
|
||||
XIAllowEvents (display->xdisplay,
|
||||
clutter_input_device_get_device_id (event->device),
|
||||
XIAsyncDevice, event->time);
|
||||
}
|
||||
@ -1684,7 +1777,7 @@ process_overlay_key (MetaDisplay *display,
|
||||
display->overlay_key_only_pressed = TRUE;
|
||||
/* We keep the keyboard frozen - this allows us to use ReplayKeyboard
|
||||
* on the next event if it's not the release of the overlay key */
|
||||
XIAllowEvents (xdisplay,
|
||||
XIAllowEvents (display->xdisplay,
|
||||
clutter_input_device_get_device_id (event->device),
|
||||
XISyncDevice, event->time);
|
||||
|
||||
@ -1716,7 +1809,9 @@ process_iso_next_group (MetaDisplay *display,
|
||||
remain frozen. It's the signal handler's responsibility
|
||||
to unfreeze it. */
|
||||
if (!meta_display_modifiers_accelerator_activate (display))
|
||||
meta_display_unfreeze_keyboard (display, event->time);
|
||||
XIAllowEvents (display->xdisplay,
|
||||
clutter_input_device_get_device_id (event->device),
|
||||
XIAsyncDevice, event->time);
|
||||
activate = TRUE;
|
||||
break;
|
||||
}
|
||||
@ -1753,7 +1848,7 @@ meta_display_process_key_event (MetaDisplay *display,
|
||||
|
||||
screen = display->screen;
|
||||
|
||||
all_keys_grabbed = window ? window->all_keys_grabbed : FALSE;
|
||||
all_keys_grabbed = window ? window->all_keys_grabbed : screen->all_keys_grabbed;
|
||||
if (!all_keys_grabbed)
|
||||
{
|
||||
handled = process_overlay_key (display, screen, event, window);
|
||||
@ -1765,16 +1860,9 @@ meta_display_process_key_event (MetaDisplay *display,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
if (META_IS_BACKEND_X11 (backend))
|
||||
{
|
||||
Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
|
||||
XIAllowEvents (xdisplay,
|
||||
clutter_input_device_get_device_id (event->device),
|
||||
XIAsyncDevice, event->time);
|
||||
}
|
||||
}
|
||||
XIAllowEvents (display->xdisplay,
|
||||
clutter_input_device_get_device_id (event->device),
|
||||
XIAsyncDevice, event->time);
|
||||
|
||||
keep_grab = TRUE;
|
||||
if (all_keys_grabbed)
|
||||
@ -1902,7 +1990,7 @@ process_keyboard_move_grab (MetaDisplay *display,
|
||||
return TRUE;
|
||||
|
||||
/* don't end grab on modifier key presses */
|
||||
if (is_modifier (event->keyval))
|
||||
if (is_modifier (display, event->hardware_keycode))
|
||||
return TRUE;
|
||||
|
||||
meta_window_get_position (window, &x, &y);
|
||||
@ -2144,7 +2232,7 @@ process_keyboard_resize_grab (MetaDisplay *display,
|
||||
return TRUE;
|
||||
|
||||
/* don't end grab on modifier key presses */
|
||||
if (is_modifier (event->keyval))
|
||||
if (is_modifier (display, event->hardware_keycode))
|
||||
return TRUE;
|
||||
|
||||
if (event->keyval == CLUTTER_KEY_Escape)
|
||||
@ -2358,19 +2446,6 @@ process_keyboard_resize_grab (MetaDisplay *display,
|
||||
return handled;
|
||||
}
|
||||
|
||||
static void
|
||||
handle_switch_to_last_workspace (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
MetaWindow *event_window,
|
||||
ClutterKeyEvent *event,
|
||||
MetaKeyBinding *binding,
|
||||
gpointer dummy)
|
||||
{
|
||||
gint target = meta_screen_get_n_workspaces(screen) - 1;
|
||||
MetaWorkspace *workspace = meta_screen_get_workspace_by_index (screen, target);
|
||||
meta_workspace_activate (workspace, event->time);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_switch_to_workspace (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
@ -2382,19 +2457,7 @@ handle_switch_to_workspace (MetaDisplay *display,
|
||||
gint which = binding->handler->data;
|
||||
MetaWorkspace *workspace;
|
||||
|
||||
if (which < 0)
|
||||
{
|
||||
/* Negative workspace numbers are directions with respect to the
|
||||
* current workspace.
|
||||
*/
|
||||
|
||||
workspace = meta_workspace_get_neighbor (screen->active_workspace,
|
||||
which);
|
||||
}
|
||||
else
|
||||
{
|
||||
workspace = meta_screen_get_workspace_by_index (screen, which);
|
||||
}
|
||||
workspace = meta_screen_get_workspace_by_index (screen, which);
|
||||
|
||||
if (workspace)
|
||||
{
|
||||
@ -2955,26 +3018,6 @@ handle_toggle_on_all_workspaces (MetaDisplay *display,
|
||||
meta_window_stick (window);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_move_to_workspace_last (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
MetaWindow *window,
|
||||
ClutterKeyEvent *event,
|
||||
MetaKeyBinding *binding,
|
||||
gpointer dummy)
|
||||
{
|
||||
gint which;
|
||||
MetaWorkspace *workspace;
|
||||
|
||||
if (window->always_sticky)
|
||||
return;
|
||||
|
||||
which = meta_screen_get_n_workspaces (screen) - 1;
|
||||
workspace = meta_screen_get_workspace_by_index (screen, which);
|
||||
meta_window_change_workspace (window, workspace);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
handle_move_to_workspace (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
@ -3269,36 +3312,28 @@ init_builtin_key_bindings (MetaDisplay *display)
|
||||
common_keybindings,
|
||||
META_KEY_BINDING_NONE,
|
||||
META_KEYBINDING_ACTION_WORKSPACE_LEFT,
|
||||
handle_switch_to_workspace, META_MOTION_LEFT);
|
||||
NULL, 0);
|
||||
|
||||
add_builtin_keybinding (display,
|
||||
"switch-to-workspace-right",
|
||||
common_keybindings,
|
||||
META_KEY_BINDING_NONE,
|
||||
META_KEYBINDING_ACTION_WORKSPACE_RIGHT,
|
||||
handle_switch_to_workspace, META_MOTION_RIGHT);
|
||||
NULL, 0);
|
||||
|
||||
add_builtin_keybinding (display,
|
||||
"switch-to-workspace-up",
|
||||
common_keybindings,
|
||||
META_KEY_BINDING_NONE,
|
||||
META_KEYBINDING_ACTION_WORKSPACE_UP,
|
||||
handle_switch_to_workspace, META_MOTION_UP);
|
||||
NULL, 0);
|
||||
|
||||
add_builtin_keybinding (display,
|
||||
"switch-to-workspace-down",
|
||||
common_keybindings,
|
||||
META_KEY_BINDING_NONE,
|
||||
META_KEYBINDING_ACTION_WORKSPACE_DOWN,
|
||||
handle_switch_to_workspace, META_MOTION_DOWN);
|
||||
|
||||
add_builtin_keybinding (display,
|
||||
"switch-to-workspace-last",
|
||||
common_keybindings,
|
||||
META_KEY_BINDING_NONE,
|
||||
META_KEYBINDING_ACTION_WORKSPACE_LAST,
|
||||
handle_switch_to_last_workspace, 0);
|
||||
|
||||
NULL, 0);
|
||||
|
||||
|
||||
/* The ones which have inverses. These can't be bound to any keystroke
|
||||
@ -3681,13 +3716,6 @@ init_builtin_key_bindings (MetaDisplay *display)
|
||||
META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_12,
|
||||
handle_move_to_workspace, 11);
|
||||
|
||||
add_builtin_keybinding (display,
|
||||
"move-to-workspace-last",
|
||||
common_keybindings,
|
||||
META_KEY_BINDING_PER_WINDOW,
|
||||
META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_LAST,
|
||||
handle_move_to_workspace_last, 0);
|
||||
|
||||
add_builtin_keybinding (display,
|
||||
"move-to-workspace-left",
|
||||
common_keybindings,
|
||||
@ -3862,9 +3890,12 @@ meta_display_init_keys (MetaDisplay *display)
|
||||
/* Keybindings */
|
||||
display->keymap = NULL;
|
||||
display->keysyms_per_keycode = 0;
|
||||
display->modmap = NULL;
|
||||
display->min_keycode = 0;
|
||||
display->max_keycode = 0;
|
||||
display->ignored_modifier_mask = 0;
|
||||
display->num_lock_mask = 0;
|
||||
display->scroll_lock_mask = 0;
|
||||
display->hyper_mask = 0;
|
||||
display->super_mask = 0;
|
||||
display->meta_mask = 0;
|
||||
|
@ -125,6 +125,16 @@ log_handler (const gchar *log_domain,
|
||||
static void
|
||||
meta_print_compilation_info (void)
|
||||
{
|
||||
#ifdef HAVE_SHAPE
|
||||
meta_verbose ("Compiled with shape extension\n");
|
||||
#else
|
||||
meta_verbose ("Compiled without shape extension\n");
|
||||
#endif
|
||||
#ifdef HAVE_XSYNC
|
||||
meta_verbose ("Compiled with sync extension\n");
|
||||
#else
|
||||
meta_verbose ("Compiled without sync extension\n");
|
||||
#endif
|
||||
#ifdef HAVE_RANDR
|
||||
meta_verbose ("Compiled with randr extension\n");
|
||||
#else
|
||||
@ -544,6 +554,11 @@ prefs_changed_callback (MetaPreference pref,
|
||||
meta_display_retheme_all ();
|
||||
break;
|
||||
|
||||
case META_PREF_CURSOR_THEME:
|
||||
case META_PREF_CURSOR_SIZE:
|
||||
meta_display_set_cursor_theme (meta_prefs_get_cursor_theme (),
|
||||
meta_prefs_get_cursor_size ());
|
||||
break;
|
||||
default:
|
||||
/* handled elsewhere or otherwise */
|
||||
break;
|
||||
|
@ -1,356 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "meta-accel-parse.h"
|
||||
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* This is copied from GTK+ and modified to work with mutter's
|
||||
* internal structures. Originating code comes from gtk/gtkaccelgroup.c
|
||||
*/
|
||||
|
||||
static inline gboolean
|
||||
is_alt (const gchar *string)
|
||||
{
|
||||
return ((string[0] == '<') &&
|
||||
(string[1] == 'a' || string[1] == 'A') &&
|
||||
(string[2] == 'l' || string[2] == 'L') &&
|
||||
(string[3] == 't' || string[3] == 'T') &&
|
||||
(string[4] == '>'));
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
is_ctl (const gchar *string)
|
||||
{
|
||||
return ((string[0] == '<') &&
|
||||
(string[1] == 'c' || string[1] == 'C') &&
|
||||
(string[2] == 't' || string[2] == 'T') &&
|
||||
(string[3] == 'l' || string[3] == 'L') &&
|
||||
(string[4] == '>'));
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
is_modx (const gchar *string)
|
||||
{
|
||||
return ((string[0] == '<') &&
|
||||
(string[1] == 'm' || string[1] == 'M') &&
|
||||
(string[2] == 'o' || string[2] == 'O') &&
|
||||
(string[3] == 'd' || string[3] == 'D') &&
|
||||
(string[4] >= '1' && string[4] <= '5') &&
|
||||
(string[5] == '>'));
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
is_ctrl (const gchar *string)
|
||||
{
|
||||
return ((string[0] == '<') &&
|
||||
(string[1] == 'c' || string[1] == 'C') &&
|
||||
(string[2] == 't' || string[2] == 'T') &&
|
||||
(string[3] == 'r' || string[3] == 'R') &&
|
||||
(string[4] == 'l' || string[4] == 'L') &&
|
||||
(string[5] == '>'));
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
is_shft (const gchar *string)
|
||||
{
|
||||
return ((string[0] == '<') &&
|
||||
(string[1] == 's' || string[1] == 'S') &&
|
||||
(string[2] == 'h' || string[2] == 'H') &&
|
||||
(string[3] == 'f' || string[3] == 'F') &&
|
||||
(string[4] == 't' || string[4] == 'T') &&
|
||||
(string[5] == '>'));
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
is_shift (const gchar *string)
|
||||
{
|
||||
return ((string[0] == '<') &&
|
||||
(string[1] == 's' || string[1] == 'S') &&
|
||||
(string[2] == 'h' || string[2] == 'H') &&
|
||||
(string[3] == 'i' || string[3] == 'I') &&
|
||||
(string[4] == 'f' || string[4] == 'F') &&
|
||||
(string[5] == 't' || string[5] == 'T') &&
|
||||
(string[6] == '>'));
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
is_control (const gchar *string)
|
||||
{
|
||||
return ((string[0] == '<') &&
|
||||
(string[1] == 'c' || string[1] == 'C') &&
|
||||
(string[2] == 'o' || string[2] == 'O') &&
|
||||
(string[3] == 'n' || string[3] == 'N') &&
|
||||
(string[4] == 't' || string[4] == 'T') &&
|
||||
(string[5] == 'r' || string[5] == 'R') &&
|
||||
(string[6] == 'o' || string[6] == 'O') &&
|
||||
(string[7] == 'l' || string[7] == 'L') &&
|
||||
(string[8] == '>'));
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
is_meta (const gchar *string)
|
||||
{
|
||||
return ((string[0] == '<') &&
|
||||
(string[1] == 'm' || string[1] == 'M') &&
|
||||
(string[2] == 'e' || string[2] == 'E') &&
|
||||
(string[3] == 't' || string[3] == 'T') &&
|
||||
(string[4] == 'a' || string[4] == 'A') &&
|
||||
(string[5] == '>'));
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
is_super (const gchar *string)
|
||||
{
|
||||
return ((string[0] == '<') &&
|
||||
(string[1] == 's' || string[1] == 'S') &&
|
||||
(string[2] == 'u' || string[2] == 'U') &&
|
||||
(string[3] == 'p' || string[3] == 'P') &&
|
||||
(string[4] == 'e' || string[4] == 'E') &&
|
||||
(string[5] == 'r' || string[5] == 'R') &&
|
||||
(string[6] == '>'));
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
is_hyper (const gchar *string)
|
||||
{
|
||||
return ((string[0] == '<') &&
|
||||
(string[1] == 'h' || string[1] == 'H') &&
|
||||
(string[2] == 'y' || string[2] == 'Y') &&
|
||||
(string[3] == 'p' || string[3] == 'P') &&
|
||||
(string[4] == 'e' || string[4] == 'E') &&
|
||||
(string[5] == 'r' || string[5] == 'R') &&
|
||||
(string[6] == '>'));
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
is_primary (const gchar *string)
|
||||
{
|
||||
return ((string[0] == '<') &&
|
||||
(string[1] == 'p' || string[1] == 'P') &&
|
||||
(string[2] == 'r' || string[2] == 'R') &&
|
||||
(string[3] == 'i' || string[3] == 'I') &&
|
||||
(string[4] == 'm' || string[4] == 'M') &&
|
||||
(string[5] == 'a' || string[5] == 'A') &&
|
||||
(string[6] == 'r' || string[6] == 'R') &&
|
||||
(string[7] == 'y' || string[7] == 'Y') &&
|
||||
(string[8] == '>'));
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
is_keycode (const gchar *string)
|
||||
{
|
||||
return (string[0] == '0' &&
|
||||
string[1] == 'x' &&
|
||||
g_ascii_isxdigit (string[2]) &&
|
||||
g_ascii_isxdigit (string[3]));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
accelerator_parse (const gchar *accelerator,
|
||||
guint *accelerator_key,
|
||||
guint *accelerator_keycode,
|
||||
MetaVirtualModifier *accelerator_mods)
|
||||
{
|
||||
gboolean error = FALSE;
|
||||
guint keyval, keycode;
|
||||
MetaVirtualModifier mods;
|
||||
gint len;
|
||||
|
||||
if (accelerator_key)
|
||||
*accelerator_key = 0;
|
||||
if (accelerator_keycode)
|
||||
*accelerator_keycode = 0;
|
||||
if (accelerator_mods)
|
||||
*accelerator_mods = 0;
|
||||
|
||||
if (accelerator == NULL)
|
||||
{
|
||||
error = TRUE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
keyval = 0;
|
||||
keycode = 0;
|
||||
mods = 0;
|
||||
len = strlen (accelerator);
|
||||
while (len)
|
||||
{
|
||||
if (*accelerator == '<')
|
||||
{
|
||||
if (len >= 9 && is_primary (accelerator))
|
||||
{
|
||||
/* Primary is treated the same as Control */
|
||||
accelerator += 9;
|
||||
len -= 9;
|
||||
mods |= META_VIRTUAL_CONTROL_MASK;
|
||||
}
|
||||
else if (len >= 9 && is_control (accelerator))
|
||||
{
|
||||
accelerator += 9;
|
||||
len -= 9;
|
||||
mods |= META_VIRTUAL_CONTROL_MASK;
|
||||
}
|
||||
else if (len >= 7 && is_shift (accelerator))
|
||||
{
|
||||
accelerator += 7;
|
||||
len -= 7;
|
||||
mods |= META_VIRTUAL_SHIFT_MASK;
|
||||
}
|
||||
else if (len >= 6 && is_shft (accelerator))
|
||||
{
|
||||
accelerator += 6;
|
||||
len -= 6;
|
||||
mods |= META_VIRTUAL_SHIFT_MASK;
|
||||
}
|
||||
else if (len >= 6 && is_ctrl (accelerator))
|
||||
{
|
||||
accelerator += 6;
|
||||
len -= 6;
|
||||
mods |= META_VIRTUAL_CONTROL_MASK;
|
||||
}
|
||||
else if (len >= 6 && is_modx (accelerator))
|
||||
{
|
||||
static const guint mod_vals[] = {
|
||||
META_VIRTUAL_ALT_MASK,
|
||||
META_VIRTUAL_MOD2_MASK,
|
||||
META_VIRTUAL_MOD3_MASK,
|
||||
META_VIRTUAL_MOD4_MASK,
|
||||
META_VIRTUAL_MOD5_MASK,
|
||||
};
|
||||
|
||||
len -= 6;
|
||||
accelerator += 4;
|
||||
mods |= mod_vals[*accelerator - '1'];
|
||||
accelerator += 2;
|
||||
}
|
||||
else if (len >= 5 && is_ctl (accelerator))
|
||||
{
|
||||
accelerator += 5;
|
||||
len -= 5;
|
||||
mods |= META_VIRTUAL_CONTROL_MASK;
|
||||
}
|
||||
else if (len >= 5 && is_alt (accelerator))
|
||||
{
|
||||
accelerator += 5;
|
||||
len -= 5;
|
||||
mods |= META_VIRTUAL_ALT_MASK;
|
||||
}
|
||||
else if (len >= 6 && is_meta (accelerator))
|
||||
{
|
||||
accelerator += 6;
|
||||
len -= 6;
|
||||
mods |= META_VIRTUAL_META_MASK;
|
||||
}
|
||||
else if (len >= 7 && is_hyper (accelerator))
|
||||
{
|
||||
accelerator += 7;
|
||||
len -= 7;
|
||||
mods |= META_VIRTUAL_HYPER_MASK;
|
||||
}
|
||||
else if (len >= 7 && is_super (accelerator))
|
||||
{
|
||||
accelerator += 7;
|
||||
len -= 7;
|
||||
mods |= META_VIRTUAL_SUPER_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
gchar last_ch;
|
||||
|
||||
last_ch = *accelerator;
|
||||
while (last_ch && last_ch != '>')
|
||||
{
|
||||
last_ch = *accelerator;
|
||||
accelerator += 1;
|
||||
len -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (len >= 4 && is_keycode (accelerator))
|
||||
{
|
||||
keycode = strtoul (accelerator, NULL, 16);
|
||||
goto out;
|
||||
}
|
||||
else if (strcmp (accelerator, "Above_Tab") == 0)
|
||||
{
|
||||
keyval = META_KEY_ABOVE_TAB;
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
{
|
||||
keyval = xkb_keysym_from_name (accelerator, XKB_KEYSYM_CASE_INSENSITIVE);
|
||||
if (keyval == XKB_KEY_NoSymbol)
|
||||
{
|
||||
error = TRUE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
accelerator += len;
|
||||
len -= len;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (error)
|
||||
return FALSE;
|
||||
|
||||
if (accelerator_key)
|
||||
*accelerator_key = keyval;
|
||||
if (accelerator_keycode)
|
||||
*accelerator_keycode = keycode;
|
||||
if (accelerator_mods)
|
||||
*accelerator_mods = mods;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_parse_accelerator (const char *accel,
|
||||
unsigned int *keysym,
|
||||
unsigned int *keycode,
|
||||
MetaVirtualModifier *mask)
|
||||
{
|
||||
if (!accel[0] || strcmp (accel, "disabled") == 0)
|
||||
return TRUE;
|
||||
|
||||
return accelerator_parse (accel, keysym, keycode, mask);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_parse_modifier (const char *accel,
|
||||
MetaVirtualModifier *mask)
|
||||
{
|
||||
if (accel == NULL || !accel[0] || strcmp (accel, "disabled") == 0)
|
||||
return TRUE;
|
||||
|
||||
return accelerator_parse (accel, NULL, NULL, mask);
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#ifndef META_ACCEL_PARSE_H
|
||||
#define META_ACCEL_PARSE_H
|
||||
|
||||
#include <glib.h>
|
||||
#include <meta/common.h>
|
||||
|
||||
/* Not a real key symbol but means "key above the tab key"; this is
|
||||
* used as the default keybinding for cycle_group.
|
||||
* 0x2xxxxxxx is a range not used by GDK or X. the remaining digits are
|
||||
* randomly chosen */
|
||||
#define META_KEY_ABOVE_TAB 0x2f7259c9
|
||||
|
||||
gboolean meta_parse_accelerator (const char *accel,
|
||||
unsigned int *keysym,
|
||||
unsigned int *keycode,
|
||||
MetaVirtualModifier *mask);
|
||||
gboolean meta_parse_modifier (const char *accel,
|
||||
MetaVirtualModifier *mask);
|
||||
|
||||
#endif /* META_ACCEL_PARSE_H */
|
@ -318,19 +318,6 @@ window_overlaps_focus_window (MetaWindow *window)
|
||||
&overlap);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
window_place_centered (MetaWindow *window)
|
||||
{
|
||||
MetaWindowType type;
|
||||
|
||||
type = window->type;
|
||||
|
||||
return (type == META_WINDOW_DIALOG ||
|
||||
type == META_WINDOW_MODAL_DIALOG ||
|
||||
type == META_WINDOW_SPLASHSCREEN ||
|
||||
(type == META_WINDOW_NORMAL && meta_prefs_get_center_new_windows ()));
|
||||
}
|
||||
|
||||
static void
|
||||
avoid_being_obscured_as_second_modal_dialog (MetaWindow *window,
|
||||
int *x,
|
||||
@ -750,7 +737,9 @@ meta_window_place (MetaWindow *window,
|
||||
* on the sides of the parent window or something.
|
||||
*/
|
||||
|
||||
if (window_place_centered (window))
|
||||
if (window->type == META_WINDOW_DIALOG ||
|
||||
window->type == META_WINDOW_MODAL_DIALOG ||
|
||||
window->type == META_WINDOW_SPLASHSCREEN)
|
||||
{
|
||||
/* Center on current monitor */
|
||||
int w, h;
|
||||
|
@ -36,7 +36,6 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "keybindings-private.h"
|
||||
#include "meta-accel-parse.h"
|
||||
|
||||
/* If you add a key, it needs updating in init() and in the gsettings
|
||||
* notify listener and of course in the .schemas file.
|
||||
@ -80,7 +79,6 @@ static MetaKeyCombo overlay_key_combo = { 0, 0, 0 };
|
||||
static GDesktopFocusMode focus_mode = G_DESKTOP_FOCUS_MODE_CLICK;
|
||||
static GDesktopFocusNewWindows focus_new_windows = G_DESKTOP_FOCUS_NEW_WINDOWS_SMART;
|
||||
static gboolean raise_on_click = TRUE;
|
||||
static gboolean center_new_windows = FALSE;
|
||||
static gboolean attach_modal_dialogs = FALSE;
|
||||
static char* current_theme = NULL;
|
||||
static int num_workspaces = 4;
|
||||
@ -273,13 +271,6 @@ static MetaBoolPreference preferences_bool[] =
|
||||
},
|
||||
&attach_modal_dialogs,
|
||||
},
|
||||
{
|
||||
{ "center-new-windows",
|
||||
SCHEMA_MUTTER,
|
||||
META_PREF_CENTER_NEW_WINDOWS,
|
||||
},
|
||||
¢er_new_windows,
|
||||
},
|
||||
{
|
||||
{ "raise-on-click",
|
||||
SCHEMA_GENERAL,
|
||||
@ -924,11 +915,8 @@ queue_changed (MetaPreference pref)
|
||||
meta_preference_to_string (pref));
|
||||
|
||||
if (changed_idle == 0)
|
||||
{
|
||||
changed_idle = g_idle_add_full (META_PRIORITY_PREFS_NOTIFY,
|
||||
changed_idle_handler, NULL, NULL);
|
||||
g_source_set_name_by_id (changed_idle, "[mutter] changed_idle_handler");
|
||||
}
|
||||
changed_idle = g_idle_add_full (META_PRIORITY_PREFS_NOTIFY,
|
||||
changed_idle_handler, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -1222,12 +1210,6 @@ meta_prefs_get_focus_new_windows (void)
|
||||
return focus_new_windows;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_prefs_get_center_new_windows (void)
|
||||
{
|
||||
return center_new_windows;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_prefs_get_attach_modal_dialogs (void)
|
||||
{
|
||||
@ -1341,7 +1323,7 @@ mouse_button_mods_handler (GVariant *value,
|
||||
*result = NULL; /* ignored */
|
||||
string_value = g_variant_get_string (value, NULL);
|
||||
|
||||
if (!string_value || !meta_parse_modifier (string_value, &mods))
|
||||
if (!string_value || !meta_ui_parse_modifier (string_value, &mods))
|
||||
{
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"Failed to parse new GSettings value\n");
|
||||
@ -1645,9 +1627,9 @@ overlay_key_handler (GVariant *value,
|
||||
*result = NULL; /* ignored */
|
||||
string_value = g_variant_get_string (value, NULL);
|
||||
|
||||
if (string_value && meta_parse_accelerator (string_value, &combo.keysym,
|
||||
&combo.keycode,
|
||||
&combo.modifiers))
|
||||
if (string_value && meta_ui_parse_accelerator (string_value, &combo.keysym,
|
||||
&combo.keycode,
|
||||
&combo.modifiers))
|
||||
;
|
||||
else
|
||||
{
|
||||
@ -1743,9 +1725,6 @@ meta_preference_to_string (MetaPreference pref)
|
||||
case META_PREF_FOCUS_NEW_WINDOWS:
|
||||
return "FOCUS_NEW_WINDOWS";
|
||||
|
||||
case META_PREF_CENTER_NEW_WINDOWS:
|
||||
return "CENTER_NEW_WINDOWS";
|
||||
|
||||
case META_PREF_ATTACH_MODAL_DIALOGS:
|
||||
return "ATTACH_MODAL_DIALOGS";
|
||||
|
||||
@ -1908,7 +1887,7 @@ update_binding (MetaKeyPref *binding,
|
||||
keycode = 0;
|
||||
mods = 0;
|
||||
|
||||
if (!meta_parse_accelerator (strokes[i], &keysym, &keycode, &mods))
|
||||
if (!meta_ui_parse_accelerator (strokes[i], &keysym, &keycode, &mods))
|
||||
{
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"Failed to parse new GSettings value\n");
|
||||
|
@ -79,6 +79,7 @@ struct _MetaScreen
|
||||
MetaStack *stack;
|
||||
MetaStackTracker *stack_tracker;
|
||||
|
||||
MetaCursorTracker *cursor_tracker;
|
||||
MetaCursor current_cursor;
|
||||
|
||||
Window wm_sn_selection_window;
|
||||
@ -112,6 +113,7 @@ struct _MetaScreen
|
||||
guint workspace_layout_overridden : 1;
|
||||
|
||||
guint keys_grabbed : 1;
|
||||
guint all_keys_grabbed : 1;
|
||||
|
||||
int closing;
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user